Bison中%nonassoc与%token的区别及适用场景咨询
%nonassoc 和 %token 在 Bison 中的核心区别
基础定义
%token仅用于声明终结符,告诉 Bison 某个符号属于语法中的终结符,不涉及任何优先级或结合性规则。%nonassoc用于给终结符指定无结合性,同时可设置优先级。当相同优先级的该终结符连续出现,或语法规则因无结合性产生歧义时,Bison 会直接判定为语法错误,拒绝该结构。
什么时候用 %token?
当你只需要定义一个终结符,不需要为它设置优先级或结合性时使用。比如单纯的标识符、关键字:
%token IDENTIFIER IF ELSE RETURN
这里仅告知 Bison 这些符号是语法的组成部分,它们之间不存在优先级/结合性的需求,或优先级由其他语法规则间接处理。
什么时候用 %nonassoc?
当你需要禁止某个运算符的连续使用,或明确该运算符不允许左/右结合时使用。最典型的场景是无意义的连续比较——多数语言中,a == b == c 这类写法逻辑模糊,应直接禁止。
示例:禁止连续比较
假设我们要定义一个语法,不允许连续的相等/不等比较:
%nonassoc EQ NEQ // 给==和!=设置无结合性 %left PLUS MINUS %left MUL DIV %% expr: expr PLUS expr | expr MINUS expr | expr MUL expr | expr DIV expr | expr EQ expr // 允许单个==比较 | expr NEQ expr | NUMBER | IDENTIFIER ; %%
当输入1 == 2 == 3时,Bison 会直接报错——因为EQ是%nonassoc,连续两个相同优先级的EQ出现时,没有结合性规则可以消解歧义,因此判定为语法错误。
如果把%nonassoc EQ NEQ换成%token EQ NEQ,Bison 会因歧义报错(无法判断是先算(1==2)==3还是1==(2==3)),而非直接禁止这种写法。若你的语言逻辑就是不允许连续比较,%nonassoc才是正确选择。
总结
- 用
%token:仅声明终结符,不涉及优先级/结合性处理。 - 用
%nonassoc:需要禁止该终结符连续使用,或明确其无结合性,遇到歧义直接报错而非消解。
内容的提问来源于stack exchange,提问作者user19474160
相关产品推荐
相关产品推荐

