4

I am learning to work with YACC and I really can't understand some errors. I would like to know why I get this error when I try to generate my parser with the .y file. Here is my .y file, that represents a context free grammar for Pascal language:

%%


Program : program ident ';' declaration_opc compound_stmt '.'
    ;

declaration_opc : var declaration_list
    |
    ;

declaration_list : declaration ';' declaration_list 
     | declaration ';'
     ;

declaration : id_list ':' type
    ;

id_list : ident 
   | ident ',' id_list
   ;

type : integer
   | BOOLEAN
   ;

proc_dec : proc_header forward ';'
    | proc_header declaration_list compound_stmt
    | func_header forward ';'
    | func_header declaration_list compound_stmt
    ;

proc_header : procedure ident parametros ';'
    ;

func_header : function ident parametros : type
    ;

parametros : '(' param_list ')' 
    |
    ;

param_list : arg 
    | arg ';' param_list
    ;

arg : id_list ':' type
    | var id_list ':' type
    ;

compound_stmt : begin statement_list end
    ;

statement_list : statement ';' statement_list
    | statement
    ;

statement : ident attrib expression
 | IF expression then statement         
 | IF expression then statement ELSE statement
 | WHILE expression DO statement
 | compound_stmt
 | readln ident
 | writeln print_list
 | 
 ;

print_list : literal print_list2
 | expression print_list2
 ;

print_list2 : ',' print_list 
 | 
 ;

expression : add_expression relop add_expression
 | add_expression
 ;

relop : lessequal
 | '<'
 | '>'
 | moreequal
 | '='
 | notequal
 ;

add_expression : add_expression addop term 
 ;

addop : '+' 
 |  '-'
 | or
 ;

term : term mulop unary_exp 
     |  unary_exp
     ;

mulop : '*' 
  | div
  | mod
  | and
  ;

unary_exp : not unary_exp 
  |  factor
  ;

factor : '(' expression ')'
  |  ident
  |  num
  |  TRUE
  |  FALSE
  ;


%%

And I always get this:

byaccj: 19 rules never reduced 
byaccj: 1 shift/reduce conflict.

What is a possible solution for this? I've found other people that have had the same kind of errors, but I was not able to find something useful for my problem. If more information is necessary, I provide. I also read that the 'Rules never reduced' error means that some rules from my grammar are never used, but I am not able to see this with my rules.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Murilo Neto
  • 43
  • 1
  • 3
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders May 26 '15 at 00:54
  • 2
    Use `yacc -v foo.y` and it'll produce a file named `y.output`. Toward the end of that file will be a list of "Rules never reduced." – Jerry Coffin May 26 '15 at 01:35

3 Answers3

4

In your case, the rule proc_dec never appears on the right side of any other rule, so it can never be reached from you start symbol (Program). Yacc is just telling you that this rule (and all the rules used by it and nothing else) are not reachable.

In general, you want to use the -v option to get yacc to prodcue a y.output file with detailed information about your grammar. This file will tell you specifically about all the conflicts and unused rules -- what they are and how they come about -- while the messages just give you a summary of the problems.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
2

In this case, you have two basic sources of problems. One is that you simply haven't included procedures in your grammar for a program. You'd probably fix this with something like:

Program : program ident ';' declaration_opc procedures compound_stmt '.'
    ;

procedures: proc_dec
    | procedures ';' proc_dec
    ;

[It's been a while since I wrote any Pascal--offhand I don't recall if you actually need the semicolon to separate procedures or not, but if not, it's trivial to remove.]

The second problem area is that your grammar for an add_expression is always infinitely recursive:

add_expression : add_expression addop term 
     ;

You haven't included anything to stop the recursion on the left side. You probably want something like:

add_expression : add_expression addop term
               | term addop term
               ;

For an expression like a + b - c, it'll match the first alternative as: (a + b)add_expression -addop cterm, and the second alternative will be used to match just the a + b part as: aterm +addop bterm.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • ,Thank you, I can't believe I couldn't see that, the 19 rules that were not reduced are related to proc_dec and arguments, so definetely I'm not calling them from the start symbol. – Murilo Neto May 26 '15 at 13:28
0

The file is incomplete, because there are a number of tokens which were never defined (such as BOOLEAN). If it were complete, we could give a better answer.

In general, rules which are not reduced simply are not (as far as yacc can determine) connected to the start state through any series of steps. So they are debris which you should redesign or remove.

Here are a few places where this has been discussed before:

Community
  • 1
  • 1
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105