I’m writing a parser in Bison for a basic compiler (and then expand it to contain subroutines and dynamic memory allocation). The grammar is defined in Appendix A of the dragon book. My Flex scanner works–I ran my test files through it and it printed out all the correct tokens it found. Sorry about the strange formatting below. My bison and flex modes in emacs are a little haywire so I’m just using C mode until I fix.
%{
#include <stdio.h>
#define YYERROR_VERBOSE 1066
extern FILE* yyin ;
extern int yylineno ;
extern char* yytext ;
extern int yylex() ;
extern void yyerror() ;
int YYDEBUG = 1 ;
%}
/* Tokens */
%token AND BASIC BREAK DO ELSE EQ FALSE
%token GREQ ID IF INDEX LEEQ MINUS NOEQ NUM OR REAL TEMP TRUE WHILE
/* Grammar rules from Appendix A */
%%
program: block { printf( "Matched program\n" ) ; }
;
block: '{' decls stmts '}' { printf( " Matched block\n" ) ; }
;
decls: decls decl |
;
decl: type ID ';'
;
type: type '[' NUM ']' | BASIC
;
stmts: stmts stmt |
;
stmt: loc '=' bool ';'
| IF '(' bool ')' stmt
| IF '(' bool ')' stmt ELSE stmt
| WHILE '(' bool ')' stmt
| DO stmt WHILE '(' bool ')' ';'
| BREAK ';'
| block
;
loc: loc '[' bool ']' | ID
;
bool: bool OR join | join
;
join: join AND equality | equality
;
equality: equality EQ rel | equality NOEQ rel | rel
;
rel: expr '<' expr | expr LEEQ expr | expr GREQ expr | expr '>' expr | expr
;
expr: expr '+' term | expr '-' term | term
;
term: term '*' unary | term '/' unary | unary
;
unary: '!' unary | '-' unary | factor
;
factor: '(' bool ')' | loc | NUM | REAL | TRUE | FALSE
;
%%
/*
* Additional C Code
* Main Routine
* yyerror()
*/
int main( int argc, char *argv[] ) {
int i ;
if ( argc < 2 ) {
fprintf( stderr, "No input files.\n\n" ) ;
return 1 ;
}
for ( i = 0 ; i < argc ; i++ ) {
yyin = fopen( argv[i], "r" ) ;
if ( !yyin ) {
fprintf( stderr, "Error opening file: %s.\n\n", argv[i] ) ;
return 1 ;
}
yyparse() ;
}
return 0 ;
}
void yyerror( char *s ) {
/* fprintf( stderr, "Error parsing - %d: %s at %s\n", yylineno, s, yytext ) ; */
fprintf( stderr, "Error parsing - %d: %s at %s\n", yylineno, s, yytext ) ;
}
I feel like I might be missing something important. I don’t think it’s the rules. I set yyin to be the input files provided in argv[]. The errors are
Error parsing – 1: syntax error, unexpected TRUE, expecting ‘{‘ at
Error parsing – 1: syntax error, unexpected FALSE, expecting ‘{‘ at ELF
Any help would be greatly appreciated!
EDIT: If I change the main function to not set yyin (so yyparse just reads from stdin), I get this:
{ int x; }
Error parsing – 1: syntax error, unexpected TRUE, expecting ‘{‘ at {
I don’t understand how that is wrong…
When I run your sample input above using a stub yylex, the input program matches. I’m making the assumption that “int” tokenizes as BASIC. (You also need to fix “retrun”.)
You need to debug your lexer. Either attach a debugger so you can see what it is returning, or put a print statement at the end of yylex.
This replaces everything in the bottom section: