xref: /netbsd-src/external/gpl3/gcc.old/dist/intl/plural.y (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
136ac495dSmrg %{
236ac495dSmrg /* Expression parsing for plural form selection.
3*8feb0f0bSmrg    Copyright (C) 2000-2020 Free Software Foundation, Inc.
436ac495dSmrg    Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
536ac495dSmrg 
636ac495dSmrg    This program is free software; you can redistribute it and/or modify it
736ac495dSmrg    under the terms of the GNU Library General Public License as published
836ac495dSmrg    by the Free Software Foundation; either version 2, or (at your option)
936ac495dSmrg    any later version.
1036ac495dSmrg 
1136ac495dSmrg    This program is distributed in the hope that it will be useful,
1236ac495dSmrg    but WITHOUT ANY WARRANTY; without even the implied warranty of
1336ac495dSmrg    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1436ac495dSmrg    Library General Public License for more details.
1536ac495dSmrg 
1636ac495dSmrg    You should have received a copy of the GNU Library General Public
1736ac495dSmrg    License along with this program; if not, write to the Free Software
1836ac495dSmrg    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301,
1936ac495dSmrg    USA.  */
2036ac495dSmrg 
2136ac495dSmrg /* The bison generated parser uses alloca.  AIX 3 forces us to put this
2236ac495dSmrg    declaration at the beginning of the file.  The declaration in bison's
2336ac495dSmrg    skeleton file comes too late.  This must come before <config.h>
2436ac495dSmrg    because <config.h> may include arbitrary system headers.  */
2536ac495dSmrg #if defined _AIX && !defined __GNUC__
2636ac495dSmrg  #pragma alloca
2736ac495dSmrg #endif
2836ac495dSmrg 
2936ac495dSmrg #ifdef HAVE_CONFIG_H
3036ac495dSmrg # include <config.h>
3136ac495dSmrg #endif
3236ac495dSmrg 
3336ac495dSmrg #include <stddef.h>
3436ac495dSmrg #include <stdlib.h>
3536ac495dSmrg #include "plural-exp.h"
3636ac495dSmrg 
3736ac495dSmrg /* The main function generated by the parser is called __gettextparse,
3836ac495dSmrg    but we want it to be called PLURAL_PARSE.  */
3936ac495dSmrg #ifndef _LIBC
4036ac495dSmrg # define __gettextparse PLURAL_PARSE
4136ac495dSmrg #endif
4236ac495dSmrg 
43*8feb0f0bSmrg #ifndef USE_BISON3
4436ac495dSmrg #define YYLEX_PARAM	&((struct parse_args *) arg)->cp
4536ac495dSmrg #define YYPARSE_PARAM	arg
46*8feb0f0bSmrg #endif
4736ac495dSmrg %}
4836ac495dSmrg %pure_parser
49*8feb0f0bSmrg /* BISON3 %parse-param {struct parse_args *arg} */
50*8feb0f0bSmrg /* BISON3 %lex-param {struct parse_args *arg} */
51*8feb0f0bSmrg /* BISON3 %define api.pure full */
5236ac495dSmrg %expect 7
5336ac495dSmrg 
5436ac495dSmrg %union {
5536ac495dSmrg   unsigned long int num;
5636ac495dSmrg   enum operator op;
5736ac495dSmrg   struct expression *exp;
5836ac495dSmrg }
5936ac495dSmrg 
6036ac495dSmrg %{
6136ac495dSmrg /* Prototypes for local functions.  */
6236ac495dSmrg static struct expression *new_exp PARAMS ((int nargs, enum operator op,
6336ac495dSmrg 					   struct expression * const *args));
6436ac495dSmrg static inline struct expression *new_exp_0 PARAMS ((enum operator op));
6536ac495dSmrg static inline struct expression *new_exp_1 PARAMS ((enum operator op,
6636ac495dSmrg 						   struct expression *right));
6736ac495dSmrg static struct expression *new_exp_2 PARAMS ((enum operator op,
6836ac495dSmrg 					     struct expression *left,
6936ac495dSmrg 					     struct expression *right));
7036ac495dSmrg static inline struct expression *new_exp_3 PARAMS ((enum operator op,
7136ac495dSmrg 						   struct expression *bexp,
7236ac495dSmrg 						   struct expression *tbranch,
7336ac495dSmrg 						   struct expression *fbranch));
74*8feb0f0bSmrg #ifdef USE_BISON3
75*8feb0f0bSmrg static int yylex PARAMS ((YYSTYPE *lval, struct parse_args *arg));
76*8feb0f0bSmrg static void yyerror PARAMS ((struct parse_args *arg, const char *str));
77*8feb0f0bSmrg #else
7836ac495dSmrg static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
7936ac495dSmrg static void yyerror PARAMS ((const char *str));
80*8feb0f0bSmrg #endif
8136ac495dSmrg 
8236ac495dSmrg /* Allocation of expressions.  */
8336ac495dSmrg 
8436ac495dSmrg static struct expression *
new_exp(nargs,op,args)8536ac495dSmrg new_exp (nargs, op, args)
8636ac495dSmrg      int nargs;
8736ac495dSmrg      enum operator op;
8836ac495dSmrg      struct expression * const *args;
8936ac495dSmrg {
9036ac495dSmrg   int i;
9136ac495dSmrg   struct expression *newp;
9236ac495dSmrg 
9336ac495dSmrg   /* If any of the argument could not be malloc'ed, just return NULL.  */
9436ac495dSmrg   for (i = nargs - 1; i >= 0; i--)
9536ac495dSmrg     if (args[i] == NULL)
9636ac495dSmrg       goto fail;
9736ac495dSmrg 
9836ac495dSmrg   /* Allocate a new expression.  */
9936ac495dSmrg   newp = (struct expression *) malloc (sizeof (*newp));
10036ac495dSmrg   if (newp != NULL)
10136ac495dSmrg     {
10236ac495dSmrg       newp->nargs = nargs;
10336ac495dSmrg       newp->operation = op;
10436ac495dSmrg       for (i = nargs - 1; i >= 0; i--)
10536ac495dSmrg 	newp->val.args[i] = args[i];
10636ac495dSmrg       return newp;
10736ac495dSmrg     }
10836ac495dSmrg 
10936ac495dSmrg  fail:
11036ac495dSmrg   for (i = nargs - 1; i >= 0; i--)
11136ac495dSmrg     FREE_EXPRESSION (args[i]);
11236ac495dSmrg 
11336ac495dSmrg   return NULL;
11436ac495dSmrg }
11536ac495dSmrg 
11636ac495dSmrg static inline struct expression *
new_exp_0(op)11736ac495dSmrg new_exp_0 (op)
11836ac495dSmrg      enum operator op;
11936ac495dSmrg {
12036ac495dSmrg   return new_exp (0, op, NULL);
12136ac495dSmrg }
12236ac495dSmrg 
12336ac495dSmrg static inline struct expression *
new_exp_1(op,right)12436ac495dSmrg new_exp_1 (op, right)
12536ac495dSmrg      enum operator op;
12636ac495dSmrg      struct expression *right;
12736ac495dSmrg {
12836ac495dSmrg   struct expression *args[1];
12936ac495dSmrg 
13036ac495dSmrg   args[0] = right;
13136ac495dSmrg   return new_exp (1, op, args);
13236ac495dSmrg }
13336ac495dSmrg 
13436ac495dSmrg static struct expression *
new_exp_2(op,left,right)13536ac495dSmrg new_exp_2 (op, left, right)
13636ac495dSmrg      enum operator op;
13736ac495dSmrg      struct expression *left;
13836ac495dSmrg      struct expression *right;
13936ac495dSmrg {
14036ac495dSmrg   struct expression *args[2];
14136ac495dSmrg 
14236ac495dSmrg   args[0] = left;
14336ac495dSmrg   args[1] = right;
14436ac495dSmrg   return new_exp (2, op, args);
14536ac495dSmrg }
14636ac495dSmrg 
14736ac495dSmrg static inline struct expression *
new_exp_3(op,bexp,tbranch,fbranch)14836ac495dSmrg new_exp_3 (op, bexp, tbranch, fbranch)
14936ac495dSmrg      enum operator op;
15036ac495dSmrg      struct expression *bexp;
15136ac495dSmrg      struct expression *tbranch;
15236ac495dSmrg      struct expression *fbranch;
15336ac495dSmrg {
15436ac495dSmrg   struct expression *args[3];
15536ac495dSmrg 
15636ac495dSmrg   args[0] = bexp;
15736ac495dSmrg   args[1] = tbranch;
15836ac495dSmrg   args[2] = fbranch;
15936ac495dSmrg   return new_exp (3, op, args);
16036ac495dSmrg }
16136ac495dSmrg 
16236ac495dSmrg %}
16336ac495dSmrg 
16436ac495dSmrg /* This declares that all operators have the same associativity and the
16536ac495dSmrg    precedence order as in C.  See [Harbison, Steele: C, A Reference Manual].
16636ac495dSmrg    There is no unary minus and no bitwise operators.
16736ac495dSmrg    Operators with the same syntactic behaviour have been merged into a single
16836ac495dSmrg    token, to save space in the array generated by bison.  */
16936ac495dSmrg %right '?'		/*   ?		*/
17036ac495dSmrg %left '|'		/*   ||		*/
17136ac495dSmrg %left '&'		/*   &&		*/
17236ac495dSmrg %left EQUOP2		/*   == !=	*/
17336ac495dSmrg %left CMPOP2		/*   < > <= >=	*/
17436ac495dSmrg %left ADDOP2		/*   + -	*/
17536ac495dSmrg %left MULOP2		/*   * / %	*/
17636ac495dSmrg %right '!'		/*   !		*/
17736ac495dSmrg 
17836ac495dSmrg %token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
17936ac495dSmrg %token <num> NUMBER
18036ac495dSmrg %type <exp> exp
18136ac495dSmrg 
18236ac495dSmrg %%
18336ac495dSmrg 
18436ac495dSmrg start:	  exp
18536ac495dSmrg 	  {
18636ac495dSmrg 	    if ($1 == NULL)
18736ac495dSmrg 	      YYABORT;
18836ac495dSmrg 	    ((struct parse_args *) arg)->res = $1;
18936ac495dSmrg 	  }
19036ac495dSmrg 	;
19136ac495dSmrg 
19236ac495dSmrg exp:	  exp '?' exp ':' exp
19336ac495dSmrg 	  {
19436ac495dSmrg 	    $$ = new_exp_3 (qmop, $1, $3, $5);
19536ac495dSmrg 	  }
19636ac495dSmrg 	| exp '|' exp
19736ac495dSmrg 	  {
19836ac495dSmrg 	    $$ = new_exp_2 (lor, $1, $3);
19936ac495dSmrg 	  }
20036ac495dSmrg 	| exp '&' exp
20136ac495dSmrg 	  {
20236ac495dSmrg 	    $$ = new_exp_2 (land, $1, $3);
20336ac495dSmrg 	  }
20436ac495dSmrg 	| exp EQUOP2 exp
20536ac495dSmrg 	  {
20636ac495dSmrg 	    $$ = new_exp_2 ($2, $1, $3);
20736ac495dSmrg 	  }
20836ac495dSmrg 	| exp CMPOP2 exp
20936ac495dSmrg 	  {
21036ac495dSmrg 	    $$ = new_exp_2 ($2, $1, $3);
21136ac495dSmrg 	  }
21236ac495dSmrg 	| exp ADDOP2 exp
21336ac495dSmrg 	  {
21436ac495dSmrg 	    $$ = new_exp_2 ($2, $1, $3);
21536ac495dSmrg 	  }
21636ac495dSmrg 	| exp MULOP2 exp
21736ac495dSmrg 	  {
21836ac495dSmrg 	    $$ = new_exp_2 ($2, $1, $3);
21936ac495dSmrg 	  }
22036ac495dSmrg 	| '!' exp
22136ac495dSmrg 	  {
22236ac495dSmrg 	    $$ = new_exp_1 (lnot, $2);
22336ac495dSmrg 	  }
22436ac495dSmrg 	| 'n'
22536ac495dSmrg 	  {
22636ac495dSmrg 	    $$ = new_exp_0 (var);
22736ac495dSmrg 	  }
22836ac495dSmrg 	| NUMBER
22936ac495dSmrg 	  {
23036ac495dSmrg 	    if (($$ = new_exp_0 (num)) != NULL)
23136ac495dSmrg 	      $$->val.num = $1;
23236ac495dSmrg 	  }
23336ac495dSmrg 	| '(' exp ')'
23436ac495dSmrg 	  {
23536ac495dSmrg 	    $$ = $2;
23636ac495dSmrg 	  }
23736ac495dSmrg 	;
23836ac495dSmrg 
23936ac495dSmrg %%
24036ac495dSmrg 
24136ac495dSmrg void
24236ac495dSmrg internal_function
FREE_EXPRESSION(exp)24336ac495dSmrg FREE_EXPRESSION (exp)
24436ac495dSmrg      struct expression *exp;
24536ac495dSmrg {
24636ac495dSmrg   if (exp == NULL)
24736ac495dSmrg     return;
24836ac495dSmrg 
24936ac495dSmrg   /* Handle the recursive case.  */
25036ac495dSmrg   switch (exp->nargs)
25136ac495dSmrg     {
25236ac495dSmrg     case 3:
25336ac495dSmrg       FREE_EXPRESSION (exp->val.args[2]);
25436ac495dSmrg       /* FALLTHROUGH */
25536ac495dSmrg     case 2:
25636ac495dSmrg       FREE_EXPRESSION (exp->val.args[1]);
25736ac495dSmrg       /* FALLTHROUGH */
25836ac495dSmrg     case 1:
25936ac495dSmrg       FREE_EXPRESSION (exp->val.args[0]);
26036ac495dSmrg       /* FALLTHROUGH */
26136ac495dSmrg     default:
26236ac495dSmrg       break;
26336ac495dSmrg     }
26436ac495dSmrg 
26536ac495dSmrg   free (exp);
26636ac495dSmrg }
26736ac495dSmrg 
26836ac495dSmrg 
269*8feb0f0bSmrg #ifdef USE_BISON3
270*8feb0f0bSmrg static int
yylex(lval,arg)271*8feb0f0bSmrg yylex (lval, arg)
272*8feb0f0bSmrg      YYSTYPE *lval;
273*8feb0f0bSmrg      struct parse_args *arg;
274*8feb0f0bSmrg {
275*8feb0f0bSmrg   const char **pexp = &arg->cp;
276*8feb0f0bSmrg #else
27736ac495dSmrg static int
27836ac495dSmrg yylex (lval, pexp)
27936ac495dSmrg      YYSTYPE *lval;
28036ac495dSmrg      const char **pexp;
28136ac495dSmrg {
282*8feb0f0bSmrg #endif
28336ac495dSmrg   const char *exp = *pexp;
28436ac495dSmrg   int result;
28536ac495dSmrg 
28636ac495dSmrg   while (1)
28736ac495dSmrg     {
28836ac495dSmrg       if (exp[0] == '\0')
28936ac495dSmrg 	{
29036ac495dSmrg 	  *pexp = exp;
29136ac495dSmrg 	  return YYEOF;
29236ac495dSmrg 	}
29336ac495dSmrg 
29436ac495dSmrg       if (exp[0] != ' ' && exp[0] != '\t')
29536ac495dSmrg 	break;
29636ac495dSmrg 
29736ac495dSmrg       ++exp;
29836ac495dSmrg     }
29936ac495dSmrg 
30036ac495dSmrg   result = *exp++;
30136ac495dSmrg   switch (result)
30236ac495dSmrg     {
30336ac495dSmrg     case '0': case '1': case '2': case '3': case '4':
30436ac495dSmrg     case '5': case '6': case '7': case '8': case '9':
30536ac495dSmrg       {
30636ac495dSmrg 	unsigned long int n = result - '0';
30736ac495dSmrg 	while (exp[0] >= '0' && exp[0] <= '9')
30836ac495dSmrg 	  {
30936ac495dSmrg 	    n *= 10;
31036ac495dSmrg 	    n += exp[0] - '0';
31136ac495dSmrg 	    ++exp;
31236ac495dSmrg 	  }
31336ac495dSmrg 	lval->num = n;
31436ac495dSmrg 	result = NUMBER;
31536ac495dSmrg       }
31636ac495dSmrg       break;
31736ac495dSmrg 
31836ac495dSmrg     case '=':
31936ac495dSmrg       if (exp[0] == '=')
32036ac495dSmrg 	{
32136ac495dSmrg 	  ++exp;
32236ac495dSmrg 	  lval->op = equal;
32336ac495dSmrg 	  result = EQUOP2;
32436ac495dSmrg 	}
32536ac495dSmrg       else
32636ac495dSmrg 	result = YYERRCODE;
32736ac495dSmrg       break;
32836ac495dSmrg 
32936ac495dSmrg     case '!':
33036ac495dSmrg       if (exp[0] == '=')
33136ac495dSmrg 	{
33236ac495dSmrg 	  ++exp;
33336ac495dSmrg 	  lval->op = not_equal;
33436ac495dSmrg 	  result = EQUOP2;
33536ac495dSmrg 	}
33636ac495dSmrg       break;
33736ac495dSmrg 
33836ac495dSmrg     case '&':
33936ac495dSmrg     case '|':
34036ac495dSmrg       if (exp[0] == result)
34136ac495dSmrg 	++exp;
34236ac495dSmrg       else
34336ac495dSmrg 	result = YYERRCODE;
34436ac495dSmrg       break;
34536ac495dSmrg 
34636ac495dSmrg     case '<':
34736ac495dSmrg       if (exp[0] == '=')
34836ac495dSmrg 	{
34936ac495dSmrg 	  ++exp;
35036ac495dSmrg 	  lval->op = less_or_equal;
35136ac495dSmrg 	}
35236ac495dSmrg       else
35336ac495dSmrg 	lval->op = less_than;
35436ac495dSmrg       result = CMPOP2;
35536ac495dSmrg       break;
35636ac495dSmrg 
35736ac495dSmrg     case '>':
35836ac495dSmrg       if (exp[0] == '=')
35936ac495dSmrg 	{
36036ac495dSmrg 	  ++exp;
36136ac495dSmrg 	  lval->op = greater_or_equal;
36236ac495dSmrg 	}
36336ac495dSmrg       else
36436ac495dSmrg 	lval->op = greater_than;
36536ac495dSmrg       result = CMPOP2;
36636ac495dSmrg       break;
36736ac495dSmrg 
36836ac495dSmrg     case '*':
36936ac495dSmrg       lval->op = mult;
37036ac495dSmrg       result = MULOP2;
37136ac495dSmrg       break;
37236ac495dSmrg 
37336ac495dSmrg     case '/':
37436ac495dSmrg       lval->op = divide;
37536ac495dSmrg       result = MULOP2;
37636ac495dSmrg       break;
37736ac495dSmrg 
37836ac495dSmrg     case '%':
37936ac495dSmrg       lval->op = module;
38036ac495dSmrg       result = MULOP2;
38136ac495dSmrg       break;
38236ac495dSmrg 
38336ac495dSmrg     case '+':
38436ac495dSmrg       lval->op = plus;
38536ac495dSmrg       result = ADDOP2;
38636ac495dSmrg       break;
38736ac495dSmrg 
38836ac495dSmrg     case '-':
38936ac495dSmrg       lval->op = minus;
39036ac495dSmrg       result = ADDOP2;
39136ac495dSmrg       break;
39236ac495dSmrg 
39336ac495dSmrg     case 'n':
39436ac495dSmrg     case '?':
39536ac495dSmrg     case ':':
39636ac495dSmrg     case '(':
39736ac495dSmrg     case ')':
39836ac495dSmrg       /* Nothing, just return the character.  */
39936ac495dSmrg       break;
40036ac495dSmrg 
40136ac495dSmrg     case ';':
40236ac495dSmrg     case '\n':
40336ac495dSmrg     case '\0':
40436ac495dSmrg       /* Be safe and let the user call this function again.  */
40536ac495dSmrg       --exp;
40636ac495dSmrg       result = YYEOF;
40736ac495dSmrg       break;
40836ac495dSmrg 
40936ac495dSmrg     default:
41036ac495dSmrg       result = YYERRCODE;
41136ac495dSmrg #if YYDEBUG != 0
41236ac495dSmrg       --exp;
41336ac495dSmrg #endif
41436ac495dSmrg       break;
41536ac495dSmrg     }
41636ac495dSmrg 
41736ac495dSmrg   *pexp = exp;
41836ac495dSmrg 
41936ac495dSmrg   return result;
42036ac495dSmrg }
42136ac495dSmrg 
42236ac495dSmrg 
423*8feb0f0bSmrg #ifdef USE_BISON3
424*8feb0f0bSmrg static void
yyerror(arg,str)425*8feb0f0bSmrg yyerror (arg, str)
426*8feb0f0bSmrg      struct parse_args *arg;
427*8feb0f0bSmrg #else
42836ac495dSmrg static void
42936ac495dSmrg yyerror (str)
430*8feb0f0bSmrg #endif
43136ac495dSmrg      const char *str;
43236ac495dSmrg {
43336ac495dSmrg   /* Do nothing.  We don't print error messages here.  */
43436ac495dSmrg }
435