2012-10-02 100 views
-2

我正在研究Scala中的解釋器,我需要找到一種方法來分配變量,名稱和可更新的值。示例輸入可能如下所示Scala解釋器

(x = x + 1) // results to: Assign("x",Plus(Var("x"),Num(1))) 

任何想法或建議將不勝感激。

+0

問題是什麼? – sschaef

回答

1

下面是使用Scala的解析器組合器來解決這個問題的一個非常簡單的起點。你可以把這段代碼擴大到適合你的實際需求,但是這應該告訴你基本思想:

trait Expression 
case class Plus(a: Expression, b: Expression) extends Expression 
case class Var(name: String) extends Expression 
case class Num(n: Int) extends Expression 
trait Statement 
case class Assign(v: String, ex: Expression) extends Statement 

object StatementParser extends RegexParsers { 
    private def num: Parser[Num] = regex(new Regex("""(\d+)""")).map(n => Num(n.toInt)) 
    private def identifier: Parser[String] = regex(new Regex("""([A-Za-z][A-Za-z0-9]*)""")) 
    private def variable: Parser[Var] = identifier.map(Var(_)) 
    private def expression: Parser[Expression] = plus | variable | num 
    private def plus: Parser[Plus] = ("(" ~> expression ~ "+" ~ expression <~ ")").map { case (l ~ _ ~ r) => Plus(l, r) } 
    private def assign: Parser[Assign] = (identifier ~ "=" ~ expression).map { case (v ~ _ ~ ex) => Assign(v, ex) } 
    private def parse(str: String): ParseResult[Statement] = parse(assign, str) 
    def apply(str: String): Statement = parse(str) match { 
    case Success(result: Statement, _) => result 
    case _ => sys.error("Could not parse the input string: " + str) 
    } 
} 

val s = StatementParser("x = (x + 1)") 
println(s) // Assign(x,Plus(Var(x),Num(1))) 
+0

'regex(new Regex(「x」))'可以寫成'「x」.r','p map f'可以寫成'p ^^ f',而不是'parse'應該使用如果整個輸入應該被解析(前者不會消耗尾隨字符),那麼不需要使用模式匹配的括號,'lazy val'代替'def'會更有效率,'p ^^(Var(_) )''只能寫成'p ^^ Var',而不是在錯誤時打印輸入字符串,這會更加明智地返回錯誤信息,一些空行對讀取流暢性會很好=> [result](https:/ /gist.github.com/3826030)。 – sschaef