简体   繁体   中英

too many useless rules show up on terminal while building a bison grammar

The code:

%{
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "gener.h"
#include "sym_tab.h"
#include "scope.h"
#include "defs.h"
extern char *yytext;
#define YYPRINT(file, type, value)   yyprint (file, type, value)
%}

%union
{
char *name;
char idtype;
decl_list idlist;
/*decl_list is in gener.h,  
  you should #include "gener.h"
*/
}

%token PROGRAM
%token IDENTIFIER 
%token DECIMAL_CONSTANT
%token DECLARE ENDDECLARE

%token AND CALL DEFAULT
%token FUNCTION PROCEDURE IN INOUT
%token IF ELSE DO WHILE FOR OR NOT SELECT
%token RETURN EXIT  PRINT 
%token EQ_LT EQ_GT NE EXACT 
%left '+' '-'
%right '*' '/'



%start program
%%

program
        : %empty
        | PROGRAM IDENTIFIER block
        ;

block
        : "{" declarations subprograms sequence "}"
        ;
declarations
        : %empty
        | DECLARE varlist ENDDECLARE 
        ;
varlist
        : %empty
        | assignment_stat identifier2
        ;

identifier2 : ',' assignment_stat
        | ',' assignment_stat 

        ;
subprograms 
        : func
        | subprograms ','  
        ;
func        
        : PROCEDURE IDENTIFIER funcbody
        | FUNCTION IDENTIFIER funcbody
        ;
funcbody    
        : formalpars block
        ;
formalpars  
        : '('')'
        | '(' formalparlist ')'

        ;
formalparlist   
        : formalparitem
        | formalparlist ','

        ;
formalparitem   
        : IN IDENTIFIER
        | INOUT IDENTIFIER
        ;       
sequence
        : statement statement_sequence
        ;
statement_sequence
        : ";"statement
        | ';' statement statement_sequence
        ;
brackets_seq    
        : '{' sequence '}'
        ;
brack_or_stat   
        : brackets_seq
        | statement
        ;


statement   
        : %empty
        | assignment_stat
        | if_stat
        | do_while_stat
        | while_stat
        | select_stat
        | exit_stat
        | return_stat
        | print_stat
        | call_stat
        ;
assignment_stat
            : IDENTIFIER EXACT IDENTIFIER 
            ;

if_stat
        : IF '(' condition')' brack_or_stat elsepart
        ;
elsepart
        : %empty
        | ELSE brack_or_stat
        ;
while_stat
        : WHILE '(' condition')' brack_or_stat
        ;
select_stat
        : SELECT'(' IDENTIFIER')'
          dec 
          DEFAULT":" brack_or_stat
        ;
dec
        : DECIMAL_CONSTANT ':' brack_or_stat
        | dec ','
        ;
do_while_stat
        : DO brack_or_stat WHILE '(' condition ')'
        ;
exit_stat   
        : EXIT
        ;
return_stat
        : RETURN '(' expression ')'
        ;
print_stat
        : PRINT '('expression ')'
        ;
call_stat
        : CALL IDENTIFIER actualpars
        ;
actualpars
        : '('')'
        | '('actualparlist')'
        ;
actualparlist
        : actualparitem 
        | actualparlist ','
        ;
actualparitem
        : IN expression
        | INOUT IDENTIFIER
        ;
condition
        : boolterm or_boolterm 
        ;
or_boolterm 
        : OR boolterm
        | OR boolterm or_boolterm
        ;
boolterm    
        : boolfactor and_boolfactor
        ;
and_boolfactor
        : AND boolfactor
        | AND boolfactor and_boolfactor
        ;
boolfactor  
        : NOT '[' condition ']'
        | '[' condition ']'
        | expression relational_oper expression
        ;
expression
        : optional_sign term add_oper_term
        ;
add_oper_term
        : add_oper term
        | add_oper term add_oper_term
        ;
term        
        : factor mul_oper_factor
        ;
mul_oper_factor
        : mul_oper factor 
        | mul_oper factor mul_oper_factor
        ;
factor
        : DECIMAL_CONSTANT
        | expression
        | IDENTIFIER idtail
        ;
idtail
        : %empty
        | actualpars
        ;
relational_oper
        : '='
        | '<'
        | "<="
        | "<>"
        | ">="
        | '>'
        ;
add_oper
        : '+'
        | '-'
        ;
mul_oper
        : '*'
        | '/'
        ;
optional_sign
        : add_oper
        | %empty
        ;



%%

this is the grammar i created for bison, but when i try bison gram.y on terminal a bunch of warnings appear. tried to switch the order by which they are written but still i get the same thing here is the terminal output

gram.y: warning: 44 nonterminals useless in grammar [-Wother]
gram.y: warning: 86 rules useless in grammar [-Wother]
gram.y:43.38-42: warning: nonterminal useless in grammar: block [-Wother]
        | PROGRAM IDENTIFIER block
                                      ^^^^^
gram.y:47.23-34: warning: nonterminal useless in grammar: declarations [-Wother]
        : "{" declarations subprograms sequence "}"
                       ^^^^^^^^^^^^
gram.y:51.27-33: warning: nonterminal useless in grammar: varlist [-Wother]
        | DECLARE varlist ENDDECLARE 
                           ^^^^^^^
gram.y:55.35-45: warning: nonterminal useless in grammar: identifier2 [-Wother]
        | assignment_stat identifier2
                                   ^^^^^^^^^^^
gram.y:47.36-46: warning: nonterminal useless in grammar: subprograms [-Wother]
        : "{" declarations subprograms sequence "}"
                                    ^^^^^^^^^^^
gram.y:63.19-22: warning: nonterminal useless in grammar: func [-Wother]
        : func
                   ^^^^
gram.y:67.40-47: warning: nonterminal useless in grammar: funcbody [-Wother]
        : PROCEDURE IDENTIFIER funcbody
                                        ^^^^^^^^
gram.y:71.19-28: warning: nonterminal useless in grammar: formalpars [-Wother]
        : formalpars block
                   ^^^^^^^^^^
gram.y:75.23-35: warning: nonterminal useless in grammar: formalparlist [-Wother]
        | '(' formalparlist ')'
                       ^^^^^^^^^^^^^
gram.y:79.19-31: warning: nonterminal useless in grammar: formalparitem [-Wother]
        : formalparitem
                   ^^^^^^^^^^^^^
gram.y:47.48-55: warning: nonterminal useless in grammar: sequence [-Wother]
        : "{" declarations subprograms sequence "}"
                                                ^^^^^^^^
gram.y:88.29-46: warning: nonterminal useless in grammar: statement_sequence [-Wother]
        : statement statement_sequence
                             ^^^^^^^^^^^^^^^^^^
gram.y:94.1-12: warning: nonterminal useless in grammar: brackets_seq [-Wother]
 brackets_seq   
 ^^^^^^^^^^^^
gram.y:97.1-13: warning: nonterminal useless in grammar: brack_or_stat [-Wother]
 brack_or_stat  
 ^^^^^^^^^^^^^
gram.y:88.19-27: warning: nonterminal useless in grammar: statement [-Wother]
        : statement statement_sequence
                   ^^^^^^^^^
gram.y:55.19-33: warning: nonterminal useless in grammar: assignment_stat [-Wother]
        | assignment_stat identifier2
                   ^^^^^^^^^^^^^^^
gram.y:106.19-25: warning: nonterminal useless in grammar: if_stat [-Wother]
        | if_stat
                   ^^^^^^^
gram.y:120.53-60: warning: nonterminal useless in grammar: elsepart [-Wother]
        : IF '(' condition')' brack_or_stat elsepart
                                                     ^^^^^^^^
gram.y:108.19-28: warning: nonterminal useless in grammar: while_stat [-Wother]
        | while_stat
                   ^^^^^^^^^^
gram.y:109.19-29: warning: nonterminal useless in grammar: select_stat [-Wother]
        | select_stat
                   ^^^^^^^^^^^
gram.y:131.19-21: warning: nonterminal useless in grammar: dec [-Wother]
          dec 
                   ^^^
gram.y:107.19-31: warning: nonterminal useless in grammar: do_while_stat [-Wother]
        | do_while_stat
                   ^^^^^^^^^^^^^
gram.y:110.19-27: warning: nonterminal useless in grammar: exit_stat [-Wother]
        | exit_stat
                   ^^^^^^^^^
gram.y:111.19-29: warning: nonterminal useless in grammar: return_stat [-Wother]
        | return_stat
                   ^^^^^^^^^^^
gram.y:112.19-28: warning: nonterminal useless in grammar: print_stat [-Wother]
        | print_stat
                   ^^^^^^^^^^
gram.y:113.19-27: warning: nonterminal useless in grammar: call_stat [-Wother]
        | call_stat
                   ^^^^^^^^^
gram.y:151.35-44: warning: nonterminal useless in grammar: actualpars [-Wother]
        : CALL IDENTIFIER actualpars
                                   ^^^^^^^^^^
gram.y:155.22-34: warning: nonterminal useless in grammar: actualparlist [-Wother]
        | '('actualparlist')'
                      ^^^^^^^^^^^^^
gram.y:158.19-31: warning: nonterminal useless in grammar: actualparitem [-Wother]
        : actualparitem 
                   ^^^^^^^^^^^^^
gram.y:120.26-34: warning: nonterminal useless in grammar: condition [-Wother]
        : IF '(' condition')' brack_or_stat elsepart
                          ^^^^^^^^^
gram.y:166.28-38: warning: nonterminal useless in grammar: or_boolterm [-Wother]
        : boolterm or_boolterm 
                            ^^^^^^^^^^^
gram.y:166.19-26: warning: nonterminal useless in grammar: boolterm [-Wother]
        : boolterm or_boolterm 
                   ^^^^^^^^
gram.y:173.30-43: warning: nonterminal useless in grammar: and_boolfactor [-Wother]
        : boolfactor and_boolfactor
                              ^^^^^^^^^^^^^^
gram.y:173.19-28: warning: nonterminal useless in grammar: boolfactor [-Wother]
        : boolfactor and_boolfactor
                   ^^^^^^^^^^
gram.y:145.30-39: warning: nonterminal useless in grammar: expression [-Wother]
        : RETURN '(' expression ')'
                              ^^^^^^^^^^
gram.y:185.38-50: warning: nonterminal useless in grammar: add_oper_term [-Wother]
        : optional_sign term add_oper_term
                                      ^^^^^^^^^^^^^
gram.y:185.33-36: warning: nonterminal useless in grammar: term [-Wother]
        : optional_sign term add_oper_term
                                 ^^^^
gram.y:192.26-40: warning: nonterminal useless in grammar: mul_oper_factor [-Wother]
        : factor mul_oper_factor
                          ^^^^^^^^^^^^^^^
gram.y:192.19-24: warning: nonterminal useless in grammar: factor [-Wother]
        : factor mul_oper_factor
                   ^^^^^^
gram.y:201.30-35: warning: nonterminal useless in grammar: idtail [-Wother]
        | IDENTIFIER idtail
                              ^^^^^^
gram.y:182.30-44: warning: nonterminal useless in grammar: relational_oper [-Wother]
        | expression relational_oper expression
                              ^^^^^^^^^^^^^^^
gram.y:188.19-26: warning: nonterminal useless in grammar: add_oper [-Wother]
        : add_oper term
                   ^^^^^^^^
gram.y:195.19-26: warning: nonterminal useless in grammar: mul_oper [-Wother]
        : mul_oper factor mul_oper_factor
                   ^^^^^^^^
gram.y:185.19-31: warning: nonterminal useless in grammar: optional_sign [-Wother]
        : optional_sign term add_oper_term
                   ^^^^^^^^^^^^^
gram.y:43.19-42: warning: rule useless in grammar [-Wother]
        | PROGRAM IDENTIFIER block
                   ^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:47.19-59: warning: rule useless in grammar [-Wother]
        : "{" declarations subprograms sequence "}"
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:50.19-24: warning: rule useless in grammar [-Wother]
        : %empty
                   ^^^^^^
gram.y:51.19-44: warning: rule useless in grammar [-Wother]
        | DECLARE varlist ENDDECLARE 
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:54.19-24: warning: rule useless in grammar [-Wother]
        : %empty
                   ^^^^^^
gram.y:55.19-45: warning: rule useless in grammar [-Wother]
        | assignment_stat identifier2
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:58.19-37: warning: rule useless in grammar [-Wother]
 identifier2    : ',' assignment_stat
                   ^^^^^^^^^^^^^^^^^^^
gram.y:59.19-37: warning: rule useless in grammar [-Wother]
        | ',' assignment_stat 
                   ^^^^^^^^^^^^^^^^^^^
gram.y:63.19-22: warning: rule useless in grammar [-Wother]
        : func
                   ^^^^
gram.y:64.19-33: warning: rule useless in grammar [-Wother]
        | subprograms ','  
                   ^^^^^^^^^^^^^^^
gram.y:67.19-47: warning: rule useless in grammar [-Wother]
        : PROCEDURE IDENTIFIER funcbody
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:68.19-46: warning: rule useless in grammar [-Wother]
        | FUNCTION IDENTIFIER funcbody
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:71.19-34: warning: rule useless in grammar [-Wother]
        : formalpars block
                   ^^^^^^^^^^^^^^^^
gram.y:74.19-24: warning: rule useless in grammar [-Wother]
        : '('')'
                   ^^^^^^
gram.y:75.19-39: warning: rule useless in grammar [-Wother]
        | '(' formalparlist ')'
                   ^^^^^^^^^^^^^^^^^^^^^
gram.y:79.19-31: warning: rule useless in grammar [-Wother]
        : formalparitem
                   ^^^^^^^^^^^^^
gram.y:80.19-35: warning: rule useless in grammar [-Wother]
        | formalparlist ','
                   ^^^^^^^^^^^^^^^^^
gram.y:84.19-31: warning: rule useless in grammar [-Wother]
        : IN IDENTIFIER
                   ^^^^^^^^^^^^^
gram.y:85.19-34: warning: rule useless in grammar [-Wother]
        | INOUT IDENTIFIER
                   ^^^^^^^^^^^^^^^^
gram.y:88.19-46: warning: rule useless in grammar [-Wother]
        : statement statement_sequence
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:91.19-30: warning: rule useless in grammar [-Wother]
        : ";"statement
                   ^^^^^^^^^^^^
gram.y:92.19-50: warning: rule useless in grammar [-Wother]
        | ';' statement statement_sequence
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:95.19-34: warning: rule useless in grammar [-Wother]
        : '{' sequence '}'
                   ^^^^^^^^^^^^^^^^
gram.y:98.19-30: warning: rule useless in grammar [-Wother]
        : brackets_seq
                   ^^^^^^^^^^^^
gram.y:99.19-27: warning: rule useless in grammar [-Wother]
        | statement
                   ^^^^^^^^^
gram.y:104.19-24: warning: rule useless in grammar [-Wother]
        : %empty
                   ^^^^^^
gram.y:105.19-33: warning: rule useless in grammar [-Wother]
        | assignment_stat
                   ^^^^^^^^^^^^^^^
gram.y:106.19-25: warning: rule useless in grammar [-Wother]
        | if_stat
                   ^^^^^^^
gram.y:107.19-31: warning: rule useless in grammar [-Wother]
        | do_while_stat
                   ^^^^^^^^^^^^^
gram.y:108.19-28: warning: rule useless in grammar [-Wother]
        | while_stat
                   ^^^^^^^^^^
gram.y:109.19-29: warning: rule useless in grammar [-Wother]
        | select_stat
                   ^^^^^^^^^^^
gram.y:110.19-27: warning: rule useless in grammar [-Wother]
        | exit_stat
                   ^^^^^^^^^
gram.y:111.19-29: warning: rule useless in grammar [-Wother]
        | return_stat
                   ^^^^^^^^^^^
gram.y:112.19-28: warning: rule useless in grammar [-Wother]
        | print_stat
                   ^^^^^^^^^^
gram.y:113.19-27: warning: rule useless in grammar [-Wother]
        | call_stat
                   ^^^^^^^^^
gram.y:116.19-45: warning: rule useless in grammar [-Wother]
            : IDENTIFIER EXACT IDENTIFIER 
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:120.19-60: warning: rule useless in grammar [-Wother]
        : IF '(' condition')' brack_or_stat elsepart
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:123.19-24: warning: rule useless in grammar [-Wother]
        : %empty
                   ^^^^^^
gram.y:124.19-36: warning: rule useless in grammar [-Wother]
        | ELSE brack_or_stat
                   ^^^^^^^^^^^^^^^^^^
gram.y:127.19-54: warning: rule useless in grammar [-Wother]
        : WHILE '(' condition')' brack_or_stat
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:130.19-132.42: warning: rule useless in grammar [-Wother]
        : SELECT'(' IDENTIFIER')'
                   ^^^^^^^^^
gram.y:135.19-52: warning: rule useless in grammar [-Wother]
        : DECIMAL_CONSTANT ':' brack_or_stat
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:136.19-25: warning: rule useless in grammar [-Wother]
        | dec ','
                   ^^^^^^^
gram.y:139.19-58: warning: rule useless in grammar [-Wother]
        : DO brack_or_stat WHILE '(' condition ')'
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:142.19-22: warning: rule useless in grammar [-Wother]
        : EXIT
                   ^^^^
gram.y:145.19-43: warning: rule useless in grammar [-Wother]
        : RETURN '(' expression ')'
                   ^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:148.19-41: warning: rule useless in grammar [-Wother]
        : PRINT '('expression ')'
                   ^^^^^^^^^^^^^^^^^^^^^^^
gram.y:151.19-44: warning: rule useless in grammar [-Wother]
        : CALL IDENTIFIER actualpars
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:154.19-24: warning: rule useless in grammar [-Wother]
        : '('')'
                   ^^^^^^
gram.y:155.19-37: warning: rule useless in grammar [-Wother]
        | '('actualparlist')'
                   ^^^^^^^^^^^^^^^^^^^
gram.y:158.19-31: warning: rule useless in grammar [-Wother]
        : actualparitem 
                   ^^^^^^^^^^^^^
gram.y:159.19-35: warning: rule useless in grammar [-Wother]
        | actualparlist ','
                   ^^^^^^^^^^^^^^^^^
gram.y:162.19-31: warning: rule useless in grammar [-Wother]
        : IN expression
                   ^^^^^^^^^^^^^
gram.y:163.19-34: warning: rule useless in grammar [-Wother]
        | INOUT IDENTIFIER
                   ^^^^^^^^^^^^^^^^
gram.y:166.19-38: warning: rule useless in grammar [-Wother]
        : boolterm or_boolterm 
                   ^^^^^^^^^^^^^^^^^^^^
gram.y:169.19-29: warning: rule useless in grammar [-Wother]
        : OR boolterm
                   ^^^^^^^^^^^
gram.y:170.19-41: warning: rule useless in grammar [-Wother]
        | OR boolterm or_boolterm
                   ^^^^^^^^^^^^^^^^^^^^^^^
gram.y:173.19-43: warning: rule useless in grammar [-Wother]
        : boolfactor and_boolfactor
                   ^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:176.19-32: warning: rule useless in grammar [-Wother]
        : AND boolfactor
                   ^^^^^^^^^^^^^^
gram.y:177.19-47: warning: rule useless in grammar [-Wother]
        | AND boolfactor and_boolfactor
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:180.19-39: warning: rule useless in grammar [-Wother]
        : NOT '[' condition ']'
                   ^^^^^^^^^^^^^^^^^^^^^
gram.y:181.19-35: warning: rule useless in grammar [-Wother]
        | '[' condition ']'
                   ^^^^^^^^^^^^^^^^^
gram.y:182.19-55: warning: rule useless in grammar [-Wother]
        | expression relational_oper expression
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:185.19-50: warning: rule useless in grammar [-Wother]
        : optional_sign term add_oper_term
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:188.19-31: warning: rule useless in grammar [-Wother]
        : add_oper term
                   ^^^^^^^^^^^^^
gram.y:189.19-45: warning: rule useless in grammar [-Wother]
        | add_oper term add_oper_term
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:192.19-40: warning: rule useless in grammar [-Wother]
        : factor mul_oper_factor
                   ^^^^^^^^^^^^^^^^^^^^^^
gram.y:195.19-49: warning: rule useless in grammar [-Wother]
        : mul_oper factor mul_oper_factor
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gram.y:196.19-33: warning: rule useless in grammar [-Wother]
        | mul_oper factor 
                   ^^^^^^^^^^^^^^^
gram.y:199.19-34: warning: rule useless in grammar [-Wother]
        : DECIMAL_CONSTANT
                   ^^^^^^^^^^^^^^^^
gram.y:200.19-28: warning: rule useless in grammar [-Wother]
        | expression
                   ^^^^^^^^^^
gram.y:201.19-35: warning: rule useless in grammar [-Wother]
        | IDENTIFIER idtail
                   ^^^^^^^^^^^^^^^^^
gram.y:204.19-24: warning: rule useless in grammar [-Wother]
        : %empty
                   ^^^^^^
gram.y:205.19-28: warning: rule useless in grammar [-Wother]
        | actualpars
                   ^^^^^^^^^^
gram.y:208.19-21: warning: rule useless in grammar [-Wother]
        : '='
                   ^^^
gram.y:209.19-21: warning: rule useless in grammar [-Wother]
        | '<'
                   ^^^
gram.y:210.19-22: warning: rule useless in grammar [-Wother]
        | "<="
                   ^^^^
gram.y:211.19-22: warning: rule useless in grammar [-Wother]
        | "<>"
                   ^^^^
gram.y:212.19-22: warning: rule useless in grammar [-Wother]
        | ">="
                   ^^^^
gram.y:213.19-21: warning: rule useless in grammar [-Wother]
        | '>'
                   ^^^
gram.y:216.19-21: warning: rule useless in grammar [-Wother]
        : '+'
                   ^^^
gram.y:217.19-21: warning: rule useless in grammar [-Wother]
        | '-'
                   ^^^
gram.y:220.19-21: warning: rule useless in grammar [-Wother]
        : '*'
                   ^^^
gram.y:221.19-21: warning: rule useless in grammar [-Wother]
        | '/'
                   ^^^
gram.y:224.19-26: warning: rule useless in grammar [-Wother]
        : add_oper
                   ^^^^^^^^
gram.y:225.19-24: warning: rule useless in grammar [-Wother]
        | %empty
                   ^^^^^^

can any1 please help me?

The problem is your production for subprograms .

But it is probably more useful for you (and any of your classmates who might stumble upon this question and answer) to understand how to find problems like this on your own.

StackOverflow encourages you to provide a "Minimal, Complete and Verifiable Example" (MCVE) , and you should take a moment to read that help page. The request is not because we like to make life difficult for people with questions. It is because the act of reducing a problem to the minimum is a key part of debugging, and you will find that as it becomes a habit, you become better and better at finding your problems. Of course, it also helps anyone trying to help you solve a problem, because it eliminates all the irrelevant noise.

But an MCVE is not just small. It is also complete : that is, it is an excerpt which actually exhibits the problem. It is not sufficient to say "I think the problem is here, so I will just show this part." You have to actually prove that the problem is where you think it is by creating the minimal example and showing that it does, in fact, produce the same problem.

In fact, if you take this strategy to heart, you will write your programs in a different way. Instead of coding a thousand lines of code and then feeding it all into a compiler, you will write little self-contained pieces and check each one before combining them into a whole. That way, when you can't figure out a particular problem, you already have an MCVE.

Grammars are annoyingly interconnected, and not nearly as modular as one might like a program to be. A little change in one production can create a shift-reduce conflict involving another seemingly complete unrelated production. Nonetheless, you can often split a grammar into more or less separate components. For example, you could start with just the part of your grammar which defines expressions:

%token PROGRAM
%token IDENTIFIER 
%token DECIMAL_CONSTANT
%token DECLARE ENDDECLARE

%token AND CALL DEFAULT
%token FUNCTION PROCEDURE IN INOUT
%token IF ELSE DO WHILE FOR OR NOT SELECT
%token RETURN EXIT  PRINT 
%token EQ_LT EQ_GT NE EXACT 
%left '+' '-'
%right '*' '/'

%%

expression
        : optional_sign term add_oper_term
        ;
add_oper_term
        : add_oper term
        | add_oper term add_oper_term
        ;
term        
        : factor mul_oper_factor
        ;
mul_oper_factor
        : mul_oper factor 
        | mul_oper factor mul_oper_factor
        ;
factor
        : DECIMAL_CONSTANT
        | expression
        | IDENTIFIER idtail
        ;
idtail
        : %empty
        | actualpars
        ;
add_oper
        : '+'
        | '-'
        ;
mul_oper
        : '*'
        | '/'
        ;
optional_sign
        : add_oper
        | %empty
        ;

actualpars
        : '('')'
        | '('actualparlist')'
        ;
actualparlist
        : actualparitem 
        | actualparlist ','
        ;
actualparitem
        : IN expression
        | INOUT IDENTIFIER
        ;

That produces a number of shift/reduce conflicts, which you will have to solve, but it has no useless productions. (Note that I left all of the %token declarations in place, so the above is not quite minimal. Bison doesn't care if you declare terminals which you never use, so it is easier to leave the declarations in place for the next steps.)

Moving up a step, we can add condition , which involves adding:

condition
        : boolterm or_boolterm 
        ;
or_boolterm 
        : OR boolterm
        | OR boolterm or_boolterm
        ;
boolterm    
        : boolfactor and_boolfactor
        ;
and_boolfactor
        : AND boolfactor
        | AND boolfactor and_boolfactor
        ;
boolfactor  
        : NOT '[' condition ']'
        | '[' condition ']'
        | expression relational_oper expression
        ;
relational_oper
        : '='
        | '<'
        | "<="
        | "<>"
        | ">="
        | '>'
        ;

Now there are more shift/reduce conflicts, but still no useless non-terminals.

The next step would be to add the statement productions. Here, we will find that many statements use the non-terminal brack_or_stat , which is defined:

brack_or_stat   
    : brackets_seq
    | statement
    ;   

In order to avoid dealing with brackets_seq just yet, we can temporarily add it to the list of terminals . (This is a standard technique for hiding grammar details.) Later, when we include the productions for brackets_seq , we can remove the %token declaration.) So we now add

%token brackets_seq

before the `%%`, and the statement productions after it:

brack_or_stat   
        : brackets_seq
        | statement
        ;

statement   
        : %empty
        | assignment_stat
        | if_stat
        | do_while_stat
        | while_stat
        | select_stat
        | exit_stat
        | return_stat
        | print_stat
        | call_stat
        ;
assignment_stat
            : IDENTIFIER EXACT IDENTIFIER 
            ;

if_stat
        : IF '(' condition')' brack_or_stat elsepart
        ;
elsepart
        : %empty
        | ELSE brack_or_stat
        ;
while_stat
        : WHILE '(' condition')' brack_or_stat
        ;
select_stat
        : SELECT'(' IDENTIFIER')'
          dec 
          DEFAULT":" brack_or_stat
        ;
dec
        : DECIMAL_CONSTANT ':' brack_or_stat
        | dec ','
        ;
do_while_stat
        : DO brack_or_stat WHILE '(' condition ')'
        ;
exit_stat   
        : EXIT
        ;
return_stat
        : RETURN '(' expression ')'
        ;
print_stat
        : PRINT '('expression ')'
        ;
call_stat
        : CALL IDENTIFIER actualpars
        ;

Now there are even more shift/reduce conflicts, but no useless non-terminals.

So now we've looked at more than half of the grammar, and are reasonably confident that the problem is not in the part we've looked at. (Although there are lots of other problems left to solve.)

So if we assume that statement is OK, let's make it a terminal, and remove it and all the non-terminals it references from the test. That leaves us with a much simpler program: (When I copy-and-pasted this excerpt and ran it through bison, it informed me that assignment_stat was not defined. So I just added it to the %token declaration.)

%token PROGRAM
%token IDENTIFIER 
%token DECIMAL_CONSTANT
%token DECLARE ENDDECLARE

%token AND CALL DEFAULT
%token FUNCTION PROCEDURE IN INOUT
%token IF ELSE DO WHILE FOR OR NOT SELECT
%token RETURN EXIT  PRINT 
%token EQ_LT EQ_GT NE EXACT 

%token statement assignment_stat

%start program
%%

program
        : %empty
        | PROGRAM IDENTIFIER block
        ;

block
        : "{" declarations subprograms sequence "}"
        ;
declarations
        : %empty
        | DECLARE varlist ENDDECLARE 
        ;
varlist
        : %empty
        | assignment_stat identifier2
        ;

identifier2 : ',' assignment_stat
        | ',' assignment_stat 

        ;
subprograms 
        : func
        | subprograms ','  
        ;
func        
        : PROCEDURE IDENTIFIER funcbody
        | FUNCTION IDENTIFIER funcbody
        ;
funcbody    
        : formalpars block
        ;
formalpars  
        : '('')'
        | '(' formalparlist ')'

        ;
formalparlist   
        : formalparitem
        | formalparlist ','

        ;
formalparitem   
        : IN IDENTIFIER
        | INOUT IDENTIFIER
        ;       
sequence
        : statement statement_sequence
        ;
statement_sequence
        : ";"statement
        | ';' statement statement_sequence
        ;
brackets_seq    
        : '{' sequence '}'
        ;
brack_or_stat   
        : brackets_seq
        | statement
        ;

And now we have a screen full of "useless non-terminal" warnings.

However, the grammar is now much simpler. (If it doesn't seem sufficiently simpler, you could continue with the simplification exercise. One possibility would be to separate out declarations, for example.) And indeed, the problem might be visible:

subprograms 
        : func
        | subprograms ','  
func    : PROCEDURE IDENTIFIER funcbody
        | FUNCTION IDENTIFIER funcbody
funcbody: formalpars block
block: "{" declarations subprograms sequence "}"

Note what is happening here: subprograms has two productions. The second one is obviously recursive. But it takes little work to see that the other one is also recursive: func has two productions, but both use funcbody ; funcbody 's only production uses block , and block uses subprograms .

So subprograms has no non-recursive production, and it therefore can never break out of the recursion. And neither can func , funcbody , or block .

But if block cannot generate any sentences, then the second production of program ( PROGRAM IDENTIFIER block ) also cannot generate any sentences, leaving program: %empty as the only valid production for the start symbol. That makes the empty string the only valid program , and so bison marks every other non-terminal as useless.

Now, let's go back to subprograms (which, as I said at the beginning, is the immediate problem). The definition is:

subprograms 
        : func
        | subprograms ','  

Now, that is a very odd definition (and, I think, the oddity is repeated throughout your grammar). What is this saying? That subprograms is a func or subprograms followed by a comma. So it will produce:

func
func ,
func , ,
func , , ,
func , , , ,

and so on. A single func , followed by zero or more commas. It must have one func, and it cannot have more.

The fact that it cannot be empty is the cause of the infinite recursion. A block must include a subprograms , and a subprograms must include a single func . But a func must include a block . And there is no escape from that merry-go-round.

So there are two problems here: subprograms cannot be empty, and it also cannot contain more than one func . What you were probably looking for was:

function_list: func
             | function_list ',' func
subprograms  : %empty
             | function_list

Note that function_list uses left recursion. That was deliberate. Bison produces LR parsers, which adore left recursion.

If you previously studied LL parsers and somehow got it into your head that left recursion is evil, forget that lesson . LL parsers cannot handle left recursion, but LR parsers can handle both left and right recursion, and handle left recursion better (because it doesn't eat up the parser stack).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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