简体   繁体   English

野牛的无用规则

[英]Useless rule in Bison

For some reason bison is rejecting a specific rule, the notequal_expression, beware that Im just starting to learn the whole concept so my line of thought is not so mature, the input file: ( The Error is: "string.y contains 1 useless nonterminal and 1 useless rule." ) 出于某种原因,野牛拒绝了一条特定的规则notequal_expression,请注意,我刚刚开始学习整个概念,因此我的思想还不那么成熟,输入文件:(错误是:“ string.y包含1个无用的非终结符和1条无用的规则。“)

    /* Parser for StringC */

%{

/* ------------------------------------------------------------------
   Initial code (copied verbatim to the output file)
   ------------------------------------------------------------------ */

// Includes
#include <malloc.h>  // _alloca is used by the parser
#include <string.h>  // strcpy

#include "lex.h"     // the lexer

// Some yacc (bison) defines
#define YYDEBUG 1         // Generate debug code; needed for YYERROR_VERBOSE
#define YYERROR_VERBOSE // Give a more specific parse error message 

// Error-reporting function must be defined by the caller
void Error (char *format, ...);

// Forward references
void yyerror (char *msg);

%}

/* ------------------------------------------------------------------
   Yacc declarations
   ------------------------------------------------------------------ */

/* The structure for passing value between lexer and parser */
%union {
   char *str;
}

%token ERROR_TOKEN IF ELSE PRINT INPUT ASSIGN EQUAL NOTEQUAL
%token CONCAT END_STMT OPEN_PAR CLOSE_PAR
%token BEGIN_CS END_CS 
%token <str> ID STRING BOOLEAN

/*%type <type> type simple_type cast*/

%expect 1  /* shift/reduce conflict: dangling ELSE */
           /*    declaration */
%%

/* ------------------------------------------------------------------
   Yacc grammar rules
   ------------------------------------------------------------------ */

program
      : statement_list
        ;

statement_list
      : statement_list statement
      | /* empty */
      ;

statement
      : END_STMT                    {puts ("Empty statement");}
      | expression END_STMT         {puts ("Expression statement");}
      | PRINT expression END_STMT   {puts ("Print statement");}
      | INPUT identifier END_STMT   {puts ("Input statement");}
      | if_statement                {puts ("If statement");}
      | compound_statement          {puts ("Compound statement");}
      | error END_STMT              {puts ("Error statement");}
      | notequal_expression         {puts ("Not equal statement");}
      ;

/* NOTE: This rule causes an unresolvable shift/reduce conflict;
   That's why %expect 1 was added (see above) */
if_statement
      : IF OPEN_PAR expression CLOSE_PAR statement optional_else_statement
      ;

optional_else_statement
      : ELSE statement
      | /* empty */
      ;

compound_statement
      : BEGIN_CS statement_list END_CS
      ;

expression
      : equal_expression
      | OPEN_PAR expression CLOSE_PAR
      ;

equal_expression
      : expression EQUAL assign_expression
      | assign_expression
      ;

notequal_expression
      : expression NOTEQUAL assign_expression 
      | NOTEQUAL assign_expression
      ;

assign_expression
      : identifier ASSIGN assign_expression
      | concat_expression
      ;

concat_expression
      : concat_expression CONCAT simple_expression
      | simple_expression
      ;

simple_expression
      : identifier
      | string
      ;

identifier
      : ID              {}
      ;

string
      : STRING          {}
      ;

bool
      : BOOLEAN          {}
      ;

%%
/* ------------------------------------------------------------------
   Additional code (again copied verbatim to the output file)
   ------------------------------------------------------------------ */

The lexer: 词法分析器:

/* Lexical analyzer for StringC */

%{

/* ------------------------------------------------------------------
   Initial code (copied verbatim to the output file)
   ------------------------------------------------------------------ */

// Includes
#include <string.h>   // strcpy, strncpy
#include <io.h>       // isatty
#ifdef MSVC
#define  isatty _isatty  // for some reason isatty is called _isatty in VC..
#endif

#define  _LEX_CPP_   // make sure our variables get created
#include "lex.h"
#include "lexsymb.h"

extern "C" int yywrap (); // the yywrap function is declared by the caller

// Forward references
void Identifier ();
void StringConstant ();
void BoolConstant ();
void EatComment ();

//// End of inititial code
%}

/* ------------------------------------------------------------------
   Some macros (standard regular expressions)
   ------------------------------------------------------------------ */

LETTER   [a-zA-Z_]
DIGIT    [0-9]
IDENT    {LETTER}({LETTER}|{DIGIT})*
STR      \"[^\"]*\"
BOOL     \(false|true)\
WSPACE   [ \t]+


/* ------------------------------------------------------------------
   The lexer rules
   ------------------------------------------------------------------ */
%%

"if"     {return IF;}
"else"   {return ELSE;}
"print"  {return PRINT;}
"input"  {return INPUT;}
"="      {return ASSIGN;}
"=="     {return EQUAL;}
"!="     {return NOTEQUAL;}                         /* Not equal to */
"+"      {return CONCAT;}
";"      {return END_STMT;}
"("      {return OPEN_PAR;}
")"      {return CLOSE_PAR;}
"{"      {return BEGIN_CS;}
"}"      {return END_CS;}
{BOOL}   {BoolConstant ();   return BOOLEAN;}
{STR}    {StringConstant (); return STRING;}
{IDENT}  {Identifier ();     return ID;}
"//"     {EatComment();}                            /* comment:    skip */
\n       {lineno++;}                                /* newline:    count lines */
{WSPACE} {}                                         /* whitespace: (do nothing) */
.        {return ERROR_TOKEN;}                      /* other char: error, illegal token */

%%

/* ------------------------------------------------------------------
   Additional code (again copied verbatim to the output file)
   ------------------------------------------------------------------ */

// The comment-skipping function: skip to end-of-line
void EatComment()  {
    char c;

   while ((c = yyinput()) != '\n' && c != 0);
    lineno++;
}

// Pass the id name
void Identifier ()  {
   yylval.str = new char[strlen(yytext)+1];
   strcpy (yylval.str, yytext);
}

// Pass the string constant
void StringConstant()  {
   int l = strlen(yytext)-2;
   yylval.str = new char[l+1];
   strncpy (yylval.str, &yytext[1], l); yylval.str[l] = 0;
}


void BoolConstant()    {
    int l = strlen(yytext)-2;
    yylval.str = new char[l+1];
    strncpy(yylval.str, &yytext[1], l); yylval.str[l] = 0;
}

Are you sure that it's notequal_expression that is causing the issue? 您确定是引起问题的notequal_expressionnotequal_expression吗? The nonterminal and rule that are not used, as I read it, are 在我阅读时,未使用的非终结符和规则是

bool
      : BOOLEAN          {}
      ;

Perhaps instead of 也许代替

simple_expression
      : identifier
      | string
      ;

you intended to code 你打算编码

simple_expression
      : identifier
      | string
      | bool
      ;

There are two problems with the grammar. 语法有两个问题。 The first is the shift/reduce conflict you've already seen (and addressed with %expect 1 . I prefer to address it in the grammar instead and use %expect 0 instead. You can do that by removing ELSE from the %token list and adding a line 第一个是您已经看到的移位/减少冲突(并已用%expect 1 。我更喜欢在语法中解决它,而改用%expect 0 。您可以通过从%token列表中删除ELSE来实现,添加一条线

%right THEN ELSE

To declare right associativity. 宣布权利关联性。 Your language doesn't actually have a THEN keyword but that's fine. 您的语言实际上没有THEN关键字,但这很好。 You can then remove completely the rule for optional_else_statement and reword the rule for if_statement as follows: 然后,您可以完全删除optional_else_statement的规则,并重新if_statement的规则,如下所示:

if_statement
      : IF OPEN_PAR expression CLOSE_PAR statement  %prec THEN
      | IF OPEN_PAR expression CLOSE_PAR statement ELSE statement
      ;

There are those who prefer to resolve it this way, and others who advocate the %expect 1 approach. 有些人喜欢以这种方式解决它,有些人则主张%expect 1方法。 I prefer this way, but now that you have both methods, you can certainly choose for yourself. 我更喜欢这种方式,但是既然您同时拥有这两种方法,那么您当然可以自己选择。

For the other problem, the useless rule is definitely this one: 对于另一个问题,无用的规则肯定是这样的:

bool
      : BOOLEAN          {}
      ;

because the non-terminal bool is not used anywhere else in the grammar. 因为在语法的其他地方都没有使用非bool This accounts for both "1 useless nonterminal and 1 useless rule" as reported by bison. 正如bison所报告的,这同时解释了“ 1个无用的非终结规则和1个无用的规则”。 To be able to identify this kind of thing for yourself, you can use 为了能够自己识别这种事情,您可以使用

bison --report=solved -v string.y

This will create a string.output file which will contain a large but readable report including any resolved shift-reduce errors (such as your IF-ELSE construction) and also a complete set of states created by bison. 这将创建一个string.output文件,该文件将包含一个大型但可读的报告,包括任何已解决的移位减少错误(例如IF-ELSE构造)以及由bison创建的完整状态集。 It's very useful when attempting to troubleshoot grammar problems. 在尝试对语法问题进行故障排除时非常有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM