Home | History | Annotate | Line # | Download | only in intl
      1  1.1  mrg %{
      2  1.1  mrg /* Expression parsing for plural form selection.
      3  1.8  mrg    Copyright (C) 2000-2020 Free Software Foundation, Inc.
      4  1.1  mrg    Written by Ulrich Drepper <drepper (at) cygnus.com>, 2000.
      5  1.1  mrg 
      6  1.1  mrg    This program is free software; you can redistribute it and/or modify it
      7  1.1  mrg    under the terms of the GNU Library General Public License as published
      8  1.1  mrg    by the Free Software Foundation; either version 2, or (at your option)
      9  1.1  mrg    any later version.
     10  1.1  mrg 
     11  1.1  mrg    This program is distributed in the hope that it will be useful,
     12  1.1  mrg    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  1.1  mrg    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  1.1  mrg    Library General Public License for more details.
     15  1.1  mrg 
     16  1.1  mrg    You should have received a copy of the GNU Library General Public
     17  1.1  mrg    License along with this program; if not, write to the Free Software
     18  1.1  mrg    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301,
     19  1.1  mrg    USA.  */
     20  1.1  mrg 
     21  1.1  mrg /* The bison generated parser uses alloca.  AIX 3 forces us to put this
     22  1.1  mrg    declaration at the beginning of the file.  The declaration in bison's
     23  1.1  mrg    skeleton file comes too late.  This must come before <config.h>
     24  1.1  mrg    because <config.h> may include arbitrary system headers.  */
     25  1.1  mrg #if defined _AIX && !defined __GNUC__
     26  1.1  mrg  #pragma alloca
     27  1.1  mrg #endif
     28  1.1  mrg 
     29  1.1  mrg #ifdef HAVE_CONFIG_H
     30  1.1  mrg # include <config.h>
     31  1.1  mrg #endif
     32  1.1  mrg 
     33  1.1  mrg #include <stddef.h>
     34  1.1  mrg #include <stdlib.h>
     35  1.1  mrg #include "plural-exp.h"
     36  1.1  mrg 
     37  1.1  mrg /* The main function generated by the parser is called __gettextparse,
     38  1.1  mrg    but we want it to be called PLURAL_PARSE.  */
     39  1.1  mrg #ifndef _LIBC
     40  1.1  mrg # define __gettextparse PLURAL_PARSE
     41  1.1  mrg #endif
     42  1.1  mrg 
     43  1.8  mrg #ifndef USE_BISON3
     44  1.1  mrg #define YYLEX_PARAM	&((struct parse_args *) arg)->cp
     45  1.1  mrg #define YYPARSE_PARAM	arg
     46  1.8  mrg #endif
     47  1.1  mrg %}
     48  1.1  mrg %pure_parser
     49  1.8  mrg /* BISON3 %parse-param {struct parse_args *arg} */
     50  1.8  mrg /* BISON3 %lex-param {struct parse_args *arg} */
     51  1.8  mrg /* BISON3 %define api.pure full */
     52  1.1  mrg %expect 7
     53  1.1  mrg 
     54  1.1  mrg %union {
     55  1.1  mrg   unsigned long int num;
     56  1.1  mrg   enum operator op;
     57  1.1  mrg   struct expression *exp;
     58  1.1  mrg }
     59  1.1  mrg 
     60  1.1  mrg %{
     61  1.1  mrg /* Prototypes for local functions.  */
     62  1.1  mrg static struct expression *new_exp PARAMS ((int nargs, enum operator op,
     63  1.1  mrg 					   struct expression * const *args));
     64  1.1  mrg static inline struct expression *new_exp_0 PARAMS ((enum operator op));
     65  1.1  mrg static inline struct expression *new_exp_1 PARAMS ((enum operator op,
     66  1.1  mrg 						   struct expression *right));
     67  1.1  mrg static struct expression *new_exp_2 PARAMS ((enum operator op,
     68  1.1  mrg 					     struct expression *left,
     69  1.1  mrg 					     struct expression *right));
     70  1.1  mrg static inline struct expression *new_exp_3 PARAMS ((enum operator op,
     71  1.1  mrg 						   struct expression *bexp,
     72  1.1  mrg 						   struct expression *tbranch,
     73  1.1  mrg 						   struct expression *fbranch));
     74  1.8  mrg #ifdef USE_BISON3
     75  1.8  mrg static int yylex PARAMS ((YYSTYPE *lval, struct parse_args *arg));
     76  1.8  mrg static void yyerror PARAMS ((struct parse_args *arg, const char *str));
     77  1.8  mrg #else
     78  1.1  mrg static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
     79  1.1  mrg static void yyerror PARAMS ((const char *str));
     80  1.8  mrg #endif
     81  1.1  mrg 
     82  1.1  mrg /* Allocation of expressions.  */
     83  1.1  mrg 
     84  1.1  mrg static struct expression *
     85  1.1  mrg new_exp (nargs, op, args)
     86  1.1  mrg      int nargs;
     87  1.1  mrg      enum operator op;
     88  1.1  mrg      struct expression * const *args;
     89  1.1  mrg {
     90  1.1  mrg   int i;
     91  1.1  mrg   struct expression *newp;
     92  1.1  mrg 
     93  1.1  mrg   /* If any of the argument could not be malloc'ed, just return NULL.  */
     94  1.1  mrg   for (i = nargs - 1; i >= 0; i--)
     95  1.1  mrg     if (args[i] == NULL)
     96  1.1  mrg       goto fail;
     97  1.1  mrg 
     98  1.1  mrg   /* Allocate a new expression.  */
     99  1.1  mrg   newp = (struct expression *) malloc (sizeof (*newp));
    100  1.1  mrg   if (newp != NULL)
    101  1.1  mrg     {
    102  1.1  mrg       newp->nargs = nargs;
    103  1.1  mrg       newp->operation = op;
    104  1.1  mrg       for (i = nargs - 1; i >= 0; i--)
    105  1.1  mrg 	newp->val.args[i] = args[i];
    106  1.1  mrg       return newp;
    107  1.1  mrg     }
    108  1.1  mrg 
    109  1.1  mrg  fail:
    110  1.1  mrg   for (i = nargs - 1; i >= 0; i--)
    111  1.1  mrg     FREE_EXPRESSION (args[i]);
    112  1.1  mrg 
    113  1.1  mrg   return NULL;
    114  1.1  mrg }
    115  1.1  mrg 
    116  1.1  mrg static inline struct expression *
    117  1.1  mrg new_exp_0 (op)
    118  1.1  mrg      enum operator op;
    119  1.1  mrg {
    120  1.1  mrg   return new_exp (0, op, NULL);
    121  1.1  mrg }
    122  1.1  mrg 
    123  1.1  mrg static inline struct expression *
    124  1.1  mrg new_exp_1 (op, right)
    125  1.1  mrg      enum operator op;
    126  1.1  mrg      struct expression *right;
    127  1.1  mrg {
    128  1.1  mrg   struct expression *args[1];
    129  1.1  mrg 
    130  1.1  mrg   args[0] = right;
    131  1.1  mrg   return new_exp (1, op, args);
    132  1.1  mrg }
    133  1.1  mrg 
    134  1.1  mrg static struct expression *
    135  1.1  mrg new_exp_2 (op, left, right)
    136  1.1  mrg      enum operator op;
    137  1.1  mrg      struct expression *left;
    138  1.1  mrg      struct expression *right;
    139  1.1  mrg {
    140  1.1  mrg   struct expression *args[2];
    141  1.1  mrg 
    142  1.1  mrg   args[0] = left;
    143  1.1  mrg   args[1] = right;
    144  1.1  mrg   return new_exp (2, op, args);
    145  1.1  mrg }
    146  1.1  mrg 
    147  1.1  mrg static inline struct expression *
    148  1.1  mrg new_exp_3 (op, bexp, tbranch, fbranch)
    149  1.1  mrg      enum operator op;
    150  1.1  mrg      struct expression *bexp;
    151  1.1  mrg      struct expression *tbranch;
    152  1.1  mrg      struct expression *fbranch;
    153  1.1  mrg {
    154  1.1  mrg   struct expression *args[3];
    155  1.1  mrg 
    156  1.1  mrg   args[0] = bexp;
    157  1.1  mrg   args[1] = tbranch;
    158  1.1  mrg   args[2] = fbranch;
    159  1.1  mrg   return new_exp (3, op, args);
    160  1.1  mrg }
    161  1.1  mrg 
    162  1.1  mrg %}
    163  1.1  mrg 
    164  1.1  mrg /* This declares that all operators have the same associativity and the
    165  1.1  mrg    precedence order as in C.  See [Harbison, Steele: C, A Reference Manual].
    166  1.1  mrg    There is no unary minus and no bitwise operators.
    167  1.1  mrg    Operators with the same syntactic behaviour have been merged into a single
    168  1.1  mrg    token, to save space in the array generated by bison.  */
    169  1.1  mrg %right '?'		/*   ?		*/
    170  1.1  mrg %left '|'		/*   ||		*/
    171  1.1  mrg %left '&'		/*   &&		*/
    172  1.1  mrg %left EQUOP2		/*   == !=	*/
    173  1.1  mrg %left CMPOP2		/*   < > <= >=	*/
    174  1.1  mrg %left ADDOP2		/*   + -	*/
    175  1.1  mrg %left MULOP2		/*   * / %	*/
    176  1.1  mrg %right '!'		/*   !		*/
    177  1.1  mrg 
    178  1.1  mrg %token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
    179  1.1  mrg %token <num> NUMBER
    180  1.1  mrg %type <exp> exp
    181  1.1  mrg 
    182  1.1  mrg %%
    183  1.1  mrg 
    184  1.1  mrg start:	  exp
    185  1.1  mrg 	  {
    186  1.1  mrg 	    if ($1 == NULL)
    187  1.1  mrg 	      YYABORT;
    188  1.1  mrg 	    ((struct parse_args *) arg)->res = $1;
    189  1.1  mrg 	  }
    190  1.1  mrg 	;
    191  1.1  mrg 
    192  1.1  mrg exp:	  exp '?' exp ':' exp
    193  1.1  mrg 	  {
    194  1.1  mrg 	    $$ = new_exp_3 (qmop, $1, $3, $5);
    195  1.1  mrg 	  }
    196  1.1  mrg 	| exp '|' exp
    197  1.1  mrg 	  {
    198  1.1  mrg 	    $$ = new_exp_2 (lor, $1, $3);
    199  1.1  mrg 	  }
    200  1.1  mrg 	| exp '&' exp
    201  1.1  mrg 	  {
    202  1.1  mrg 	    $$ = new_exp_2 (land, $1, $3);
    203  1.1  mrg 	  }
    204  1.1  mrg 	| exp EQUOP2 exp
    205  1.1  mrg 	  {
    206  1.1  mrg 	    $$ = new_exp_2 ($2, $1, $3);
    207  1.1  mrg 	  }
    208  1.1  mrg 	| exp CMPOP2 exp
    209  1.1  mrg 	  {
    210  1.1  mrg 	    $$ = new_exp_2 ($2, $1, $3);
    211  1.1  mrg 	  }
    212  1.1  mrg 	| exp ADDOP2 exp
    213  1.1  mrg 	  {
    214  1.1  mrg 	    $$ = new_exp_2 ($2, $1, $3);
    215  1.1  mrg 	  }
    216  1.1  mrg 	| exp MULOP2 exp
    217  1.1  mrg 	  {
    218  1.1  mrg 	    $$ = new_exp_2 ($2, $1, $3);
    219  1.1  mrg 	  }
    220  1.1  mrg 	| '!' exp
    221  1.1  mrg 	  {
    222  1.1  mrg 	    $$ = new_exp_1 (lnot, $2);
    223  1.1  mrg 	  }
    224  1.1  mrg 	| 'n'
    225  1.1  mrg 	  {
    226  1.1  mrg 	    $$ = new_exp_0 (var);
    227  1.1  mrg 	  }
    228  1.1  mrg 	| NUMBER
    229  1.1  mrg 	  {
    230  1.1  mrg 	    if (($$ = new_exp_0 (num)) != NULL)
    231  1.1  mrg 	      $$->val.num = $1;
    232  1.1  mrg 	  }
    233  1.1  mrg 	| '(' exp ')'
    234  1.1  mrg 	  {
    235  1.1  mrg 	    $$ = $2;
    236  1.1  mrg 	  }
    237  1.1  mrg 	;
    238  1.1  mrg 
    239  1.1  mrg %%
    240  1.1  mrg 
    241  1.1  mrg void
    242  1.1  mrg internal_function
    243  1.1  mrg FREE_EXPRESSION (exp)
    244  1.1  mrg      struct expression *exp;
    245  1.1  mrg {
    246  1.1  mrg   if (exp == NULL)
    247  1.1  mrg     return;
    248  1.1  mrg 
    249  1.1  mrg   /* Handle the recursive case.  */
    250  1.1  mrg   switch (exp->nargs)
    251  1.1  mrg     {
    252  1.1  mrg     case 3:
    253  1.1  mrg       FREE_EXPRESSION (exp->val.args[2]);
    254  1.1  mrg       /* FALLTHROUGH */
    255  1.1  mrg     case 2:
    256  1.1  mrg       FREE_EXPRESSION (exp->val.args[1]);
    257  1.1  mrg       /* FALLTHROUGH */
    258  1.1  mrg     case 1:
    259  1.1  mrg       FREE_EXPRESSION (exp->val.args[0]);
    260  1.1  mrg       /* FALLTHROUGH */
    261  1.1  mrg     default:
    262  1.1  mrg       break;
    263  1.1  mrg     }
    264  1.1  mrg 
    265  1.1  mrg   free (exp);
    266  1.1  mrg }
    267  1.1  mrg 
    268  1.1  mrg 
    269  1.8  mrg #ifdef USE_BISON3
    270  1.8  mrg static int
    271  1.8  mrg yylex (lval, arg)
    272  1.8  mrg      YYSTYPE *lval;
    273  1.8  mrg      struct parse_args *arg;
    274  1.8  mrg {
    275  1.8  mrg   const char **pexp = &arg->cp;
    276  1.8  mrg #else
    277  1.1  mrg static int
    278  1.1  mrg yylex (lval, pexp)
    279  1.1  mrg      YYSTYPE *lval;
    280  1.1  mrg      const char **pexp;
    281  1.1  mrg {
    282  1.8  mrg #endif
    283  1.1  mrg   const char *exp = *pexp;
    284  1.1  mrg   int result;
    285  1.1  mrg 
    286  1.1  mrg   while (1)
    287  1.1  mrg     {
    288  1.1  mrg       if (exp[0] == '\0')
    289  1.1  mrg 	{
    290  1.1  mrg 	  *pexp = exp;
    291  1.1  mrg 	  return YYEOF;
    292  1.1  mrg 	}
    293  1.1  mrg 
    294  1.1  mrg       if (exp[0] != ' ' && exp[0] != '\t')
    295  1.1  mrg 	break;
    296  1.1  mrg 
    297  1.1  mrg       ++exp;
    298  1.1  mrg     }
    299  1.1  mrg 
    300  1.1  mrg   result = *exp++;
    301  1.1  mrg   switch (result)
    302  1.1  mrg     {
    303  1.1  mrg     case '0': case '1': case '2': case '3': case '4':
    304  1.1  mrg     case '5': case '6': case '7': case '8': case '9':
    305  1.1  mrg       {
    306  1.1  mrg 	unsigned long int n = result - '0';
    307  1.1  mrg 	while (exp[0] >= '0' && exp[0] <= '9')
    308  1.1  mrg 	  {
    309  1.1  mrg 	    n *= 10;
    310  1.1  mrg 	    n += exp[0] - '0';
    311  1.1  mrg 	    ++exp;
    312  1.1  mrg 	  }
    313  1.1  mrg 	lval->num = n;
    314  1.1  mrg 	result = NUMBER;
    315  1.1  mrg       }
    316  1.1  mrg       break;
    317  1.1  mrg 
    318  1.1  mrg     case '=':
    319  1.1  mrg       if (exp[0] == '=')
    320  1.1  mrg 	{
    321  1.1  mrg 	  ++exp;
    322  1.1  mrg 	  lval->op = equal;
    323  1.1  mrg 	  result = EQUOP2;
    324  1.1  mrg 	}
    325  1.1  mrg       else
    326  1.1  mrg 	result = YYERRCODE;
    327  1.1  mrg       break;
    328  1.1  mrg 
    329  1.1  mrg     case '!':
    330  1.1  mrg       if (exp[0] == '=')
    331  1.1  mrg 	{
    332  1.1  mrg 	  ++exp;
    333  1.1  mrg 	  lval->op = not_equal;
    334  1.1  mrg 	  result = EQUOP2;
    335  1.1  mrg 	}
    336  1.1  mrg       break;
    337  1.1  mrg 
    338  1.1  mrg     case '&':
    339  1.1  mrg     case '|':
    340  1.1  mrg       if (exp[0] == result)
    341  1.1  mrg 	++exp;
    342  1.1  mrg       else
    343  1.1  mrg 	result = YYERRCODE;
    344  1.1  mrg       break;
    345  1.1  mrg 
    346  1.1  mrg     case '<':
    347  1.1  mrg       if (exp[0] == '=')
    348  1.1  mrg 	{
    349  1.1  mrg 	  ++exp;
    350  1.1  mrg 	  lval->op = less_or_equal;
    351  1.1  mrg 	}
    352  1.1  mrg       else
    353  1.1  mrg 	lval->op = less_than;
    354  1.1  mrg       result = CMPOP2;
    355  1.1  mrg       break;
    356  1.1  mrg 
    357  1.1  mrg     case '>':
    358  1.1  mrg       if (exp[0] == '=')
    359  1.1  mrg 	{
    360  1.1  mrg 	  ++exp;
    361  1.1  mrg 	  lval->op = greater_or_equal;
    362  1.1  mrg 	}
    363  1.1  mrg       else
    364  1.1  mrg 	lval->op = greater_than;
    365  1.1  mrg       result = CMPOP2;
    366  1.1  mrg       break;
    367  1.1  mrg 
    368  1.1  mrg     case '*':
    369  1.1  mrg       lval->op = mult;
    370  1.1  mrg       result = MULOP2;
    371  1.1  mrg       break;
    372  1.1  mrg 
    373  1.1  mrg     case '/':
    374  1.1  mrg       lval->op = divide;
    375  1.1  mrg       result = MULOP2;
    376  1.1  mrg       break;
    377  1.1  mrg 
    378  1.1  mrg     case '%':
    379  1.1  mrg       lval->op = module;
    380  1.1  mrg       result = MULOP2;
    381  1.1  mrg       break;
    382  1.1  mrg 
    383  1.1  mrg     case '+':
    384  1.1  mrg       lval->op = plus;
    385  1.1  mrg       result = ADDOP2;
    386  1.1  mrg       break;
    387  1.1  mrg 
    388  1.1  mrg     case '-':
    389  1.1  mrg       lval->op = minus;
    390  1.1  mrg       result = ADDOP2;
    391  1.1  mrg       break;
    392  1.1  mrg 
    393  1.1  mrg     case 'n':
    394  1.1  mrg     case '?':
    395  1.1  mrg     case ':':
    396  1.1  mrg     case '(':
    397  1.1  mrg     case ')':
    398  1.1  mrg       /* Nothing, just return the character.  */
    399  1.1  mrg       break;
    400  1.1  mrg 
    401  1.1  mrg     case ';':
    402  1.1  mrg     case '\n':
    403  1.1  mrg     case '\0':
    404  1.1  mrg       /* Be safe and let the user call this function again.  */
    405  1.1  mrg       --exp;
    406  1.1  mrg       result = YYEOF;
    407  1.1  mrg       break;
    408  1.1  mrg 
    409  1.1  mrg     default:
    410  1.1  mrg       result = YYERRCODE;
    411  1.1  mrg #if YYDEBUG != 0
    412  1.1  mrg       --exp;
    413  1.1  mrg #endif
    414  1.1  mrg       break;
    415  1.1  mrg     }
    416  1.1  mrg 
    417  1.1  mrg   *pexp = exp;
    418  1.1  mrg 
    419  1.1  mrg   return result;
    420  1.1  mrg }
    421  1.1  mrg 
    422  1.1  mrg 
    423  1.8  mrg #ifdef USE_BISON3
    424  1.8  mrg static void
    425  1.8  mrg yyerror (arg, str)
    426  1.8  mrg      struct parse_args *arg;
    427  1.8  mrg #else
    428  1.1  mrg static void
    429  1.1  mrg yyerror (str)
    430  1.8  mrg #endif
    431  1.1  mrg      const char *str;
    432  1.1  mrg {
    433  1.1  mrg   /* Do nothing.  We don't print error messages here.  */
    434  1.1  mrg }
    435