I am trying to make a basic compiler parse and interpret a simple made up programming language. I have my context free grammar created, and have tried to implement it in YACC, but I keep getting '6 fules never reduced'. Here are my productions in the yacc file
%token BEGIN END INT INT_CONST STRING STRING_LIT TERM ID PRINT
%%
start : program
;
program: ID 'is' compound_statement
;
compound_statement: BEGIN statement_loop END; {;}
;
statement_loop: statement statement_loop
| statement
;
statement: ID '=' expr ';'
| ID'=' STRING_LIT ';'
| PRINT value_loop ';'
;
value_loop: value '.' value_loop
| value
;
value: STRING_LIT
| expr
;
expr: term_loop
| '-' term_loop
;
term_loop: term
| term '+' term_loop
| term '-' term_loop
;
term: factor_loop
;
factor_loop: factor_loop
| factor '*' factor_loop
| factor '/' factor_loop
;
declaration: INT id_loop
| STRING id_loop
;
id_loop: ID
| id_loop ','
;
factor: INT_CONST
| ID
'(' expr ')'
;
factor_loop
has no non-recursive production, so it cannot ever produce anything. You probably meant the first production to be factor_loop: factor
.
Since factor_loop
can't produce anything, all of the productions which rely on factor_loop
are also useless.
There are a number of other problems with that grammar, so other error messages are likely. I don't see anything which would cause reduce-reduce conflicts, which makes me wonder whether what you provided was the complete literal grammar file.
Some of the issues:
In program
, 'is'
is not a valid single-character token.
There is a stray semicolon after the END
in compound_statement
.
declaration
is not used anywhere.
id_loop
produces an ID
followed by any number of commas. So a,,,,
is a valid id_loop
but not a, b, c
.
I'm pretty sure you are missing a |
at the beginning if the third line of factor
.
There is way too much right recursion. In some cases, this only produces excess parser stack usage, but it is particularly serious for arithmetic operators because it makes right-associative and they aren't.
In particular, it parses 1 - 2 - 3
as 1 - (2 - 3)
instead of the correct (1 - 2) - 3
Unary minus has far too high a precedence. You will end up parsing -2 + 6
as though it had been written -(2 + 6)
, so the result will be -8 instead of 4.