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