// Prologue (directives). %expect 0 // Emitted in the header file, after the definition of YYSTYPE. %code provides { // Tell Flex the expected prototype of yylex. #define YY_DECL \ enum yytokentype yylex (YYSTYPE* yylval, int *nerrs) YY_DECL; void yyerror (int *nerrs, const char *msg); } // Emitted on top of the implementation file. %code top { #include <stdio.h> // printf. #include <stdlib.h> // getenv. } %define api.pure full %define api.token.prefix {TOK_} %define api.value.type union %define parse.error verbose %define parse.trace // Error count, exchanged between main, yyparse and yylex. %param {int *nerrs} %token PLUS "+" MINUS "-" STAR "*" SLASH "/" LPAREN "(" RPAREN ")" EOL "end-of-line" EOF 0 "end-of-file" ; %token <int> NUM "number" %type <int> exp %printer { fprintf (yyo, "%d", $$); } <int> // Precedence (from lowest to highest) and associativity. %left "+" "-" %left "*" "/" %% // Rules. input: %empty | input line ; line: exp EOL { printf ("%d\n", $exp); } | error EOL { yyerrok; } ; exp: exp "+" exp { $$ = $1 + $3; } | exp "-" exp { $$ = $1 - $3; } | exp "*" exp { $$ = $1 * $3; } | exp "/" exp { if ($3 == 0) { yyerror (nerrs, "invalid division by zero"); YYERROR; } else $$ = $1 / $3; } | "(" exp ")" { $$ = $2; } | NUM { $$ = $1; } ; %% // Epilogue (C code). void yyerror (int *nerrs, const char *msg) { fprintf (stderr, "%s\n", msg); ++*nerrs; } int main (void) { int nerrs = 0; // Possibly enable parser runtime debugging. yydebug = !!getenv ("YYDEBUG"); yyparse (&nerrs); // Exit on failure if there were errors. return !!nerrs; }