Parsing 在Erlang中使用yecc分析错误:";“之前的语法错误”;
我目前正在用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 -> '{' '
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}
标记。您可以显示针对不同情况从标记器获得的标记吗?它是试图理解解析器的最重要输入。