为了简化原始问题,假设我想解析一串左右括号。 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 =>失败)。我不认为这是可能的。
如果您有任何见解,请回复,并感谢您的帮助!
答案 0 :(得分:1)
一个简单的解决方案:
completedparse: pair {printf("Success!\n");}
| pair error
;
error
伪终端不匹配所有错误,但它会匹配预期有EOF且找到其他错误的错误。如果在某些其他上下文中遇到错误,则错误生成不会适用。通常,您应该使用yyerror
对语法错误执行操作;上面的规则只是一种避免在输入结尾处有垃圾的情况下调用completedparse
动作的方法。
顺便说一下,你的语法与(())()
不匹配。您可能想要使用:
pair: /* EMPTY */
| '(' pair ')' pair
;
<强>此外:强>
回应评论中的附录:
您可以在错误生成中使用操作{ YYABORT }
以便立即返回(返回值为1,表示语法错误)。如果要打印一般错误消息,最好在yyerror
实现中这样做,因为任何语法错误都会调用它,而error
生成只会在某些情况下减少错误。您可以使用error
制作来生成更具体的错误消息,但这需要做更多的工作。
您无法自定义$accept
伪生产。但是,上述技术或多或少是等效的。
您无法更改yyparse
的返回类型或值(0成功,1语法错误,2分配错误)。但是,从解析中返回更多数据(例如,AST)通常很有用。 &#34;传统&#34;解决方案是只使用全局变量,但对于我们这些对全局变量有厌恶的人,另一种解决方案是使用[%parse-param][1]
声明来添加一个或多个其他参数;通常,您的开始生产将设置这些参数指向的对象的值。如果你这样做,你应该在依赖额外的返回信息之前检查yyparse
的返回值,这完全是因为即使出现错误也可以评估开始生产。