如何在Bison中到达文件末尾时才打印语句?

时间:2014-04-13 23:06:56

标签: bison flex-lexer

为了简化原始问题,假设我想解析一串左右括号。 flex文件将具有令牌

"(" return LPAREN
")" return RPAREN

并且野牛文件将有制作

completedparse: pair {printf("Success!\n");}
;
pair: LPAREN pair RPAREN
    | LPAREN RPAREN pair
    | LPAREN RPAREN
;

如果给出字符串“(()()(()))”或“()()(())”它会成功。

我遇到的问题是“(()()))”会在失败之前立即打印成功声明。我知道野牛创造了生产

$accept: completedparse $end

这是野牛如何接受或拒绝该字符串。如果我可以编写自己的$ accept产品并在该产品中包含任何打印语句,那么我的所有问题都会消失。但是根据3.0.2手册中的$ accept不能用于语法。

如果我可以修改yyparse()的返回值,我的问题也会消失(假设我需要的信息不仅仅是0 =>成功,1 =>失败)。我不认为这是可能的。

如果您有任何见解,请回复,并感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

一个简单的解决方案:

completedparse: pair {printf("Success!\n");} 
              | pair error
              ;

error伪终端不匹配所有错误,但它会匹配预期有EOF且找到其他错误的错误。如果在某些其他上下文中遇到错误,则错误生成不会适用。通常,您应该使用yyerror对语法错误执行操作;上面的规则只是一种避免在输入结尾处有垃圾的情况下调用completedparse动作的方法。

顺便说一下,你的语法与(())()不匹配。您可能想要使用:

pair:         /* EMPTY */
    |         '(' pair ')' pair
    ;

<强>此外:

回应评论中的附录:

  1. 您可以在错误生成中使用操作{ YYABORT }以便立即返回(返回值为1,表示语法错误)。如果要打印一般错误消息,最好在yyerror实现中这样做,因为任何语法错误都会调用它,而error生成只会在某些情况下减少错误。您可以使用error制作来生成更具体的错误消息,但这需要做更多的工作。

  2. 您无法自定义$accept伪生产。但是,上述技术或多或少是等效的。

  3. 您无法更改yyparse的返回类型或值(0成功,1语法错误,2分配错误)。但是,从解析中返回更多数据(例如,AST)通常很有用。 &#34;传统&#34;解决方案是只使用全局变量,但对于我们这些对全局变量有厌恶的人,另一种解决方案是使用[%parse-param][1]声明来添加一个或多个其他参数;通常,您的开始生产将设置这些参数指向的对象的值。如果你这样做,你应该在依赖额外的返回信息之前检查yyparse的返回值,这完全是因为即使出现错误也可以评估开始生产。