%{ #include #include #include #include "expr.h" #include "y.tab.h" extern int yylex(void); extern int yyerror(const char *s); static void breakpoint(void) { } static void expr_only_integers(YYSTYPE *y1, YYSTYPE *y2) { if (y1->type == STRING) { fprintf(stderr, "expr: %s is not an integer\n", y1->u.s); exit(1); } if (y2->type == STRING) { fprintf(stderr, "expr: %s is not an integer\n", y2->u.s); exit(1); } } static int expr_compare(YYSTYPE *y1, YYSTYPE *y2) { if (y1->type == INTEGER && y2->type == INTEGER) { return y1->u.i - y2->u.i; } char buf[64]; char *s1 = y1->u.s; char *s2 = y2->u.s; if (y1->type == INTEGER) { snprintf(buf, sizeof(buf), "%d", y1->u.i); s1 = buf; } else if (y2->type == INTEGER) { snprintf(buf, sizeof(buf), "%d", y2->u.i); s2 = buf; } return strcmp(s1, s2); } %} %token INTEGER %token STRING %token '(' ')' %left ':' %left '*' '/' '%' %left '+' '-' %left '=' '<' '>' LE GE NE %left '&' %left '|' %start expr %% expr : STRING { } | INTEGER { } | '(' expr ')' { } | expr ':' expr { printf("match\n"); } | expr '*' expr { expr_only_integers(&$1, &$3); $$.u.i = $1.u.i * $3.u.i; printf("%d\n", $$.u.i); } | expr '/' expr { expr_only_integers(&$1, &$3); $$.u.i = $1.u.i / $3.u.i; printf("%d\n", $$.u.i); } | expr '%' expr { expr_only_integers(&$1, &$3); $$.u.i = $1.u.i % $3.u.i; printf("%d\n", $$.u.i); } | expr '+' expr { expr_only_integers(&$1, &$3); $$.u.i = $1.u.i + $3.u.i; printf("%d\n", $$.u.i); } | expr '-' expr { expr_only_integers(&$1, &$3); $$.u.i = $1.u.i - $3.u.i; printf("%d\n", $$.u.i); } | expr '=' expr { int r = expr_compare(&$1, &$3) == 0; printf("%d\n", r); } | expr NE expr { int r = expr_compare(&$1, &$3) != 0; printf("%d\n", r); } | expr '<' expr { int r = expr_compare(&$1, &$3) < 0; printf("%d\n", r); } | expr LE expr { int r = expr_compare(&$1, &$3) <= 0; printf("%d\n", r); } | expr '>' expr { int r = expr_compare(&$1, &$3) > 0; printf("%d\n", r); } | expr GE expr { int r = expr_compare(&$1, &$3) >= 0; printf("%d\n", r); } | expr '&' expr { printf("and\n"); } | expr '|' expr { printf("or\n"); } ;