/* * aegis - project change supervisor * Copyright (C) 2002-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 *); static void yydebugger(void *, const char *, ...); %} %token ANDAND %token BITAND %token BITOR %token BITXOR %token COLON %token DIV %token EQ %token EQU %token GE %token GT %token INTEGER %token JUNK %token LE %token LP %token LT %token MINUS %token MOD %token MUL %token NE %token NOT %token NPLURALS %token NUMBER %token OROR %token PLURAL %token PLUS %token QUEST %token RP %token SEMI %union { unsigned lv_number; } %type INTEGER expr %right EQU %right QUEST COLON %left OROR %left ANDAND %left BITOR %left BITXOR %left BITAND %left NE EQ %left LT LE GT GE %left PLUS MINUS %left MUL DIV MOD %right UNARY NOT BITNOT %{ static unsigned number; static unsigned nplurals; static unsigned plural; unsigned sub_plural_gram(const nstring &s, unsigned n) { extern int yyparse(void); #ifdef DEBUG extern int yydebug; #endif trace(("sub_plural_gram()\n{\n")); number = n; #ifdef DEBUG yydebug = trace_pretest_; #endif sub_plural_lex_open(s); int bad = yyparse(); sub_plural_lex_close(); trace(("bad = %d\n", bad)); trace(("}\n")); if (bad) return 0; if (plural >= nplurals) return 0; return plural; } static void yyerror(const char *) { /* do nothing */ } #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: nplurals SEMI plural ; nplurals : NPLURALS EQU INTEGER { nplurals = $3; } ; plural : PLURAL EQU expr { plural = $3; } ; expr : LP expr RP { $$ = $2; trace(("$$ = %u;\n", $$)); } | NUMBER { $$ = number; trace(("$$ = %u;\n", $$)); } | INTEGER { $$ = $1; trace(("$$ = %u;\n", $$)); } | MINUS expr %prec UNARY { $$ = -$2; trace(("$$ = %u;\n", $$)); } | expr PLUS expr { $$ = $1 + $3; trace(("$$ = %u;\n", $$)); } | expr MINUS expr { $$ = $1 - $3; trace(("$$ = %u;\n", $$)); } | expr MUL expr { $$ = $1 * $3; trace(("$$ = %u;\n", $$)); } | expr DIV expr { $$ = $3 ? $1 / $3 : 0; trace(("$$ = %u;\n", $$)); } | expr MOD expr { $$ = $3 ? $1 % $3 : 0; trace(("$$ = %u;\n", $$)); } | expr EQ expr { $$ = ($1 == $3); trace(("$$ = %u;\n", $$)); } | expr NE expr { $$ = ($1 != $3); trace(("$$ = %u;\n", $$)); } | expr LT expr { $$ = ($1 < $3); trace(("$$ = %u;\n", $$)); } | expr LE expr { $$ = ($1 <= $3); trace(("$$ = %u;\n", $$)); } | expr GT expr { $$ = ($1 > $3); trace(("$$ = %u;\n", $$)); } | expr GE expr { $$ = ($1 >= $3); trace(("$$ = %u;\n", $$)); } | NOT expr { $$ = (!$2); trace(("$$ = %u;\n", $$)); } | BITNOT expr { $$ = ~$2; trace(("$$ = %u;\n", $$)); } | expr ANDAND expr { $$ = $1 && $3; trace(("$$ = %u;\n", $$)); } | expr BITAND expr { $$ = $1 & $3; trace(("$$ = %u;\n", $$)); } | expr OROR expr { $$ = $1 || $3; trace(("$$ = %u;\n", $$)); } | expr BITOR expr { $$ = $1 | $3; trace(("$$ = %u;\n", $$)); } | expr BITXOR expr { $$ = $1 ^ $3; trace(("$$ = %u;\n", $$)); } | expr QUEST expr COLON expr { $$ = $1 ? $3 : $5; trace(("$$ = %u;\n", $$)); } ;