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))
    }
}
4

1 回答 1

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可以解析(非空nextInput第二部分 ,Factor <~ "*" ~> Term能够解析的任何内容。

于 2013-04-01T07:15:08.047 回答