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