【问题标题】:Yacc "rule useless due to conflicts"Yacc“规则因冲突而无用”
【发布时间】:2011-04-11 00:31:36
【问题描述】:

我需要一些有关 yacc 的帮助。 我正在研究中缀/后缀翻译器,中缀到后缀部分非常简单,但我在后缀到中缀翻译时遇到了一些问题。 这是我将要做什么的一个例子(只是为了翻译一个简单的 ab+c- 或 abc+-)

exp: num {printf("+ ");} exp '+' 
   | num {printf("- ");} exp '-'
   | exp {printf("+ ");} num '+' 
   | exp {printf("- ");} num '-'    
   |/* empty*/
   ;

num: number {printf("%d ", $1);}
   ;

显然它不起作用,因为我在实际正文之前要求一个动作(使用 printfs)所以,在编译时,我得到了很多

警告:由于冲突,规则在解析器中无用

问题是 printfs 正是我需要它们的地方(或者我的输出不会是中缀表达式)。有没有办法将打印操作保留在那里并让 yacc 确定它需要使用哪个?

【问题讨论】:

    标签: yacc


    【解决方案1】:

    基本上,没有。问题是要解决你所拥有的问题,yacc 必须有无限量的前瞻。这是……有问题的,因为 yacc 是一个相当简单的工具,所以它需要一个(错误的)猜测并抛出一些带有警告的规则。您需要更改您的语法,以便 yacc 可以决定如何处理只需要非常少量的前瞻(单个令牌 IIRC)的令牌。执行此操作的常用方法是将值的解释附加到标记上,然后使用后操作,或者更实际地,构建一个您作为单独步骤遍历的树(从其语法中打印出中缀表达式树是微不足道的)。

    请注意,当您收到来自 yacc 的警告时,这通常意味着您的语法错误并且生成的解析器会做出非常意想不到的事情。完善它,直到你从那个阶段得到 no 警告。即,将语法警告视为错误;否则你会后悔的。

    【讨论】:

    • 在我看来,yacc 作为一个“相当简单的工具”是一件好事。这意味着您可以按预期使用它;过于复杂的工具会带来更多麻烦,甚至更多!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-04
    • 1970-01-01
    • 2011-04-17
    相关资源
    最近更新 更多