我正在尝试使用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))
}
}
答案 0 :(得分: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
可以解析(非空next
)第二部分Input
能够解析的任何Factor <~ "*" ~> Term
。