c++ - 错误时会发生什么 - Bison

标签 c++ bison flex-lexer

想象一下这个语法:

declaration
    : declaration_specifiers ';' { /* allocate AST Node and return (1) */}
    | declaration_specifiers init_declarator_list ';' { /* allocate AST Node and return (2)*/}
    ;
init_declarator_list
    : init_declarator { /* alloc AST Node and return (3) */}
    | init_declarator_list ',' init_declarator { /* allocate AST Node and return (4) */}
    ;

现在假设 ',' 标记中存在错误。所以我们到目前为止:

声明 -> declaration_specifiers init_declarator_list -> init_declarator_list ',' /*error*/

这里发生了什么?

bison是否执行(4)代码?和(2)?如果 bison 不执行 (4) 但执行 (2) $3 值是多少?如何为 $variables 设置默认值?

如何正确删除错误生成的 AST?

最佳答案

bison 仅在 Action 的产生式减少时执行 Action ,这意味着它必须与输入完全匹配,除非它是一个错误产生式,在这种情况下使用宽松的匹配形式。 (见下文。)所以您可以放心,如果执行了一个 Action ,那么与其终结符和非终结符关联的各种语义值就是词法分析器或它们各自 Action 的结果。

然而,在错误恢复期间,bison 会自动从堆栈中丢弃语义值。使用相当新的 bison 版本,您可以使用 %destructor 声明指定在丢弃值时要执行的操作。 (有关详细信息,请参阅 bison manual。)您可以按类型或按符号(或两者都指定析构函数,但每个符号的析构函数优先。)

%destructor 操作将在 bison 丢弃 语义值时运行。粗略地说,丢弃语义值意味着您的程序永远没有机会处理语义值。它不适用于在减少生产时从堆栈中弹出的值,即使没有与减少相关的明确操作。 “丢弃”的完整定义在前面引用的 Bison 手册部分的末尾。

如果没有错误产生,除了丢弃整个堆栈和任何先行符号(bison 会自动执行)然后终止解析之外,错误恢复的方式实际上没有太多可能。您可以通过在语法中添加错误产生式来做得更好。错误产生式包括特殊标记 error;在没有其他可能匹配的情况下,此标记精确匹配空序列。与正常产品不同,错误产品不需要立即可见; bison 将从堆栈中丢弃状态(和相应的值),直到它找到具有错误 转换的状态,或者它到达堆栈的末尾。此外,错误生成中 error 之后的终端不需要是先行标记; bison 将丢弃先行标记(和相应的值),直到它能够继续产生错误(或到达输入末尾)。查看handy manual有关该过程的详细描述(或者如果附近有拷贝,请阅读 Dragon book)。

关于c++ - 错误时会发生什么 - Bison,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22695192/

相关文章:

bison - 改革语法以消除移位减少 if-then-else 中的冲突

使用flex的C编译器

indentation - 如何使用 flex/bison 进行类似 python 的缩进

c++ - 在不同的线程中调用 vector 析构函数或清除

c++ - 在循环中创建对象并将其添加到 vector 时,总是添加相同的对象

c++ - 简单的 Flex/Bison C++

c++ - Flex 和 Bison 工具

c++ - 如何使用模板函数进行隐式转换

c++ - 当我通过删除临时节点来释放内存时,我遇到了读取访问冲突。但只有当我返回虚假陈述时

c - 可重入 Flex 和 Bison 的问题