I am working on a program using Flex and Bison. My task can be done using only Flex(using start conditions etc.), but I have understood that using Bison might make my life easier. My task is to design a program which recognizes a programming language declaration part. Its syntax and logic can be understood through my code below. My problem is that I want my program to recognize as an acceptable declaration part every part of code which begins only with the "var" keyword! Until now, I have not managed to do that. How can I succeed it?
I present below my .l (flex) and .y (bison) files.
exercise4.l
%{
#include <stdio.h>
%}
%%
[ \t\n]+ { /* Ignore all whitespaces */ }
";" { /* Ignore all semicolons */ }
":" { /* Ignore all colons */ }
var { printf("A keyword: %s\n",yytext); return VAR; }
real { printf("A variable type: %s\n",yytext); return REAL; }
boolean { printf("A variable type: %s\n",yytext); return BOOLEAN; }
integer { printf("A variable type: %s\n",yytext); return INTEGER; }
char { printf("A variable type: %s\n",yytext); return CHAR; }
[a-zA-Z][a-zA-Z0-9_]* { printf("A variable name: %s\n",yytext); return VAR_NAME; }
. { printf("Unrecognized character!\n"); return yytext[0]; }
%%
exercise4.y
%{
#include <stdio.h>
%}
%token VAR VAR_NAME REAL BOOLEAN INTEGER CHAR
%%
program : VAR typedecls ;
typedecls : typedecl | typedecls typedecl ;
typedecl : varlist ':' var_type ';' ;
varlist : VAR_NAME | varlist ',' VAR_NAME ;
var_type : REAL | BOOLEAN | INTEGER | CHAR ;
%%
main( argc, argv )
int argc;
char **argv;
{
extern FILE *yyin;
++argv, --argc; /* skip over program name */
if ( argc > 0 )
yyin = fopen( argv[0], "r" );
else
yyin = stdin;
//yylex();
yyparse();
}
yyerror(char *s)
{
printf("\nError\n");
}
#include "lex.yy.c"
Your scanner never returns
:
or;
tokens (and complains about,
being unrecognized). But your grammar includes those tokens.Consequently,
can never match anything. It doesn't see the
:
it is expecting, and thevar_type
is thus unexpected. (And it wouldn't ever match the;
if it got that far.)I don't know what ancient tutorial you're following, but the pre-ansi prototype for
main
suggests it was composed in the last century (and not in its final years, either). As a rough guide, I slightly updated your files.Here's exercise4.l; the most important modification is that I removed the handbuilt trace logs, since I intend to use flex's built-in debugging feature. I also added some options to reduce compiler warnings, and enabled line number tracking for use in error messages. I left in the bug.
And here's the parser, with a few fixes (like using the standard C prototype syntax from the 1989 C standard):
Now, I run the files through flex, bison and gcc, in that order, to produce an executable:
Normally, the three shell commands would go into a Makefile so that you could just type
make exercise4
to create the executable. But there's nothing really complicated there.Now, we can try it out. Since I didn't fix the bugs, you'll easily see the problem:
The lines starting
--
are flex's trace. You can see each token as it is recognized. So when a:
is encountered in the input, the rule at line 13 is executed. That rule is{ /* Ignore all colons */ }
. And that's what happens.The error message at the end was printed by
yyerror
. Thanks to the%errors-verbose
directive, it tells us what it found (INTEGER
) and what it was expecting.Hope that all helps some.