2012-10-02 2 views
-2

저는 스칼라에서 통역사로 일하고 있으며 변수, 이름 및 업데이트 할 수있는 값을 할당하는 방법을 찾아야합니다. 입력 예는 다음과 같을 수 있습니다.스칼라 인터프리터

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

모든 의견이나 제안은 대단히 감사하겠습니다.

+0

무엇이 문제입니까? – sschaef

답변

1

다음은 스칼라 파서 결합자를 사용하여이를 해결하는 간단한 시작점입니다. 이 코드를 사용하여 실제 필요에 맞게 확장 할 수 있지만 기본 아이디어가 표시되어야합니다.

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''는''pse'' 대신에''p ^^ f''로 쓸 수 있습니다. ''parseAll'은 전체 입력을 구문 분석해야한다면 (이전은 뒤 따르는 문자를 먹지 않습니다), 패턴 일치를 둘러싼 괄호는 불필요합니다.'def' 대신'lazy val'이 더 효율적입니다.'p ^^ (Var (_))'는'p ^^ Var'로만 쓰여질 수 있습니다. 오류시 입력 문자열을 출력하는 대신 오류 메시지를 반환하는 것이 더 현명합니다. 일부 빈 줄은 유창성을 읽기에 좋을 것입니다.> [result] (https : /) /gist.github.com/3826030). – sschaef