2010-02-13 66 views
2

我有我认为是我的语法的一个简单部分这是从yacc获取错误。我知道我需要在某处添加%prec,但不确定其中的位置。yacc shift减少问题

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就是一个变量名,编号是一个变量的引用。

+0

'ID'的定义是什么? – outis 2010-02-13 07:30:16

+0

我们几乎肯定需要看到Expression,Value和FunctionCall的定义。表达式可能允许ID(或可能是Ref)作为选项,在这种情况下Ref = Ref规则是冗余w.r.t Ref =表达式。 – 2010-02-13 07:41:33

回答

1

嗯不知道,FunctionCall,Value和Ref也是表达式吗?也许如果它表达式被删除时,它可能暗示表达式包含其中之一...

1

Assignment : Ref '=' Ref的问题是Ref = Ref = Ref是不明确的(其中你可能已经知道);尝试定义“=”使用%right关键字(假设你想“=”是右结合)令牌:

%right '=' 

至于Assignment: Ref '=' Value,我必须看到的定义ID和各种Value虽然将'='定义为正确的联想可能就足够了。

0

看起来解析器不能区分语法中的各种Assignment字符串在其前瞻(相当严格)的限制之内。

如果IDValue制作很容易解析我不认为你会有这个问题。你很可能将所有的产品组合成一个,这样至少可以更容易地减少这个规则并使问题更加明显。

1

我们真的需要查看FunctionCall和(特别是)Expression的定义以给出明确的答案,但我的猜测是Expression可以是单个Ref或Value。在这种情况下,它表示它不知道(当然)是否将分配右侧的Ref/Value直接解析为自身,或者将其解析为简单表达式。

令人惊讶的是,FunctionCall没有产生类似的歧义 - 这往往表明您的表达式的定义可能是奇怪的,至少接近有缺陷。

如果我这样做,我可能会改变分配的定义看起来是这样的:

%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为特定分配单个令牌的明确无误的路径。这也有助于减少用户的混淆,因为所有表达式都具有相同的语法。