From: Bruno Haible Date: Fri, 16 Mar 2001 17:33:21 +0000 (+0000) Subject: Fix the plural expression grammar, again. X-Git-Tag: v0.10.36~47 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=efd4210b802c0b06823a3eae5024992aba152c44;p=thirdparty%2Fgettext.git Fix the plural expression grammar, again. --- diff --git a/intl/ChangeLog b/intl/ChangeLog index 095a17bea..13579ad72 100644 --- a/intl/ChangeLog +++ b/intl/ChangeLog @@ -1,11 +1,15 @@ -2001-03-12 Bruno Haible - - * gettextP.h (struct expression): Add operators less_than, - greater_than, less_or_equal, greater_or_equal. - * plural.y ('<', '>', LE, GE): New operators. +2001-03-16 Bruno Haible + + * gettextP.h (struct expression): Add operators lnot, less_than, + greater_than, less_or_equal, greater_or_equal. Add args1 to union. + * plural.y ('?' ':'): Make right-associative. + ('<', '>', LE, GE, '!'): New operators. + (EQ): Renamed from '='. + (NE): Renamed from '!'. (exp): Add rules with these operators. + (new_exp_1): New function. (FREE_EXPRESSION): Recognize these operators. - (yylex): Don't skip "\\n". Recognize '<', '>', LE, GE operators. + (yylex): Don't skip "\\n". Recognize '<', '>', LE, GE, '!' operators. * dcigettext.c (plural_eval): Recognize these operators. 2001-03-10 Bruno Haible diff --git a/intl/dcigettext.c b/intl/dcigettext.c index 982689bf4..ba93fb303 100644 --- a/intl/dcigettext.c +++ b/intl/dcigettext.c @@ -994,6 +994,8 @@ plural_eval (pexp, n) return n; case num: return pexp->val.num; + case lnot: + return ! plural_eval (pexp->val.args1.right, n); case mult: return (plural_eval (pexp->val.args2.left, n) * plural_eval (pexp->val.args2.right, n)); diff --git a/intl/gettextP.h b/intl/gettextP.h index 0c8520cdf..715b04d99 100644 --- a/intl/gettextP.h +++ b/intl/gettextP.h @@ -79,6 +79,7 @@ struct expression { var, /* The variable "n". */ num, /* Decimal number. */ + lnot, /* Logical NOT. */ mult, /* Multiplication. */ divide, /* Division. */ module, /* Module operation. */ @@ -98,6 +99,10 @@ struct expression { unsigned long int num; /* Number value for `num'. */ struct + { + struct expression *right; /* Subexpression in unary operation. */ + } args1; + struct { struct expression *left; /* Left expression in binary operation. */ struct expression *right; /* Right expression in binary operation. */ diff --git a/intl/plural.y b/intl/plural.y index f835fa5f2..20fb60c81 100644 --- a/intl/plural.y +++ b/intl/plural.y @@ -49,6 +49,8 @@ %{ /* Prototypes for local functions. */ static struct expression *new_exp_0 PARAMS ((enum operator op)); +static struct expression *new_exp_1 PARAMS ((enum operator op, + struct expression *right)); static struct expression *new_exp_2 PARAMS ((enum operator op, struct expression *left, struct expression *right)); @@ -60,15 +62,17 @@ static int yylex PARAMS ((YYSTYPE *lval, const char **pexp)); static void yyerror PARAMS ((const char *str)); %} -/* This declares that all operators are left-associative, and that the - precedence order is the same as in C. There is no unary minus. */ -%left '?' /* ? */ +/* This declares that all operators have the same associativity and the + precedence order as in C. See [Harbison, Steele: C, A Reference Manual]. + There is no unary minus and no bitwise operators. */ +%right '?' /* ? */ %left '|' /* || */ %left '&' /* && */ -%left '=', '!' /* == != */ -%nonassoc '<', '>', LE, GE /* < > <= >= */ +%left EQ, NE /* == != */ +%left '<', '>', LE, GE /* < > <= >= */ %left '+', '-' /* + - */ %left '*', '/', '%' /* * / % */ +%right '!' /* ! */ %token NUMBER %type exp @@ -96,12 +100,12 @@ exp: exp '?' exp ':' exp if (($$ = new_exp_2 (land, $1, $3)) == NULL) YYABORT } - | exp '=' exp + | exp EQ exp { if (($$ = new_exp_2 (equal, $1, $3)) == NULL) YYABORT } - | exp '!' exp + | exp NE exp { if (($$ = new_exp_2 (not_equal, $1, $3)) == NULL) YYABORT @@ -151,6 +155,11 @@ exp: exp '?' exp ':' exp if (($$ = new_exp_2 (module, $1, $3)) == NULL) YYABORT } + | '!' exp + { + if (($$ = new_exp_1 (lnot, $2)) == NULL) + YYABORT + } | 'n' { if (($$ = new_exp_0 (var)) == NULL) @@ -182,6 +191,29 @@ new_exp_0 (op) return newp; } +static struct expression * +new_exp_1 (op, right) + enum operator op; + struct expression *right; +{ + struct expression *newp = NULL; + + if (right != NULL) + newp = (struct expression *) malloc (sizeof (*newp)); + + if (newp != NULL) + { + newp->operation = op; + newp->val.args1.right = right; + } + else + { + FREE_EXPRESSION (right); + } + + return newp; +} + static struct expression * new_exp_2 (op, left, right) enum operator op; @@ -250,7 +282,10 @@ FREE_EXPRESSION (exp) { case qmop: FREE_EXPRESSION (exp->val.args3.fbranch); - /* FALLTHROUGH */ + /* FREE_EXPRESSION (exp->val.args3.tbranch); */ + /* FREE_EXPRESSION (exp->val.args3.bexp); */ + /* break; */ + /* instead: FALLTHROUGH */ case mult: case divide: @@ -266,7 +301,12 @@ FREE_EXPRESSION (exp) case land: case lor: FREE_EXPRESSION (exp->val.args2.right); - FREE_EXPRESSION (exp->val.args2.left); + /* FREE_EXPRESSION (exp->val.args2.left); */ + /* break; */ + /* instead: FALLTHROUGH */ + + case lnot: + FREE_EXPRESSION (exp->val.args1.right); break; default: @@ -318,13 +358,23 @@ yylex (lval, pexp) break; case '=': - case '!': if (exp[0] == '=') - ++exp; + { + ++exp; + result = EQ; + } else result = YYERRCODE; break; + case '!': + if (exp[0] == '=') + { + ++exp; + result = NE; + } + break; + case '&': case '|': if (exp[0] == result)