Reputation: 19
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
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
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