cal.l
%{
#include <stdlib.h> /* for atoi call */
#define DEBUG /* for debuging: print tokens and their line numbers */
#define NUMBER 258 /* copy this from cal.tab.c */
typedef union { /* copy this from cal.tab.c */
int d;
} YYSTYPE;
YYSTYPE yylval; /* for passing value to parser */
extern int lineNum; /* line number from cal.tab.c */
%}
%%
[ \t]+ {}
[\n] { lineNum++; }
"(" {
#ifdef DEBUG
printf("token '(' at line %d\n", lineNum);
#endif
return '(';
}
")" {
#ifdef DEBUG
printf("token ')' at line %d\n", lineNum);
#endif
return ')';
}
"+" {
#ifdef DEBUG
printf("token '+' at line %d\n", lineNum);
#endif
return '+';
}
"*" {
#ifdef DEBUG
printf("token '*' at line %d\n", lineNum);
#endif
return '*';
}
[0-9]+ {
#ifdef DEBUG
printf("token %s at line %d\n", yytext, lineNum);
#endif
yylval.d = atoi(yytext);
return NUMBER;
}
%%
int yywrap() { /* need this to avoid link problem */
return 1;
}
cal.y
%{
#include <stdio.h>
#include <ctype.h>
int lineNum = 1;
void yyerror(char *ps, ...) { /* need this to avoid link problem */
printf("%s\n", ps);
}
%}
%union {
int d;
}
// need to choose token type from union above
%token <d> NUMBER
%token '(' ')'
%left '+'
%left '*'
%type <d> exp factor term
%start cal
%%
cal : exp
{ printf("The result is %d\n", $1); }
;
exp : exp '+' factor
{ $$ = $1 + $3; }
| factor
{ $$ = $1; }
;
factor : factor '*' term
{ $$ = $1 * $3; }
| term
{ $$ = $1; }
;
term : NUMBER
{ $$ = $1; }
| '(' exp ')'
{ $$ = $2; }
;
%%
int main() {
yyparse();
return 0;
}
Makefile
cal: lex.yy.o cal.tab.o
gcc -o cal lex.yy.o cal.tab.o
lex.yy.o: cal.l
flex cal.l; gcc -c lex.yy.c
cal.tab.o: cal.y
bison -d cal.y; gcc -c cal.tab.c
clean:
rm -f p2 cal.output *.o cal.tab.c lex.yy.c