]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Rework the last plural.y changes, for clarity, and optimize for space.
authorBruno Haible <bruno@clisp.org>
Mon, 19 Mar 2001 17:43:35 +0000 (17:43 +0000)
committerBruno Haible <bruno@clisp.org>
Mon, 19 Mar 2001 17:43:35 +0000 (17:43 +0000)
intl/ChangeLog
intl/dcigettext.c
intl/gettextP.h
intl/loadmsgcat.c
intl/plural.y

index c060623ddb19bc389082e36255322b32bf8a2d35..647518a327d7bbc19eeeb380dc745217ed3cc55a 100644 (file)
@@ -1,16 +1,30 @@
-2001-03-16  Bruno Haible  <haible@clisp.cons.org>
+2001-03-17  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.
+       greater_than, less_or_equal, greater_or_equal. Replace args2/args3
+       union by a 'nargs' counter and an 'args[]' array.
+       * plural.y: Don't include stdarg.h.
+       (new_exp): New function.
+       (new_exp_0, new_exp_2, new_exp_3): Rewritten to call new_exp.
        (new_exp_1): New function.
-       (FREE_EXPRESSION): Recognize these operators.
-       (yylex): Don't skip "\\n". Recognize '<', '>', LE, GE, '!' operators.
-       * dcigettext.c (plural_eval): Recognize these operators.
+       ('?' ':'): Make right-associative.
+       (EQUOP2): New token, replaces '=' and '!'.
+       (CMPOP2): New token.
+       (ADDOP2): New token, replaces '+' and '-'.
+       (MULOP2): New token, replaces '*', '/' and '%'.
+       ('!'): New token.
+       (exp): Add rules for CMPOP2 and '!'. Don't call YYABORT.
+       (start): Call YYABORT here.
+       (FREE_EXPRESSION): Update.
+       (yylex): Don't skip "\\n". Recognize comparison and '!' operators.
+       Update for new token symbols.
+       * loadmsgcat.c (plvar, plone, germanic_plural, init_germanic_plural):
+       Update.
+       * dcigettext.c (_nl_find_msg): Optimize for space.
+       (plural_eval): Recognize comparison and '!' operators. Optimize for
+       space.
+
+       * dcigettext.c (transcmp): New declaration.
 
 2001-03-10  Bruno Haible  <haible@clisp.cons.org>
 
index ba93fb3032e0a171f551764041c874fc65d64094..937c0fdee5c01be489f613f1ed8fda01be955704 100644 (file)
@@ -243,6 +243,7 @@ static void *root;
 # endif
 
 /* Function to compare two entries in the table of known translations.  */
+static int transcmp PARAMS ((const void *p1, const void *p2));
 static int
 transcmp (p1, p2)
      const void *p1;
@@ -685,14 +686,15 @@ _nl_find_msg (domain_file, msgid, lengthp)
       nls_uint32 hash_val = hash_string (msgid);
       nls_uint32 idx = hash_val % domain->hash_size;
       nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
-      nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
-
-      if (nstr == 0)
-       /* Hash table entry is empty.  */
-       return NULL;
 
       while (1)
        {
+         nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
+
+         if (nstr == 0)
+           /* Hash table entry is empty.  */
+           return NULL;
+
          /* Compare msgid with the original string at index nstr-1.
             We compare the lengths with >=, not ==, because plural entries
             are represented by strings with an embedded NUL.  */
@@ -710,11 +712,6 @@ _nl_find_msg (domain_file, msgid, lengthp)
            idx -= domain->hash_size - incr;
          else
            idx += incr;
-
-         nstr = W (domain->must_swap, domain->hash_tab[idx]);
-         if (nstr == 0)
-           /* Hash table entry is empty.  */
-           return NULL;
        }
       /* NOTREACHED */
     }
@@ -988,57 +985,74 @@ plural_eval (pexp, n)
      struct expression *pexp;
      unsigned long int n;
 {
-  switch (pexp->operation)
+  switch (pexp->nargs)
     {
-    case var:
-      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));
-    case divide:
-      return (plural_eval (pexp->val.args2.left, n)
-             / plural_eval (pexp->val.args2.right, n));
-    case module:
-      return (plural_eval (pexp->val.args2.left, n)
-             % plural_eval (pexp->val.args2.right, n));
-    case plus:
-      return (plural_eval (pexp->val.args2.left, n)
-             + plural_eval (pexp->val.args2.right, n));
-    case minus:
-      return (plural_eval (pexp->val.args2.left, n)
-             - plural_eval (pexp->val.args2.right, n));
-    case less_than:
-      return (plural_eval (pexp->val.args2.left, n)
-             < plural_eval (pexp->val.args2.right, n));
-    case greater_than:
-      return (plural_eval (pexp->val.args2.left, n)
-             > plural_eval (pexp->val.args2.right, n));
-    case less_or_equal:
-      return (plural_eval (pexp->val.args2.left, n)
-             <= plural_eval (pexp->val.args2.right, n));
-    case greater_or_equal:
-      return (plural_eval (pexp->val.args2.left, n)
-             >= plural_eval (pexp->val.args2.right, n));
-    case equal:
-      return (plural_eval (pexp->val.args2.left, n)
-             == plural_eval (pexp->val.args2.right, n));
-    case not_equal:
-      return (plural_eval (pexp->val.args2.left, n)
-             != plural_eval (pexp->val.args2.right, n));
-    case land:
-      return (plural_eval (pexp->val.args2.left, n)
-             && plural_eval (pexp->val.args2.right, n));
-    case lor:
-      return (plural_eval (pexp->val.args2.left, n)
-             || plural_eval (pexp->val.args2.right, n));
-    case qmop:
-      return (plural_eval (pexp->val.args3.bexp, n)
-             ? plural_eval (pexp->val.args3.tbranch, n)
-             : plural_eval (pexp->val.args3.fbranch, n));
+    case 0:
+      switch (pexp->operation)
+       {
+       case var:
+         return n;
+       case num:
+         return pexp->val.num;
+       default:
+         break;
+       }
+      /* NOTREACHED */
+      break;
+    case 1:
+      {
+       /* pexp->operation must be lnot.  */
+       unsigned long int arg = plural_eval (pexp->val.args[0], n);
+       return ! arg;
+      }
+    case 2:
+      {
+       unsigned long int leftarg = plural_eval (pexp->val.args[0], n);
+       if (pexp->operation == lor)
+         return leftarg || plural_eval (pexp->val.args[1], n);
+       else if (pexp->operation == land)
+         return leftarg && plural_eval (pexp->val.args[1], n);
+       else
+         {
+           unsigned long int rightarg = plural_eval (pexp->val.args[1], n);
+
+           switch (pexp->operation)
+             {
+             case mult:
+               return leftarg * rightarg;
+             case divide:
+               return leftarg / rightarg;
+             case module:
+               return leftarg % rightarg;
+             case plus:
+               return leftarg + rightarg;
+             case minus:
+               return leftarg - rightarg;
+             case less_than:
+               return leftarg < rightarg;
+             case greater_than:
+               return leftarg > rightarg;
+             case less_or_equal:
+               return leftarg <= rightarg;
+             case greater_or_equal:
+               return leftarg >= rightarg;
+             case equal:
+               return leftarg == rightarg;
+             case not_equal:
+               return leftarg != rightarg;
+             default:
+               break;
+             }
+         }
+       /* NOTREACHED */
+       break;
+      }
+    case 3:
+      {
+       /* pexp->operation must be qmop.  */
+       unsigned long int boolarg = plural_eval (pexp->val.args[0], n);
+       return plural_eval (pexp->val.args[boolarg ? 1 : 2], n);
+      }
     }
   /* NOTREACHED */
   return 0;
index 715b04d996c54aa231dd4618371dc874d88563ea..c7f465549dd9de1f74314b6b7d60ae2dd7db4eb1 100644 (file)
@@ -75,11 +75,15 @@ SWAP (i)
    plural form.  */
 struct expression
 {
+  int nargs;                   /* Number of arguments.  */
   enum operator
   {
+    /* Without arguments:  */
     var,                       /* The variable "n".  */
     num,                       /* Decimal number.  */
+    /* Unary operators:  */
     lnot,                      /* Logical NOT.  */
+    /* Binary operators:  */
     mult,                      /* Multiplication.  */
     divide,                    /* Division.  */
     module,                    /* Module operation.  */
@@ -89,30 +93,17 @@ struct expression
     greater_than,              /* Comparison.  */
     less_or_equal,             /* Comparison.  */
     greater_or_equal,          /* Comparison.  */
-    equal,                     /* Comparison for equality.  */
-    not_equal,                 /* Comparison for inequality.  */
+    equal,                     /* Comparision for equality.  */
+    not_equal,                 /* Comparision for inequality.  */
     land,                      /* Logical AND.  */
     lor,                       /* Logical OR.  */
+    /* Ternary operators:  */
     qmop                       /* Question mark operator.  */
   } operation;
   union
   {
     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;
-    struct
-    {
-      struct expression *bexp; /* Boolean expression in ?: operation.  */
-      struct expression *tbranch; /* True-branch in ?: operation.  */
-      struct expression *fbranch; /* False-branch in ?: operation.  */
-    } args3;
+    struct expression *args[3];        /* Up to three arguments.  */
   } val;
 };
 
index a4a1cba6cff4acfbd61ddfebb8d306d52d1af12c..7ce30892c9bb69404e7c73088cae82a4760fe20f 100644 (file)
@@ -138,10 +138,12 @@ int _nl_msg_cat_cntr;
    form determination.  It represents the expression  "n != 1".  */
 static const struct expression plvar =
 {
+  .nargs = 0,
   .operation = var,
 };
 static const struct expression plone =
 {
+  .nargs = 0,
   .operation = num,
   .val =
   {
@@ -150,13 +152,14 @@ static const struct expression plone =
 };
 static struct expression germanic_plural =
 {
+  .nargs = 2,
   .operation = not_equal,
   .val =
   {
-    .args2 =
+    .args =
     {
-      .left = (struct expression *) &plvar,
-      .right = (struct expression *) &plone
+      [0] = (struct expression *) &plvar,
+      [1] = (struct expression *) &plone
     }
   }
 };
@@ -177,14 +180,17 @@ init_germanic_plural ()
 {
   if (plone.val.num == 0)
     {
+      plvar.nargs = 0;
       plvar.operation = var;
 
+      plone.nargs = 0;
       plone.operation = num;
       plone.val.num = 1;
 
+      germanic_plural.nargs = 2;
       germanic_plural.operation = not_equal;
-      germanic_plural.val.args2.left = &plvar;
-      germanic_plural.val.args2.right = &plone;
+      germanic_plural.val.args[0] = &plvar;
+      germanic_plural.val.args[1] = &plone;
     }
 }
 
@@ -441,7 +447,7 @@ _nl_load_domain (domain_file)
          nplurals += 9;
          while (*nplurals != '\0' && isspace (*nplurals))
            ++nplurals;
-#ifdef HAVE_STRTOUL
+#if defined HAVE_STRTOUL || defined _LIBC
          n = strtoul (nplurals, &endp, 10);
 #else
          for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
index 20fb60c81c7b03fd8dfac7c60b2a4958d9ad9ef5..f50f8648dfb37732c696320c6954c28292c41258 100644 (file)
 
 %union {
   unsigned long int num;
+  enum operator op;
   struct expression *exp;
 }
 
 %{
 /* 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 PARAMS ((int nargs, enum operator op,
+                                          struct expression * const *args));
+static inline struct expression *new_exp_0 PARAMS ((enum operator op));
+static inline 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));
-static struct expression *new_exp_3 PARAMS ((enum operator op,
-                                            struct expression *bexp,
-                                            struct expression *tbranch,
-                                            struct expression *fbranch));
+static inline struct expression *new_exp_3 PARAMS ((enum operator op,
+                                                  struct expression *bexp,
+                                                  struct expression *tbranch,
+                                                  struct expression *fbranch));
 static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
 static void yyerror PARAMS ((const char *str));
+
+/* Allocation of expressions.  */
+
+static struct expression *
+new_exp (nargs, op, args)
+     int nargs;
+     enum operator op;
+     struct expression * const *args;
+{
+  int i;
+  struct expression *newp;
+
+  /* If any of the argument could not be malloc'ed, just return NULL.  */
+  for (i = nargs - 1; i >= 0; i--)
+    if (args[i] == NULL)
+      goto fail;
+
+  /* Allocate a new expression.  */
+  newp = (struct expression *) malloc (sizeof (*newp));
+  if (newp != NULL)
+    {
+      newp->nargs = nargs;
+      newp->operation = op;
+      for (i = nargs - 1; i >= 0; i--)
+       newp->val.args[i] = args[i];
+      return newp;
+    }
+
+ fail:
+  for (i = nargs - 1; i >= 0; i--)
+    FREE_EXPRESSION (args[i]);
+
+  return NULL;
+}
+
+static inline struct expression *
+new_exp_0 (op)
+     enum operator op;
+{
+  return new_exp (0, op, NULL);
+}
+
+static inline struct expression *
+new_exp_1 (op, right)
+     enum operator op;
+     struct expression *right;
+{
+  struct expression *args[1];
+
+  args[0] = right;
+  return new_exp (1, op, args);
+}
+
+static struct expression *
+new_exp_2 (op, left, right)
+     enum operator op;
+     struct expression *left;
+     struct expression *right;
+{
+  struct expression *args[2];
+
+  args[0] = left;
+  args[1] = right;
+  return new_exp (2, op, args);
+}
+
+static inline struct expression *
+new_exp_3 (op, bexp, tbranch, fbranch)
+     enum operator op;
+     struct expression *bexp;
+     struct expression *tbranch;
+     struct expression *fbranch;
+{
+  struct expression *args[3];
+
+  args[0] = bexp;
+  args[1] = tbranch;
+  args[2] = fbranch;
+  return new_exp (3, op, args);
+}
+
 %}
 
 /* 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 EQ, NE                   /*   == !=      */
-%left '<', '>', LE, GE         /*   < > <= >=  */
-%left '+', '-'                 /*   + -        */
-%left '*', '/', '%'            /*   * / %      */
-%right '!'                     /*   !          */
-
+   There is no unary minus and no bitwise operators.
+   Operators with the same syntactic behaviour have been merged into a single
+   token, to save space in the array generated by bison.  */
+%right '?'             /*   ?          */
+%left '|'              /*   ||         */
+%left '&'              /*   &&         */
+%left EQUOP2           /*   == !=      */
+%left CMPOP2           /*   < > <= >=  */
+%left ADDOP2           /*   + -        */
+%left MULOP2           /*   * / %      */
+%right '!'             /*   !          */
+
+%token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
 %token <num> NUMBER
 %type <exp> exp
 
@@ -81,194 +168,61 @@ static void yyerror PARAMS ((const char *str));
 
 start:   exp
          {
+           if ($1 == NULL)
+             YYABORT;
            ((struct parse_args *) arg)->res = $1;
          }
        ;
 
 exp:     exp '?' exp ':' exp
          {
-           if (($$ = new_exp_3 (qmop, $1, $3, $5)) == NULL)
-             YYABORT
+           $$ = new_exp_3 (qmop, $1, $3, $5);
          }
        | exp '|' exp
          {
-           if (($$ = new_exp_2 (lor, $1, $3)) == NULL)
-             YYABORT
+           $$ = new_exp_2 (lor, $1, $3);
          }
        | exp '&' exp
          {
-           if (($$ = new_exp_2 (land, $1, $3)) == NULL)
-             YYABORT
+           $$ = new_exp_2 (land, $1, $3);
          }
-       | exp EQ exp
+       | exp EQUOP2 exp
          {
-           if (($$ = new_exp_2 (equal, $1, $3)) == NULL)
-             YYABORT
+           $$ = new_exp_2 ($2, $1, $3);
          }
-       | exp NE exp
+       | exp CMPOP2 exp
          {
-           if (($$ = new_exp_2 (not_equal, $1, $3)) == NULL)
-             YYABORT
+           $$ = new_exp_2 ($2, $1, $3);
          }
-       | exp '<' exp
+       | exp ADDOP2 exp
          {
-           if (($$ = new_exp_2 (less_than, $1, $3)) == NULL)
-             YYABORT
+           $$ = new_exp_2 ($2, $1, $3);
          }
-       | exp '>' exp
+       | exp MULOP2 exp
          {
-           if (($$ = new_exp_2 (greater_than, $1, $3)) == NULL)
-             YYABORT
-         }
-       | exp LE exp
-         {
-           if (($$ = new_exp_2 (less_or_equal, $1, $3)) == NULL)
-             YYABORT
-         }
-       | exp GE exp
-         {
-           if (($$ = new_exp_2 (greater_or_equal, $1, $3)) == NULL)
-             YYABORT
-         }
-       | exp '+' exp
-         {
-           if (($$ = new_exp_2 (plus, $1, $3)) == NULL)
-             YYABORT
-         }
-       | exp '-' exp
-         {
-           if (($$ = new_exp_2 (minus, $1, $3)) == NULL)
-             YYABORT
-         }
-       | exp '*' exp
-         {
-           if (($$ = new_exp_2 (mult, $1, $3)) == NULL)
-             YYABORT
-         }
-       | exp '/' exp
-         {
-           if (($$ = new_exp_2 (divide, $1, $3)) == NULL)
-             YYABORT
-         }
-       | exp '%' exp
-         {
-           if (($$ = new_exp_2 (module, $1, $3)) == NULL)
-             YYABORT
+           $$ = new_exp_2 ($2, $1, $3);
          }
        | '!' exp
          {
-           if (($$ = new_exp_1 (lnot, $2)) == NULL)
-             YYABORT
+           $$ = new_exp_1 (lnot, $2);
          }
        | 'n'
          {
-           if (($$ = new_exp_0 (var)) == NULL)
-             YYABORT
+           $$ = new_exp_0 (var);
          }
        | NUMBER
          {
-           if (($$ = new_exp_0 (num)) == NULL)
-             YYABORT;
-           $$->val.num = $1
+           if (($$ = new_exp_0 (num)) != NULL)
+             $$->val.num = $1;
          }
        | '(' exp ')'
          {
-           $$ = $2
+           $$ = $2;
          }
        ;
 
 %%
 
-static struct expression *
-new_exp_0 (op)
-     enum operator op;
-{
-  struct expression *newp = (struct expression *) malloc (sizeof (*newp));
-
-  if (newp != NULL)
-    newp->operation = 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;
-     struct expression *left;
-     struct expression *right;
-{
-  struct expression *newp = NULL;
-
-  if (left != NULL && right != NULL)
-    newp = (struct expression *) malloc (sizeof (*newp));
-
-  if (newp != NULL)
-    {
-      newp->operation = op;
-      newp->val.args2.left = left;
-      newp->val.args2.right = right;
-    }
-  else
-    {
-      FREE_EXPRESSION (left);
-      FREE_EXPRESSION (right);
-    }
-
-  return newp;
-}
-
-static struct expression *
-new_exp_3 (op, bexp, tbranch, fbranch)
-     enum operator op;
-     struct expression *bexp;
-     struct expression *tbranch;
-     struct expression *fbranch;
-{
-  struct expression *newp = NULL;
-
-  if (bexp != NULL && tbranch != NULL && fbranch != NULL)
-    newp = (struct expression *) malloc (sizeof (*newp));
-
-  if (newp != NULL)
-    {
-      newp->operation = op;
-      newp->val.args3.bexp = bexp;
-      newp->val.args3.tbranch = tbranch;
-      newp->val.args3.fbranch = fbranch;
-    }
-  else
-    {
-      FREE_EXPRESSION (bexp);
-      FREE_EXPRESSION (tbranch);
-      FREE_EXPRESSION (fbranch);
-    }
-
-  return newp;
-}
-
 void
 internal_function
 FREE_EXPRESSION (exp)
@@ -278,37 +232,17 @@ FREE_EXPRESSION (exp)
     return;
 
   /* Handle the recursive case.  */
-  switch (exp->operation)
+  switch (exp->nargs)
     {
-    case qmop:
-      FREE_EXPRESSION (exp->val.args3.fbranch);
-      /* FREE_EXPRESSION (exp->val.args3.tbranch); */
-      /* FREE_EXPRESSION (exp->val.args3.bexp); */
-      /* break; */
-      /* instead: FALLTHROUGH */
-
-    case mult:
-    case divide:
-    case module:
-    case plus:
-    case minus:
-    case less_than:
-    case greater_than:
-    case less_or_equal:
-    case greater_or_equal:
-    case equal:
-    case not_equal:
-    case land:
-    case lor:
-      FREE_EXPRESSION (exp->val.args2.right);
-      /* FREE_EXPRESSION (exp->val.args2.left); */
-      /* break; */
-      /* instead: FALLTHROUGH */
-
-    case lnot:
-      FREE_EXPRESSION (exp->val.args1.right);
-      break;
-
+    case 3:
+      FREE_EXPRESSION (exp->val.args[2]);
+      /* FALLTHROUGH */
+    case 2:
+      FREE_EXPRESSION (exp->val.args[1]);
+      /* FALLTHROUGH */
+    case 1:
+      FREE_EXPRESSION (exp->val.args[0]);
+      /* FALLTHROUGH */
     default:
       break;
     }
@@ -361,7 +295,8 @@ yylex (lval, pexp)
       if (exp[0] == '=')
        {
          ++exp;
-         result = EQ;
+         lval->op = equal;
+         result = EQUOP2;
        }
       else
        result = YYERRCODE;
@@ -371,7 +306,8 @@ yylex (lval, pexp)
       if (exp[0] == '=')
        {
          ++exp;
-         result = NE;
+         lval->op = not_equal;
+         result = EQUOP2;
        }
       break;
 
@@ -387,24 +323,50 @@ yylex (lval, pexp)
       if (exp[0] == '=')
        {
          ++exp;
-         result = LE;
+         lval->op = less_or_equal;
        }
+      else
+       lval->op = less_than;
+      result = CMPOP2;
       break;
 
     case '>':
       if (exp[0] == '=')
        {
          ++exp;
-         result = GE;
+         lval->op = greater_or_equal;
        }
+      else
+       lval->op = greater_than;
+      result = CMPOP2;
       break;
 
-    case 'n':
     case '*':
+      lval->op = mult;
+      result = MULOP2;
+      break;
+
     case '/':
+      lval->op = divide;
+      result = MULOP2;
+      break;
+
     case '%':
+      lval->op = module;
+      result = MULOP2;
+      break;
+
     case '+':
+      lval->op = plus;
+      result = ADDOP2;
+      break;
+
     case '-':
+      lval->op = minus;
+      result = ADDOP2;
+      break;
+
+    case 'n':
     case '?':
     case ':':
     case '(':