为什么这些野牛规则没用?

问题描述

我正在尝试使用 flex 和 bison 创建一个简单的编译器,但是我写下的所有规则都证明是无用的“14 个无用的非终结符和 66 个无用的规则”。什么使规则无用,有没有办法修复它?

File: Decl_Class'*' 'EOF'

Decl_Class: CLASS IDENT '(' EXTENDS IDENT ')' '?' {Field'*'}

Field: Variable
      |Constructor
      |Method

Variable: Modifier'*' Expr_type Decl_variables

Decl_variables: Decl_variable
               |Decl_variable ',' Decl_variables

Decl_variable: IDENT
              |IDENT '=' Expr

Constructor: Modifier'*' IDENT '(' Expr_type | VOID ')' IDENT '(' Params '?' ')' {Instructions'*'}

Method: Modifier'*' '(' Expr_type | VOID ')' IDENT '(' Params '?' ')' {Instructions'*'}

Modifier: IDENT

Expr: IDENT

Params: '(' Expr_type ')' IDENT | '(' Expr_type ')' IDENT ',' Params

Expr_type: BOOLEAN | INT | DOUBLE | IDENT | INTEGER | REAL | TRU | FALS 
                   | THIS | NULLVAL
                   | '(' Expr ')'
                   | Access|Access '=' Expr|Access '(' L_Expr '?' ')'
                   | NEW IDENT '(' L_Expr '?' ')'
                   | '+''+'Expr | '-''-'Expr | Expr'+''+' | Expr'-''-'
                   | '!'Expr | '-'Expr | '+'Expr
                   | Expr Operator Expr
                   | '(' Expr_type ')' Expr_type

Operator: "==" | "!=" | "<" | "<=" | ">" | ">=" | "+" | "-" | "*" | "/" | "%" | "&&" | "||"

Access: IDENT | Expr '.' IDENT

L_Expr: Expr | Expr ',' L_Expr

Instruction: ';'
           | Expr';'
           | Expr_type Decl_variables';'
           | IF '(' Expr ')' Instruction
           | IF '(' Expr ')' Instruction ELSE Instruction
           | WHILE '(' Expr ')' Instruction
           | FOR '(' L_Expr '?' ';' Expr '?' ';'  L_Expr '?'')' Instruction
           | FOR '(' Expr ')' Decl_variables ';' Expr '?' ';'  L_Expr '?'')' Instruction { Instructions'*' }
           | RETURN Expr '?'';'

解决方法

Decl_Class: CLASS IDENT '(' EXTENDS IDENT ')' '?' {Field'*'}

这里 {} 里面的部分是一个代码动作(编译时会产生语法错误),而不是对 Field 非终结符的引用。所以 Field 从来没有被实际使用过,它引用的非终端也没有。这就是使它们无用的原因:它们从未被使用过。

PS:在语法的不同地方,您使用 '*''?' 的方式表明其意图可能是分别匹配零个或多个或零或一个项目。请注意,所有 '*''?' 所做的都是将标记与给定值匹配。在 bison 中没有重复某些内容或使其成为可选的语法快捷方式 - 您需要为此定义单独的非终结符。

PPS:在大多数(所有?)具有 ++-- 运算符的语言中,它们由单个标记组成,而不是两个后续的 '+''-' 标记(所以- -x 将是双重否定,只有 --x 之间没有空格的 - 将是减量)。因此,您对自减和自增运算符的规则在这方面是不寻常的。