%{ /* * arith.y -- parser for a simple arithmetic/boolean evaluator * * Copyright (c) 2004 by Devin Carraway . * * Released under terms of the GNU General Public License: * * * Published as a helpful and hopefully not wholly broken example of * how one can use lex/yacc, since when I was trying to learn I found * lots of examples but fairly few that could be built, run and tinkered * with straight out of the box. I make no assurances about correctness, * except to observe that there's not that much here to screw up. :) * * The language recognized by this parser is essentially the C expression * syntax, excepting operators performing assignments, and with the addition * of two constants 'true' and 'false' having arithmetic values of 1 and 0 * respectively. All inputs are interpreted as having type 'int'. */ %} %union { int value; } %token tok_newline %type expr %token tok_value %left tok_lor %left tok_land %left tok_xor %left tok_or %left tok_and %left tok_eq tok_ne %left tok_lshift tok_rshift %nonassoc tok_lt tok_lteq tok_gt tok_gteq %right '+' '-' %left '*' '/' '%' %right tok_not %% entry: /* nothing */ | entry expr tok_newline { printf("%d\n", $2); } | entry error tok_newline { yyerrok; } ; expr: tok_value { $$ = $1; } | '-' expr { $$ = - $2; } | '+' expr { $$ = $2; } | '(' expr ')' { $$ = $2; } | tok_not expr { $$ = ! $$; } | expr tok_land expr { $$ = $1 && $3; } | expr tok_lor expr { $$ = $1 || $3; } | expr tok_and expr { $$ = $1 & $3; } | expr tok_or expr { $$ = $1 | $3; } | expr tok_xor expr { $$ = $1 ^ $3; } | expr tok_eq expr { $$ = $1 == $3; } | expr tok_ne expr { $$ = $1 != $3; } | expr tok_lt expr { $$ = $1 < $3; } | expr tok_lteq expr { $$ = $1 <= $3; } | expr tok_gt expr { $$ = $1 > $3; } | expr tok_gteq expr { $$ = $1 >= $3; } | expr tok_lshift expr { $$ = $1 << $3; } | expr tok_rshift expr { $$ = $1 >> $3; } | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr { $$ = $1 / $3; } | expr '%' expr { $$ = $1 % $3; } ; %% #include #include extern int yydebug; static void usage() { printf("usage: arith [ -d | -h ]\n" "\t-d : enable parser debug mode\n" "\t-h : read this fine explanation again\n" "\n"); } int main(int argc, char **argv) { int c; while ((c = getopt(argc, argv, "dh")) != -1) { switch ((char)c) { case 'd': yydebug = 1; break; case 'h': usage(); return 0; default: usage(); return 1; } } yyparse(); return 0; } int yyerror(char *s) { printf("yyerror: %s\n", s); return 1; } int yywrap() { return 1; }