我認爲唯一的方法是直接打開和解析導入的文件。從那裏你可以爲模塊創建一個子表達式樹。例如,如果您已經使用^^
和/或^^^
來返回自己的表達式,那麼您可能不需要手動合併樹,例如,您應該能夠在樹中的正確位置簡單發出相關的表達式類型,例如:
import scala.util.parsing.combinator.syntactical.StandardTokenParsers
import scala.io.Source
object Example {
sealed trait Expr
case class Imports(modules: List[Module]) extends Expr
case class Module(modulePath: String, root: Option[Expr]) extends Expr
case class BracedExpr(x: String, y: String) extends Expr
case class Main(imports: Imports, braced: BracedExpr) extends Expr
class BlahTest extends StandardTokenParsers {
def importExpr: Parser[Module] = "import" ~> "\"" ~> stringLit <~ "\"" ^^ {
case modulePath =>
//you could use something other than `expr` below if you
//wanted to limit the expressions available in modules
//e.g. you could stop one module importing another.
phrase(expr)(new lexical.Scanner(Source.fromFile(modulePath).mkString)) match {
case Success(result, _) =>
Module(modulePath, Some(result))
case failure : NoSuccess =>
//TODO log or act on failure
Module(modulePath, None)
}
}
def prologExprs = rep(importExpr) ^^ {
case modules =>
Imports(modules)
}
def bracedExpr = "{" ~> stringLit ~ "," ~ stringLit <~ "}" ^^ {
case x ~ "," ~ y =>
BracedExpr(x, y)
}
def bodyExprs = bracedExpr
def expr = prologExprs ~ bodyExprs ^^ {
case prolog ~ body =>
Main(prolog, body)
}
}
}
你可以簡單地添加eval
到你的表達特點,實現每個EVAL必要的子類,然後有客人遞歸下降的AST。以這種方式,您不需要手動將表達式樹合併在一起。
啊,謝謝你。我想我可以爲我的案子做這件事。順便說一句,我不認爲你需要importExpr中的轉義引號,是嗎? stringLit是否已經引用了報價? – melston
確實,您不需要importExpr中的轉義引號。 'stringLit'的確包含並放棄了這些。當我寫代碼的時候,道歉很晚。因此,您的'importExpr'可以從下面開始: 'def importExpr:Parser [Module] =「import」〜> stringLit ^^' – adamretter