在 yacc/bison 语法中,是否有办法从中间规则操作中完全丢弃规则,但没有错误(以及对 yyerror 的调用),以便其他选项仍然有效(类似于 'reject'柔性)?
假设 'num' 有一个整数值,那么下面的规则将为偶数和奇数产生式定义不同的语法
rule : num { if (($1 & 1) == 1) reject; } a b c
| num { if (($1 & 1) == 0) reject; } d e ;
谢谢
在 yacc/bison 语法中,是否有办法从中间规则操作中完全丢弃规则,但没有错误(以及对 yyerror 的调用),以便其他选项仍然有效(类似于 'reject'柔性)?
假设 'num' 有一个整数值,那么下面的规则将为偶数和奇数产生式定义不同的语法
rule : num { if (($1 & 1) == 1) reject; } a b c
| num { if (($1 & 1) == 0) reject; } d e ;
谢谢
与 flex 不同,Yacc 不进行任何类型的回溯,因此在运行时没有其他选项——要么规则运行正确,要么出现错误。您可以使用YYREJECT
宏完全退出解析器(从 1 返回yyparse
),但这可能不是您想要的。
如果你要使用btyaccYYERROR
(它支持回溯),你可以通过调用一个试探性的动作来做你想做的事。这将导致它回溯并尝试不同的替代方案,并且只有在没有替代方案时才会实际给出语法错误。
您可以使用中间规则操作将令牌推送到解析堆栈,然后可以通过另一个规则对其进行评估,这将使您能够对解析结果进行编程选择。
http://www.gnu.org/software/bison/manual/html_node/Mid_002dRule-Actions.html
中间规则操作本身算作规则的组成部分之一。当同一规则后面有另一个动作时(通常最后有另一个动作),这会有所不同:在计算出在 $n 中使用哪个数字 n 时,您必须计算这些动作以及符号。
中间规则动作也可以具有语义值。该操作可以通过对 $$ 的赋值来设置其值,并且规则中稍后的操作可以使用 $n 引用该值。由于没有符号来命名动作,所以没有办法提前为值声明数据类型,所以每次引用都必须使用'$<...>n'构造来指定数据类型这个值。
因此,可能可以这样做,但与 flex 中的方式不同。这样做可能有点骇人听闻,因为您实际上所做的是破坏语法的上下文无关性质。