1
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 が名前を挿入できず、 name が に入り、function_callname が試行され、 funciton 呼び出しに入るからです。そのような状況をどのように解決しますか?

名前を単純な識別子に減らす解決策がありました

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

name ::= identifier | function_callしかし、VHDL 仕様で BNF 化されており、function_callおそらく他の場所で共有されているため、これを行うことは好みません。ここで見つかった左再帰の消去は、同じ理由で望ましくありません

def name: Parser[_] = "a" ~ rep("a" | "1") ~ pared_name
def pared_name: Parser[_] = "(" ~> name <~ ")" | ""

ところで、私がエラーを修正した場合、name.parseAllは名前ルールの最初の代替としてのみ「aaa」を消費するのか、それとも「aaa(1)」全体を取るのでしょうか? aaa だけを消費する前に、aaa(1) 全体を消費するように名前を付けるにはどうすればよいですか? function_call を名前の最初の選択肢に入れる必要があると思いますが、この場合、スタックオーバーフローがさらに熱心になりますか?

4

1 に答える 1

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)
    ^
于 2015-12-30T02:37:41.907 に答える