]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Fix the plural expression grammar, again.
authorBruno Haible <bruno@clisp.org>
Fri, 16 Mar 2001 17:33:21 +0000 (17:33 +0000)
committerBruno Haible <bruno@clisp.org>
Fri, 16 Mar 2001 17:33:21 +0000 (17:33 +0000)
intl/ChangeLog
intl/dcigettext.c
intl/gettextP.h
intl/plural.y

index 095a17beac57a158b1115efc40249974a2695baf..13579ad724801e6cb4df82fa2aad25c9bdddc7d2 100644 (file)
@@ -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>
index 982689bf4d9736fc33d03cb2e629dfd8368bd42d..ba93fb3032e0a171f551764041c874fc65d64094 100644 (file)
@@ -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));
index 0c8520cdf07a92603853f96b4de2f6f1e7930b5c..715b04d996c54aa231dd4618371dc874d88563ea 100644 (file)
@@ -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.  */
index f835fa5f2de0d7bd1c1bde5dd1fc0bfe3c390a70..20fb60c81c7b03fd8dfac7c60b2a4958d9ad9ef5 100644 (file)
@@ -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)
@@ -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)