我正在尝试使用 Yecc 编写 Erlang 解析器,但我在语义规则的优先级方面遇到了一些麻烦。在我的例子中,我定义了语法、终端和非终端符号、规则和相关代码。
这是我为测试而写的。
%Grammar non terminals
Nonterminals product require require1 mandatory mandatory1.
%Grammar terminals
Terminals 'tick' 'feature' '(' ')' 'req' 'mand' ';' 'nil'.
%Initial symbol
Rootsymbol product.
%Operands priority
Left 200 require.
Left 190 require1.
Left 180 mandatory.
Left 170 mandatory1.
Left 80 'req'.
Left 60 'mand'.
Left 50 ';'. %Secuence
Left 40 'feature'. %Optional feature
%--------------------------------------------------
%Grammar with operational rules
%[req1 & req2]
product -> require: '$1'.
require -> feature req feature '(' feature ';' product ')' : if
'$1' == '$5' -> {'$5', {'$4', '$7', '$8', {mand,1}, '$3'}};
true -> {'$5', {'$1', '$2', '$3', '$4', '$7', '$8'}}
end.
%[req3]
product -> require1 : '$1'.
require1 -> feature req feature '(' tick ')' : {nil,1}.
%[mand2 & mand3]
product -> mandatory : '$1'.
mandatory -> '(' feature ';' product ')' mand feature : if
'$2' == '$7' -> {'$2', {'$4'}};
true -> {'$2',{'$1', '$4', '$5', '$6', '$7'}}
end.
%[mand1]
product -> mandatory1: '$1'.
mandatory1 -> '(' tick ')' mand feature : {$5, {tick,1}}.
%[tick]
product -> feature ';' tick : {'$1', {nil,1}}.
product -> nil.
product -> feature ';' product : {'$1', {'$3'}}.
Erlang code.
%To remove brackets and return only the third parameter, right now is not used.
unwrap_feature({_,_,V}) -> V.
%%How to compile and use
%Save this as stack.yrl
%Run erl and then
%yecc:yecc("stack.yrl","stack.erl").
%c(stack).
现在让我们执行一个特定的术语来检查规则是如何应用的。
stack:parse([{feature,1,'A'},{'req',1},{feature,1,'C'},{'(',1},{feature,1,'A'},{';',1},{feature,1,'B'},{';',1},{feature,1,'C'},{';',1},{tick,1},{')',1}]).
解析器输出为:
{ok,{{feature,1,'A'},
{{'(',1},
{{feature,1,'B'},{{{feature,1,'C'},{nil,1}}}},
{')',1},
{mand,1},
{feature,1,'C'}}}}
但我需要这个。只要解析器处理该术语(如调试输出),我就在编写输出。
初始任期。
{feature,1,'A'},{'req',1},{feature,1,'C'},{'(',1},{feature,1,'A'},{';',1},{feature,1,'B'},{';',1},{feature,1,'C'},{';',1},{tick,1},{')',1}
规则 %[req1 & req2]。(这是正确应用的 - 案例 '$1' == '$5')
{feature,1,'A'},{{'(',1},{feature,1,'B'},{';',1},{feature,1,'C'},{';',1},{tick,1},{')',1},{mand,1},{feature,1,'C'}}
现在,我不知道会发生什么,但输出应该是这样的。
规则 %[mand2 & mand3]。(情况属实)
{feature,1,'A'},{{feature,1,'B'},{{'(',1},{feature,1,'C'},{';',1},{tick,1},{')',1},{mand,1},{feature,1,'C'}}}
规则 %[mand2 & mand3]。(案例 '$2' == '$7')
{feature,1,'A'},{{feature,1,'B'},{{feature,1,'C'},{{tick,1}}}}
规则 %[tick] – 最终结果。
{feature,1,'A'},{{feature,1,'B'},{{feature,1,'C'},{{{tick,1},{nil,1}}}}}
我已经尝试过了:
正如 Yecc 手册中所解释的,我能够做到这一点:
- 使用运算符优先级。
- 将优先级应用于规则。从文档中(也可以声明非终端的优先级,“上一级”。这在运算符重载时很实用(另请参见下面的示例 3))。
但这似乎对我不起作用。有什么帮助???
谢谢!