summaryrefslogtreecommitdiffstats
path: root/intl
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2001-03-16 17:33:21 +0000
committerBruno Haible <bruno@clisp.org>2001-03-16 17:33:21 +0000
commitefd4210b802c0b06823a3eae5024992aba152c44 (patch)
tree5ab9f40cc451ed6de47d860bd3f3a0254ccc7798 /intl
parentf22951d28a5a24cd261761496cca26e8689eb2a2 (diff)
downloadexternal_gettext-efd4210b802c0b06823a3eae5024992aba152c44.zip
external_gettext-efd4210b802c0b06823a3eae5024992aba152c44.tar.gz
external_gettext-efd4210b802c0b06823a3eae5024992aba152c44.tar.bz2
Fix the plural expression grammar, again.
Diffstat (limited to 'intl')
-rw-r--r--intl/ChangeLog16
-rw-r--r--intl/dcigettext.c2
-rw-r--r--intl/gettextP.h5
-rw-r--r--intl/plural.y72
4 files changed, 78 insertions, 17 deletions
diff --git a/intl/ChangeLog b/intl/ChangeLog
index 095a17b..13579ad 100644
--- a/intl/ChangeLog
+++ b/intl/ChangeLog
@@ -1,11 +1,15 @@
-2001-03-12 Bruno Haible <haible@clisp.cons.org>
-
- * 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 <haible@clisp.cons.org>
+
+ * 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 <haible@clisp.cons.org>
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
index 982689b..ba93fb3 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 0c8520c..715b04d 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. */
@@ -99,6 +100,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. */
} args2;
diff --git a/intl/plural.y b/intl/plural.y
index f835fa5..20fb60c 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 <num> NUMBER
%type <exp> 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)
@@ -183,6 +192,29 @@ new_exp_0 (op)
}
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;
struct expression *left;
@@ -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)