使用解析器组合器时堆栈溢出

时间:2015-12-27 21:10:38

标签: scala parsing parser-combinators left-recursion

import scala.util.parsing.combinator._

object ExprParser extends JavaTokenParsers {
    lazy val name: Parser[_] = "a" ~ rep("a" | "1") | function_call
    lazy val function_call = name ~ "(" ~> name <~ ")"
}

无限期地为function_call.parseAll("aaa(1)")重复。显然,这是因为1不能在名称和名称之间输入function_call,它会尝试输入funciton调用的名称。你如何解决这种情况?

有一个将名称缩减为简单标识符的解决方案

def name = rep1("a" | "1") 
def function_call = name ~ "(" ~ (function_call | name) ~ ")"

但我不想这样做,因为name ::= identifier | function_call在VHDL规范中是BNF-ed而function_call可能在其他地方共享。由于同样的原因,左递归消除found here是不合需要的

def name: Parser[_] = "a" ~ rep("a" | "1") ~ pared_name
def pared_name: Parser[_] = "(" ~> name <~ ")" | ""
顺便说一句,我也想知道,如果我修正了这个错误,将会命名.parseAll消费&#34; aaa&#34;仅作为名称规则中的第一选择或采取整体&#34; aaa(1)&#34;?在仅消耗aaa之前,我如何命名以消耗整个aaa(1)?我想我应该把function_call作为名字中的第一个替代品,但在这种情况下它会更加急切地堆叠溢出?

1 个答案:

答案 0 :(得分:1)

一个简单的解决方案是使用packrat解析器:

object ExprParser extends JavaTokenParsers with PackratParsers {
  lazy val name: PackratParser[_] = "a" ~ rep("a" | "1") | function_call
  lazy val function_call: PackratParser[_] = name ~ "(" ~> name <~ ")"
}

输出:

scala> ExprParser.parseAll(ExprParser.function_call, "aaa(1)")
res0: ExprParser.ParseResult[Any] =
[1.5] failure: Base Failure

aaa(1)
    ^