Parsing 在Erlang中使用yecc分析错误:";“之前的语法错误”;

Parsing 在Erlang中使用yecc分析错误:";“之前的语法错误”;,parsing,erlang,Parsing,Erlang,我目前正在用Erlang中的yecc编写解析器 Nonterminals expression. Terminals '{' '}' '+' '*' 'atom' 'app' 'integer' 'if0' 'fun' 'rec'. Rootsymbol expression. expression -> '{' '+' expression expression '}' : {'AddExpression', '$3','$4'}. expression -> '{' '

我目前正在用Erlang中的yecc编写解析器

Nonterminals expression.

Terminals '{' '}'  '+' '*' 'atom' 'app' 'integer' 'if0' 'fun' 'rec'.

Rootsymbol expression.

expression -> '{' '+' expression  expression '}' : {'AddExpression', '$3','$4'}.
expression -> '{' 'if0' expression expression expression '}' : {'if0', '$3', '$4', '$5'}.
expression -> '{' '*' expression expression '}' : {'MultExpression', '$3','$4'}.
expression -> '{' 'app' expression expression '}' : {'AppExpression', '$3','$4'}.
expression -> '{' 'fun' '{' expression '}' expression '}': {'FunExpression', '$4', '$6'}.
expression -> '{' 'rec' '{' expression expression '}' expression '}' : {'RecExpression', '$4', '$5', '$7'}.
expression -> atom : '$1'.
expression -> integer : '$1'.
我还有一个erlang项目,它在解析之前标记输入:

tok(X) ->
element(2, erl_scan:string(X)).

get_Value(X)->
 element(2, parse(tok(X))).
这些情况是可以接受的:

interp:get_Value("{+ {+ 4 6} 6}").
interp:get_Value("{+ 4 2}"). 
这些回报: {'AddExpression'{'AddExpression'{integer,1,6}{integer,1,6}}{integer,1,6}} 和 {'AddExpression'{integer,1,4}{integer,1,2}

但是这个测试用例:

interp:get_Value("{if0 3 4 5}").
返回:

{1,string_parser,["syntax error before: ","if0"]}

在语法规则中,您显示的是终端标记的类别,而不是它们的值。所以你可以匹配一个原子,但不能匹配一个特定的原子。如果您使用的是Erlang标记器,那么为
“if0”
生成的标记将是
{atom,Line,if0}
,而在语法中您需要
{if0,Line}
标记。这就是
yecc
文档的“预处理”部分试图解释的内容


为此,您需要一个特殊的标记器。如果您想使用Erlang标记器,一种简单的处理方法是使用一个预处理过程来扫描标记列表,并将
{atom,Line,if0}
标记转换为
{if0,Line}
标记。

您可以显示针对不同情况从标记器获得的标记吗?它是试图理解解析器的最重要输入。