/* * aegis - project change supervisor * Copyright (C) 1996, 1999, 2002, 2003, 2005-2008 Peter Miller * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see * . */ %{ #include #include #include #include #include #include #include #include #ifdef DEBUG #define YYDEBUG 1 #endif static void yyerror(const char *s); static void yydebugger(void *, const char *, ...); %} %token DIV %token EQ %token GE %token GT %token JUNK %token LE %token LP %token LT %token MINUS %token MOD %token MUL %token NE %token NOT %token NUMBER %token PLUS %token RP %union { long lv_number; } %type NUMBER expr %left NE EQ %left LT LE GT GE %left PLUS MINUS %left MUL DIV MOD %right UNARY %{ static long result; static sub_context_ty *scp; nstring sub_expr_gram(sub_context_ty *scp_arg, const nstring &s) { extern int yyparse(void); #ifdef DEBUG extern int yydebug; #endif trace(("sub_expr_gram()\n{\n")); #ifdef DEBUG yydebug = trace_pretest_; #endif scp = scp_arg; sub_expr_lex_open(s); int bad = yyparse(); sub_expr_lex_close(); trace(("bad = %d\n", bad)); trace(("}\n")); if (bad) return ""; return nstring::format("%ld", result); } static void yyerror(const char *s) { trace(("yyerror(\"%s\")\n{\n", s)); scp->error_set(s); trace(("}\n")); } #ifdef DEBUG /* * jiggery-pokery for yacc * * Replace all calls to printf with a call to trace_printf. The * trace_where_ is needed to set the location, and is safe, because * yacc only invokes the printf with an if (be careful, the printf * is not in a compound statement). */ #define printf trace_where_, trace_printf /* * jiggery-pokery for bison * * Replace all calls to fprintf with a call to yydebugger. Ignore * the first argument, it will be "stderr". The trace_where_ is * needed to set the location, and is safe, because bison only * invokes the printf with an if (be careful, the fprintf is not in * a compound statement). */ #define fprintf trace_where_, yydebugger static void yydebugger(void *, const char *fmt, ...) { va_list ap; string_ty *s; va_start(ap, fmt); s = str_vformat(fmt, ap); va_end(ap); trace_printf("%s", s->str_text); str_free(s); } #endif %} %% grammar: expr { result = $1; } ; expr : LP expr RP { $$ = $2; trace(("$$ = %ld;\n", $$)); } | NUMBER { $$ = $1; trace(("$$ = %ld;\n", $$)); } | MINUS expr %prec UNARY { $$ = -$2; trace(("$$ = %ld;\n", $$)); } | expr PLUS expr { $$ = $1 + $3; trace(("$$ = %ld;\n", $$)); } | expr MINUS expr { $$ = $1 - $3; trace(("$$ = %ld;\n", $$)); } | expr MUL expr { $$ = $1 * $3; trace(("$$ = %ld;\n", $$)); } | expr DIV expr { $$ = $3 ? $1 / $3 : 0; trace(("$$ = %ld;\n", $$)); } | expr MOD expr { $$ = $3 ? $1 % $3 : 0; trace(("$$ = %ld;\n", $$)); } | expr EQ expr { $$ = ($1 == $3); trace(("$$ = %ld;\n", $$)); } | expr NE expr { $$ = ($1 != $3); trace(("$$ = %ld;\n", $$)); } | expr LT expr { $$ = ($1 < $3); trace(("$$ = %ld;\n", $$)); } | expr LE expr { $$ = ($1 <= $3); trace(("$$ = %ld;\n", $$)); } | expr GT expr { $$ = ($1 > $3); trace(("$$ = %ld;\n", $$)); } | expr GE expr { $$ = ($1 >= $3); trace(("$$ = %ld;\n", $$)); } | NOT expr %prec UNARY { $$ = (!$2); trace(("$$ = %ld;\n", $$)); } ;