简体   繁体   English

建立野牛语法时,终端上显示了太多无用的规则

[英]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. 这是我为野牛创建的语法,但是当我在终端上尝试野​​牛gram.y时,会出现一堆警告。 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 . 问题是您生产的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. StackOverflow鼓励您提供一个“最小,完整和可验证的示例”(MCVE) ,您应该花一点时间阅读该帮助页面。 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. 但是MCVE不仅很小。 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. 这样,当您无法解决特定问题时,就已经拥有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.) (请注意,我将所有%token声明留在了适当的位置,因此上述内容并不是简单。Bison不在乎是否声明了您从未使用过的终端,因此将声明保留在以后的步骤中会更容易)

Moving up a step, we can add condition , which involves adding: 向上移动一步,我们可以添加condition ,其中涉及添加:

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 ,它的定义如下:

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 . 为了避免再次处理brackets_seq ,我们可以将其临时添加到终端列表中。 (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 (这是隐藏语法细节的标准技术。)稍后,当我们包含brackets_seq ,我们可以删除%token声明。)因此,我们现在添加

%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. 因此,如果我们假设该statement还可以,那么将其设为终端,然后从测试中删除该引用以及它引用的所有非终端。 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.) 这给我们留下了一个简单得多的程序:(当我复制并粘贴此摘录并通过野牛运行时,它通知我未定义assignment_stat 。因此,我将其添加到%token声明中。)

%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. 注意这里发生了什么: subprograms有两个生成。 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 ; 但是,只需花很少的工作就可以看到另一个也是递归的: func有两个产品,但是都使用funcbody funcbody 's only production uses block , and block uses subprograms . funcbody的唯一产品使用block ,而block使用subprograms

So subprograms has no non-recursive production, and it therefore can never break out of the recursion. 因此, subprograms没有非递归产生,因此它永远不会脱离递归。 And neither can func , funcbody , or block . 而且funcfuncbodyblock都不能。

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. 但是,如果block无法生成任何语句,则program的第二个产生式( PROGRAM IDENTIFIER block )也无法生成任何语句,从而使program: %empty成为起始符号的唯一有效产生。 That makes the empty string the only valid program , and so bison marks every other non-terminal as useless. 这使空字符串成为唯一有效的program ,因此,野牛将所有其他非终端标记为无用。

Now, let's go back to subprograms (which, as I said at the beginning, is the immediate problem). 现在,让我们回到subprograms (正如我刚开始所说的那样,这是当前的问题)。 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. subprograms是一个func或一个subprograms后跟一个逗号。 So it will produce: 因此它将产生:

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

and so on. 等等。 A single func , followed by zero or more commas. 单个func ,后跟零个或多个逗号。 It must have one func, and it cannot have more. 必须具有一个func,而不能具有更多。

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 . block必须包含一个subprograms ,并且一个subprograms必须包含一个func But a func must include a block . func必须包含一个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 . 因此,这里存在两个问题: subprograms不能为空,也不能包含多个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. 请注意, function_list使用左递归。 That was deliberate. 那是故意的。 Bison produces LR parsers, which adore left recursion. 野牛产生LR解析器,它喜欢左递归。

If you previously studied LL parsers and somehow got it into your head that left recursion is evil, forget that lesson . 如果您以前学习过LL解析器,却以某种方式使它陷入困境,那么左递归就是邪恶的, 那就不要上那课了 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). LL解析器无法处理左递归,但是LR解析器可以处理左递归和右递归,并且可以更好地处理左递归(因为它不会耗尽解析器堆栈)。

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

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