[英]Useless rules and nonterminals in Bison grammar
I have the following Bison file describing my scripting language grammar: 我有以下Bison文件描述了我的脚本语言语法:
%error-verbose
%{
#include "node.h"
NBlock *programBlock;
#define YYDEBUG 1
extern int yylex();
void yyerror(const char *) { printf("Error: %s\n", s); }
%}
%union {
Node *node;
NBlock *block;
NBody *body;
NHeader *header;
NExpression *expression;
NStatement *statement;
NIdentifier *identifier;
NVariableDeclaration *variableDeclaration;
NDoWhileStatement *doWhileStatement;
NWhileStatement *whileStatement;
NIfStatement *ifStatement;
NForStatement *forStatement;
std::vector<NVariableDeclaration*> *variableDeclarations;
std::vector<NExpression*> *expressions;
std::vector<NStatement*> *statements;
std:string *string;
int token;
}
%token <string> TIDENTIFIER TINTEGER TDOUBLE
%token <token> TCEQ TCNE TCLT TCLE TCGT TCGE TEQUAL
%token <token> TLPAREN TRPAREN TLBRACE TRBRACE TCOMMA TDOT
%token <token> TPLUS TMINUS TMUL TDIV TDO TDOUBLE_TYPE TINT_TYPE
%token <token> TELSE TFOR TIF TSEMICOLON TTHEN TWHILE
%type <expression> expression term factor
%type <block> program body header tail statements
%type <statement> statement forStatement ifStatement doWhileStatement whileStatement variableDeclaration
%type <token> comparison
%type <string> identifier_type
%left TPLUS TMINUS
%left TMUL TDIV
%start program
%%
program: TLBRACE body TRBRACE { printf("Reduce body to program\n"); }
;
body: header TLBRACE block TRBRACE tail { printf("Reduce header block tail to body\n"); }
;
header: TLBRACE variableDeclarations TRBRACE { printf("Reduce variableDeclarations to header\n"); }
| TLBRACE TRBRACE { printf("Reduce empty to header\n"); }
;
variableDeclarations: variableDeclaration TSEMICOLON { printf("Reduce variable declaration to header\n"); }
| variableDeclarations variableDeclaration TSEMICOLON { printf("Reduce variable declaration list to header\n"); }
;
tail: TLBRACE statements TRBRACE { printf("reduce statement list to tail\n"); }
| TLBRACE TRBRACE { printf("Reduce empty to tal\n"); }
;
statements: statement TSEMICOLON { printf("Reduce statement to statement list\n"); }
| statements statement TSEMICOLON { printf("Reduce statement list to statement list\n"); }
;
statement: ifStatement { printf("Reduce if to statement\n"); };
| forStatement { printf("Reduce for to statement\n"); };
| doWhileStatement { printf("Reduce doWhile to statement\n"); };
| whileStatement { printf("reduce while to statement\n"); }
| expression { printf("Reduce expression to statement\n"); };
;
forStatement: TFOR TLPAREN expression TSEMICOLON expression TSEMICOLON expression TRPAREN block { printf("Reduce for to for statement\n"); }
;
ifStatement: TIF expression TTHEN block { printf("Reduce if to if statement\n"); }
| TIF expression block TELSE block { printf("Reduce ifelse to if statement\n"); }
;
doWhileStatement: TDO block TWHILE expression { printf("reduce dowhile to while statement\n"); }
;
whileStatement: TWHILE block expression { printf("Reduce while to while statement\n"); }
;
block: TLBRACE statements TRBRACE { printf("Reduce statement list to block\n"); }
| TLBRACE TRBRACE { printf("Reduce empty to block\n"); }
;
variableDeclaration: identifier_type TIDENTIFIER { printf("reduce uninitialized identifier to variable declaration\n"); }
| identifier_type TIDENTIFIER TEQUAL expression { printf("Reduce initialized identifier to variable declaration\n"); }
;
identifier_type: TINT_TYPE { printf("Reduce int to identifier type\n"); }
| TDOUBLE_TYPE { printf("Reduce double to identifier type\n"); }
| { printf("Reduce empty to identifier type\n"); }
;
expression: TIDENTIFIER TEQUAL expression { printf("Reduce assignment to expression\n"); }
| TIDENTIFIER { printf("reduce identifier to expression\n"); }
| expression comparison expression { printf("Reduce comparison to expression\n"); }
| TLPAREN expression TRPAREN { printf("Reduce nested expression to expression\n"); }
| expression TPLUS term { printf("Reduce addition to expression\n"); }
| expression TMINUS term { printf("Reduce subtraction to expression\n"); }
| term { printf("Reduce term to expresson\n"); }
| factor { printf("Reduce factor to expression\n"); }
;
term: term TMUL factor { printf("Reduce multiplication to term\n"); }
| term TDIV factor { printf("Reduce division to term\n"); }
;
factor: TIDENTIFIER { printf("Reduce identifier to factor\n"); }
| TINTEGER { printf("Reduce integer to numeric\n"); }
| TDOUBLE { printf("Reduce double to numeric\n"); }
;
comparison: TCEQ { printf("Reduce eq to comparison\n"); }
| TCNE { printf("Reduce ne to comparison\n"); }
| TCLT { printf("Reduce lt to comparison\n"); }
| TCLE { printf("Reduce le to comparison\n"); }
| TCGT { printf("reduce gt to comparison\n"); }
| TCGE { printf("Reduce ge to comparison\n"); }
| TPLUS { printf("Reduce plus to comparison\n"); }
| TMINUS { printf("Reduce minus to comparison\n"); }
| TMUL { printf("Reduce mul to comparison\n"); }
| TDIV { printf("Reduce div to comparison\n"); }
;
I really don't understand why I am getting errors related to useless nonterminals and useless rules. 我真的不明白为什么我会收到与无用的非终结符和无用的规则有关的错误。
Running the command: 运行命令:
bison -d -o parser.cpp parser.y
I get the following errors: 我收到以下错误:
$ bison -d -o parser.cpp parser.y
parser.y: attention: 1 nonterminal useless in grammar
parser.y: attention: 5 rules useless in grammar
parser.y:52.31-34: attention: nonterminal useless in grammar: term
parser.y:135.51-118: attention: rule useless in grammar: expression: expression TPLUS term
parser.y:136.51-123: attention: rule useless in grammar: expression: expression TMINUS term
parser.y:137.51-96: attention: rule useless in grammar: expression: term
parser.y:141.41-103: attention: rule useless in grammar: term: term TMUL factor
parser.y:142.51-107: attention: rule useless in grammar: term: term TDIV factor
parser.y: conflicts: 20 shift/reduce, 14 reduce/reduce
parser.y:145.41-96: attention: rule useless in parser due to conflicts: factor: TIDENTIFIER
I think the conflict is that the parser will not know which rule to chose when it finds a TIDENTIFIER. 我认为冲突是解析器在找到TIDENTIFIER时将不知道选择哪个规则。 The reason is that
原因是
TIDENTIFIER
can be reduced to expression
TIDENTIFIER
可以简化为expression
factor
can be reduced to expression
factor
可以简化为expression
TIDENTIFIER
can be reduced to factor
TIDENTIFIER
可降至factor
So when the parser get an identifier it can go two ways to reach an expression. 因此,当解析器获得标识符时,它可以通过两种方式到达表达式。
TIDENTIFIER -> expression
TIDENTIFIER -> factor -> expression
I thin in your case you can safely remove TIDENTIFIER
from factor since factor
is reduced to ONLY expression
anyway. 我薄你的情况,你可以安全地删除
TIDENTIFIER
从因素,因为factor
被减少到只有 expression
反正。
However a more proper way (at least for most common languages) might be to keep TIDENTIFIER
in factor
and handle the rest in statement
. 但是,更合适的方法(至少对于大多数通用语言而言)可能是让
TIDENTIFIER
成为factor
并在statement
处理其余的factor
。 For example TIDENTIFIER ASSIGN expression
can be a valid statement
. 例如,
TIDENTIFIER ASSIGN expression
可以是有效statement
。
BTW your statement
includes expression
. 顺便说一句,您的
statement
包括expression
。 Which is proably not what you intended. 可能不是您的预期。
statement
should always be different from expression
(after all that's why you need two rules). statement
应始终与expression
不同(毕竟这就是为什么需要两个规则的原因)。
I think you should check for cases like that. 我认为您应该检查类似的情况。 If you have a rule using another rule only (without any other tokens or other rules) then it is probably wrong.
如果您有一个仅使用其他规则的规则(没有任何其他标记或其他规则),则可能是错误的。 Wrong in a sense that it is not what you intended .
从某种意义上说这不是您想要的,这是错误的 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.