Search code examples
gccgnubisonflex-lexer

Bison parser always prints syntax error without specifying what is wrong


Hi everyone I'm trying to write a parser for this simple java simple file basically I want this parser to recognise and validate instuction blocks. Upon finding a correct instruction block, the validator would print a success message.

Input file:

{ 
  a = b; 
}

{
  counter = counter- 1;
  i = i + 1;
}

{
  variable1 = i / j;
  variable2 = i * j;
  i++;
  j--;

}

but no matter what I tried I always get syntax error

Bison parser.y code:

%{
#include <stdio.h>
%}
%union {
char * str;
}
%token IDENTIFIER
%token INT_LITERAL
%token STRING_LITERAL
%token PLUS PLUS_PLUS MINUS MINUS_MINUS EQUAL SEMICOLON
%%
program: block
       | /* empty */
       ;
block: '{' statement_list '}'
      ;

statement_list: statement
              | statement_list statement
              ;

statement: assignment_statement
         | increment_statement
         | decrement_statement
         ;

assignment_statement: IDENTIFIER EQUAL INT_LITERAL SEMICOLON
                   ;

increment_statement: IDENTIFIER PLUS_PLUS SEMICOLON
                  ;

decrement_statement: IDENTIFIER MINUS_MINUS SEMICOLON
                  ;

%%

int yyerror (char *s) {
fprintf (stderr, "%s\n", s);
}

int main() {
    yyparse();
    return 0;
}

Flex parserlex.l code:

%{
#include "parser.tab.h"
%}

%%

"{"                             { return '{'; }
"}"                             { return '}'; }
"="                             { return EQUAL; }
";"                             { return SEMICOLON; }
"++"                            { return PLUS_PLUS; }
"--"                            { return MINUS_MINUS; }
[ \t\n\r]+                      ;  // Ignore white spaces

[a-zA-Z_][a-zA-Z0-9_]*           { yylval.str = strdup(yytext); return IDENTIFIER; }
[0-9]+                          { yylval.str = strdup(yytext); return INT_LITERAL; }

.                               { fprintf(stderr, "Unrecognized token: %s\n", yytext); return 0; }

%%

int yywrap() {
    return 1;
}

I don't know what is wrong and since the only error message I get is "syntax error" I don't even know where to start looking for potential solutions. I also tried to use bison -v and reading bison.output file but it didn't got me much. Any help would be greatly appreciated


Solution

  • Some obvious limitations of your grammar:

    • Your assignment_statement rule only accepts IDENTIFIER EQUAL INT_LITERAL so anything other than a constant on the rhs (such as a = b; -- the second line in your input) will give a syntax error

    • Your top-level program only accepts a single block so it would give a syntax error on seeing a second block (if it ever got that far).

    To help tracing your program, you can enable tracing code (by using the -t argument to bison) and turn it on by setting yydebug = 1 before calling yyparse(). I prefer putting something like

    if (getennv('YYDEBUG')) yydebug = 1;
    

    in the beginning of main and always using -t (or %define parse.trace near the top of the .y file -- same effect). That way it will print a trace if you set YYDEBUG in your environment before running your program.