我不知道这些信息是否与问题相关,但我正在学习Scala解析器组合器。 使用一些例子(在这个master thesis中)我能够编写一个简单的函数(在某种意义上说它是非命令性的)编程语言。
有没有办法改进我的解析器/评估器,以便它可以允许/评估这样的输入:
<%
import scala.<some package / classes>
import weka.<some package / classes>
%>
some DSL code (lambda calculus)
<%
System.out.println("asdasd");
J48 j48 = new J48();
%>
作为以客户语言(DSL)编写的输入?
我应该使用反射或类似的*来评估此类输入吗? 是否有一些源代码建议要研究(可能是常规来源?)?
也许这类似于runtime compilation,但我不确定这是最好的选择。
修改
完全回答“{”和“}”。也许“{{”会更好。
答案 0 :(得分:0)
关于这些进口陈述的含义应该是什么问题。
也许你首先开始允许用你的语言引用java方法(我猜是Lambda微积分?)。
例如:
java.lang.System.out.println "foo"
如果你有,那么你可以添加非限定名称的分辨率,如
println "foo"
但是第一个问题出现了:println存在于System.out和System.err中,或者更正确:它是PrintStream的一种方法,System.err和System.out都是PrintStreams。
因此,您需要一些对象,类,类型等概念才能正确执行。
答案 1 :(得分:0)
我设法如何运行我解释的DSL中嵌入的Scala代码。
将DSL变量插入Scala代码并恢复返回值作为奖励。:)
解析和解释之前的最小相关代码,直到执行嵌入式Scala代码运行时执行(主分析器AST和解释器):
object Main extends App {
val ast = Parser1 parse "some dsl code here"
Interpreter eval ast
}
object Parser1 extends RegexParsers with ImplicitConversions {
import AST._
val separator = ";"
def parse(input: String): Expr = parseAll(program, input).get
type P[+T] = Parser[T]
def program = rep1sep(expr, separator) <~ separator ^^ Sequence
def expr: Parser[Expr] = (assign /*more calls here*/)
def scalacode: P[Expr] = "{" ~> rep(scala_text) <~ "}" ^^ {case l => Scalacode(l.flatten)}
def scala_text = text_no_braces ~ "$" ~ ident ~ text_no_braces ^^ {case a ~ b ~ c ~ d => List(a, b + c, d)}
//more rules here
def assign = ident ~ ("=" ~> atomic_expr) ^^ Assign
//more rules here
def atomic_expr = (
ident ^^ Var
//more calls here
| "(" ~> expr <~ ")"
| scalacode
| failure("expression expected")
)
def text_no_braces = """[a-zA-Z0-9\"\'\+\-\_!@#%\&\(\)\[\]\/\?\:;\.\>\<\,\|= \*\\\n]*""".r //| fail("Scala code expected")
def ident = """[a-zA-Z]+[a-zA-Z0-9]*""".r
}
object AST {
sealed abstract class Expr
// more classes here
case class Scalacode(items: List[String]) extends Expr
case class Literal(v: Any) extends Expr
case class Var(name: String) extends Expr
}
object Interpreter {
import AST._
val env = collection.immutable.Map[VarName, VarValue]()
def run(code: String) = {
val code2 = "val res_1 = (" + code + ")"
interpret.interpret(code2)
val res = interpret.valueOfTerm("res_1")
if (res == None) Literal() else Literal(res.get)
}
class Context(private var env: Environment = initEnv) {
def eval(e: Expr): Any = e match {
case Scalacode(l: List[String]) => {
val r = l map {
x =>
if (x.startsWith("$")) {
eval(Var(x.drop(1)))
} else {
x
}
}
eval(run(r.mkString))
}
case Assign(id, expr) => env += (id -> eval(expr))
//more pattern matching here
case Literal(v) => v
case Var(id) => {
env getOrElse(id, sys.error("Undefined " + id))
}
}
}
}