我认为我的语法是一个简单的部分,这是从yacc得到错误。我知道我需要在某处添加%prec,但不确定在哪里。
Assignment : Ref '=' Ref
| Ref '=' Expression
| Ref '=' Value
| Ref '=' FunctionCall
;
Ref : ID
| ID '[' Expression ']'
;
Value : INT
| BOOLEAN
| CHAR
| STRING
;
我得到的错误是:
warning: rule never reduced because of conflicts: Assignment: Ref '=' Ref
warning: rule never reduced because of conflicts: Assignment: Ref '=' Value
因此ID只是一个变量名,而Ref是对变量的引用。
答案 0 :(得分:1)
嗯,不确定,FunctionCall,Value和Ref也是Expressions吗?也许如果删除Expression时它可以工作,那么可能会建议Expression包含其中一个......
答案 1 :(得分:1)
Assignment : Ref '=' Ref
Ref = Ref = Ref
的问题不明确(您可能已经知道);尝试使用%right
关键字定义'='标记(假设您希望“=”为右关联):
%right '='
对于Assignment: Ref '=' Value
,我必须看到ID
和各种Value
主体的定义,但将'='定义为右关联可能就足够了。
答案 2 :(得分:1)
我们确实需要看到FunctionCall和(特别是)Expression的定义来给出明确的答案,但我的猜测是Expression可以是单个Ref或Value。在这种情况下,它表示它不知道(肯定)是否直接将赋值右侧的Ref / Value解析为自身,或者作为简单表达式。
令人惊讶的是,FunctionCall没有产生类似的歧义 - 这往往表明你对Expression的定义可能是奇怪的,至少接近有缺陷。
如果我这样做,我可能会将Assignment的定义更改为:
%left '-' '+'
%left '*' '/'
%%
Assignment: Ref '=' Expression;
Expression: Value
| FunctionCall
| Ref
| Expression '+' Expression
| Expression '-' Expression
| Expression '/' Expression
| Expression '*' Expression
| '(' Expression ')'
;
当然,您可能希望支持更多的运营商而不是基本的运营商,但很难猜测 - 我只是试图投入足够的话来提供至少一个合理的想法。
在任何情况下,使用这种结构毫无疑问,赋值的右侧有是一个表达式,而表达式可以包含你列出的三个基本项,结合任意算术运算符,如:
x[i] = a[2] + 1 + f(3)
必须(逐步):
Ref = Expression
Ref = Expression '+' Expression
Ref = Expression '+' Expression '+' Expression
Ref = Ref '+' Value '+' FunctionCall
ID '[' ID ']' '=' ID '[' Value ']' '+' Value '+' FunctionCall
(并且FunctionCall可能会进一步减少到:ID '(' Value ')'
结论:至少这部分语法基本上不受S / R冲突的影响 - 从顶级Assignment
到特定任务的单个令牌,有一条明确,明确的路径。这也有助于减少用户的混淆,因为所有表达式都具有相同的语法。
答案 3 :(得分:0)
似乎解析器无法区分语法中的各种Assignment
字符串(相当严格)的预测限制。
如果ID
和Value
制作很容易解析,我认为你不会遇到这个问题。你很可能将所有Assignment
个产品组合成一个,这至少可以更容易地减少这一个规则并使问题更加明显。