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

如何仅在Bison中到达文件结尾时打印语句?,bison,flex-lexer,Bison,Flex Lexer,为了简化原始问题,假设我想要解析一个左括号和右括号字符串。flex文件将具有令牌 "(" return LPAREN ")" return RPAREN 而野牛档案会有这些作品 completedparse: pair {printf("Success!\n");} ; pair: LPAREN pair RPAREN | LPAREN RPAREN pair | LPAREN RPAREN ; 如果给定字符串“(())”或“(())”,它将成功 我的问题是“(())”会在失

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

"(" return LPAREN
")" return RPAREN
而野牛档案会有这些作品

completedparse: pair {printf("Success!\n");}
;
pair: LPAREN pair RPAREN
    | LPAREN RPAREN pair
    | LPAREN RPAREN
;
如果给定字符串“(())”或“(())”,它将成功

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

$accept: completedparse $end
这就是bison接受或拒绝字符串的方式。如果我能写我自己的$accept产品,并在该产品中包含任何打印语句,我的所有问题都会消失。但是根据3.0.2手册,语法中不能使用$accept

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

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

一个简单的解决方案:

completedparse: pair {printf("Success!\n");} 
              | pair error
              ;
错误
伪终端不会匹配所有错误,但它将匹配预期EOF和发现其他错误的错误。如果在其他上下文中遇到错误,则不会应用错误产品。一般来说,您应该使用
yyerror
对语法错误执行操作;上述规则只是一种避免在输入末尾有垃圾的情况下调用
completedparse
操作的方法

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

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

针对评论中的增编:

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

  • 您不能自定义
    $accept
    伪产品。然而,上述技术或多或少是等效的

  • 无法更改
    yyparse
    的返回类型或值(0成功,1语法错误,2分配错误)。但是,从解析(例如,AST)返回更多数据通常很有用。“传统”的解决方案是只使用一个全局变量,但对于我们这些不喜欢全局变量的人来说,另一个解决方案是使用
    [%parse param][1]
    声明添加一个或多个附加参数;通常,开始生产将设置这些参数指向的对象的值。如果执行此操作,则在依赖其他返回信息之前,应始终检查
    yyparse
    的返回值,因为即使在出现错误的情况下,也可能会对开始生产进行评估


  • 这个语法与实际作业不接近,我创建的真正语法除了错误问题外是正确的。@CullenS:是的,我想,但如果其他人发现这个问题,我认为值得修复。这个语法与实际作业不接近,我创建的真正语法除了错误问题外是正确的。我知道错误标记,但是如果我包括它,那么yyparse返回的值不是0表示成功,不是1吗?但是,如果我在“pairerror”生成之后放一个print错误语句,那就不会有问题了。需要明确的是,定制$accept生产和/或更改yyparse的返回值是不可能的?顺便说一句,非常感谢你的帮助。非常感谢你的帮助,非常有洞察力。