我目前正在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"]}
答案 0 :(得分:1)
在语法规则中,您显示的是终端令牌的类别,不其值。因此,您可以匹配原子,但不能与特定原子匹配。如果您使用的是Erlang标记生成器,则为"if0"
生成的标记将为{atom,Line,if0}
,而在您的语法中,您需要{if0,Line}
标记。这就是"预处理" yecc
文档的部分试图解释。
您需要一个特殊的标记器。如果要使用Erlang标记生成器,处理此方法的一种简单方法是使用预处理过程来扫描标记列表并将{atom,Line,if0}
标记转换为{if0,Line}
标记。