codeNewbie
codeNewbie

Reputation: 19

Unexpected syntax error produced by running generated YACC parser

For example I have the code

%nonassoc lower
%nonassoc ELSE

if_stmt: IF '(' expr ')' statement   %prec lower
         {
            /*some code*/
         }
       | IF '(' expr ')' statement ELSE statement
         {
            /*some code*/
         }
       ;

With the rules and code (which don't do much) I now get " elsesyntax error " when I test an IF-ELSE statement. If it is only an IF statement it works fine.

I thought that I should pass something in the 2nd action in order for it to work but I'm not sure what.

If possible, I would like not to separate the 2 actions.

EDIT: So here is the grammar as asked, and the precedence: EDIT2 : implemented my grammar rules. compound_stmt and local_declarations are comments cause i don't yet know what to do with them.

%nonassoc islowerthanelse
%nonassoc ELSE

%%

%token <intVal> NUM WHILE PRINT IF ELSE INT 

program            :    declaration_list statement_list       
                         {
                         printf("/0\n");

                         }
                         ;                                    

declaration_list   :    declaration_list declaration          
                          {
                            printf("/1\n");
                            $$ = make_node(DeclSeq, NULL, $1, $2, NULL, NULL);
                          }
                         |declaration 
                         {
                            printf("/2\n");
                            $$ = $1;
                         }                        
                         ;

declaration        :    type_specifier ID ';'                  
                          {
                            printf("/3\n");
                            $$ = make_node(Decl, p3, $1, NULL, NULL, NULL);
                           }

type_specifier     :    INT                                   
                          {
                            printf("/5\n");
                            $$ = make_node(INT, NULL, NULL, NULL, NULL, NULL);

                          }
                         ;

statement_list     :    statement_list statement              
                         {
                           printf("/6\n");
                           $$ = make_node(StmtSeq, NULL, $1, $2, NULL, NULL);
                         }
                         |/* EMPTY */
                          {
                            printf("/7\n");
                            $$ = make_node(astEmptyStmtSeq, NULL, NULL, NULL, NULL, NULL);

                          }
                         ;

statement          :    expression_stmt                       
                          {
                            printf("/8\n");
                            $$ = $1;
                          }
                         /*|compound_stmt                       
                          {
                            $$ = $1;
                          }*/
                         |selection_stmt                      
                          {
                            $$ = $1;
                          }
                         |iteration_stmt                      
                          {
                            $$ = $1;
                          }
                         |print_stmt                          
                          {
                            printf("/12\n");
                            $$ = $1;
                          }
                         ;

/*compound_stmt      :    '{' local_declarations statement_list '}' 
                         ;

local_declarations :    local_declarations declaration
                         |/* EMPTY *\
                         ;*/

expression_stmt    :    expression ';'                       
                          {
                            printf("/15\n");
                            $$ = make_node(ExprStmt, NULL, $1, NULL, NULL, NULL);
                          }                 
                         |/* EMPTY */ ';'
                          {
                            printf("/16\n");
                            $$ = make_node(EmptyExprStmt, NULL, NULL, NULL, NULL, NULL);
                          }
                         ;

selection_stmt     :    IF '(' expression ')' statement      %prec islowerthanelse      
                          { printf("/256\n");
                            $$ = make_node(IfStmt, NULL, $3, $5, NULL, NULL);

                          }      
                         |IF '(' expression ')' statement ELSE statement 
                          {printf("/257\n");
                            $$ = make_node(IfElseStmt, NULL, $3, $5, $7, NULL);
                          }                    
                         ;

iteration_stmt     :    WHILE '(' expression ')' statement
                          {
                            $$ = make_node(astWhileStmt, NULL, $3, $5, NULL, NULL);
                          }
                          ;

Upvotes: 0

Views: 433

Answers (2)

Chris Dodd
Chris Dodd

Reputation: 126140

Best guess from the fragment show -- your %prec lower actually has a higher precedence that the ELSE token, so when seeing an ELSE it will reduce the first rule, and then get a syntax error as it can't do anything with the ELSE after the reduction.

However, actually answering this question would require seeing the full grammar.


I added the following to your grammar to make an MVCE:

%{
#include <stdio.h>
#define make_node(...)  0
%}

%nonassoc islowerthanelse
%nonassoc ELSE

%token NUM WHILE PRINT IF INT ID
%token expression print_stmt

%%

:

%%
#include "lex.yy.c"
int main() { return yyparse(); }
int yywrap() { return 1; }
void yyerror(const char *msg) { printf("%s\n", msg); }

Along with a trivial lexer:

%%
"while" return WHILE;
"print" return PRINT;
"if" return IF;
"else" return ELSE;
"int" return INT;
"expression" return expression;
[A-Za-z][A-Za-z0-9]* return ID;
[0-9]* return NUM;
[ \t\n] ;
. return *yytext;

and an input file like:

int A;
if (expression) expression; else expression;

and it appears to work just fine...

$ a.out <input.txt/5
/3
/2
/7
/15
/8
/15
/8
/257
/6
/0

Upvotes: 1

rici
rici

Reputation: 241671

Actions are independent of each other; there is no"fall-through". If you want to refactor common code between two actions, put it into a function which can be called from the actions.

However, that should have nothing to do with the syntax error you are seeing. Actions do not affect the parse; if the parser reports a syntax error, it will do so without running any action (since the error reflects the impossibility of finding an appropriate production).

Upvotes: 0

Related Questions