2013-04-01 72 views
0

我想在Scala中使用我從書中複製過來的簡單語法中的解析器組合器。當我運行下面的代碼停止後的第一個標記已經被解析與錯誤解析器組合器 - 簡單語法

[1.3] failure: string matching regex '\z' expected but '+' found

我明白爲什麼出問題。第一個標記是一個表達式,因此它是唯一需要根據語法進行分析的東西。但我不知道什麼是解決問題的好方法。

object SimpleParser extends RegexParsers 
{ 
    def Name = """[a-zA-Z]+""".r 
    def Int = """[0-9]+""".r 

    def Main:Parser[Any] = Expr 
    def Expr:Parser[Any] = 
    (
      Term 
     | Term <~ "+" ~> Expr 
     | Term <~ "-" ~> Expr 
    ) 

    def Term:Parser[Any] = 
    (
      Factor 
     | Factor <~ "*" ~> Term 
    ) 

    def Factor:Parser[Any] = 
    (
      Name 
     | Int 
     | "-" ~> Int 
     | "(" ~> Expr <~ ")" 
     | "let" ~> Name <~ "=" ~> Expr <~ "in" ~> Expr <~ "end" 
    ) 

    def main(args: Array[String]) 
    { 
     var input = "2 + 2" 
     println(input) 
     println(parseAll(Main, input)) 
    } 
} 

回答

1

Factor <~ "*" ~> Term意味着Factor.<~("*" ~> Term),所以整個右半部分被丟棄。 使用Factor ~ "*" ~ Term ^^ { case f ~ _ ~ t => ??? }rep1sep

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

import scala.util.parsing.combinator.RegexParsers 

object SimpleParser extends RegexParsers 
{ 
    def Name = """[a-zA-Z]+""".r 
    def Int = """[0-9]+""".r 

    def Main:Parser[Any] = Expr 
    def Expr:Parser[Any] = rep1sep(Term, "+" | "-") 

    def Term:Parser[Any] = rep1sep(Factor, "*") 

    def Factor:Parser[Any] = 
    (
      "let" ~> Name ~ "=" ~ Expr ~ "in" ~ Expr <~ "end" ^^ { case n ~ _ ~ e1 ~ _ ~ e2 => (n, e1, e2) 
     | Int 
     | "-" ~> Int 
     | "(" ~> Expr <~ ")" 
     | Name } 
    ) 
} 

SimpleParser.parseAll(SimpleParser.Main, "2 + 2") 

// Exiting paste mode, now interpreting. 

import scala.util.parsing.combinator.RegexParsers 
defined module SimpleParser 
res1: SimpleParser.ParseResult[Any] = [1.6] parsed: List(List(2), List(2)) 

分析器的第二部分def Term:Parser[Any] = Factor | Factor <~ "*" ~> Term是無用的。第一部分Factor可以解析第二部分Factor <~ "*" ~> Term能夠解析的任何Input(非空的next)。

+0

謝謝!我可以理解我以錯誤的方式使用<~ and ~>。但我不明白爲什麼有必要使用rep1sep。以前的方式有什麼問題? –

+0

'rep1sep'只是更短。 – senia

+0

你可以用'def Term:Parser [Any] = Factor〜「*」〜Term ^^ {case f〜_〜t =>替換'def Term:Parser [Any] = rep1sep(Factor,「*」)'' (f,t)} | Factor'。 – senia