Merged changes made for version 4.1.20 onto the trunk
[findutils.git] / intl / plural.y
blobc6d2de344abb0ef3a6f51787cbb606be8ca68e54
1 %{
2 /* Expression parsing for plural form selection.
3 Copyright (C) 2000, 2001 Free Software Foundation, Inc.
4 Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 /* The bison generated parser uses alloca. AIX 3 forces us to put this
21 declaration at the beginning of the file. The declaration in bison's
22 skeleton file comes too late. This must come before <config.h>
23 because <config.h> may include arbitrary system headers. */
24 #if defined _AIX && !defined __GNUC__
25 #pragma alloca
26 #endif
28 #ifdef HAVE_CONFIG_H
29 # include <gnulib/config.h>
30 # undef VERSION
31 # undef PACKAGE_VERSION
32 # undef PACKAGE_TARNAME
33 # undef PACKAGE_STRING
34 # include <config.h>
35 #endif
37 #include <stdlib.h>
38 #include "gettextP.h"
40 /* Names for the libintl functions are a problem. They must not clash
41 with existing names and they should follow ANSI C. But this source
42 code is also used in GNU C Library where the names have a __
43 prefix. So we have to make a difference here. */
44 #ifdef _LIBC
45 # define FREE_EXPRESSION __gettext_free_exp
46 #else
47 # define FREE_EXPRESSION gettext_free_exp__
48 # define __gettextparse gettextparse__
49 #endif
51 #define YYLEX_PARAM &((struct parse_args *) arg)->cp
52 #define YYPARSE_PARAM arg
54 %pure_parser
55 %expect 10
57 %union {
58 unsigned long int num;
59 enum operator op;
60 struct expression *exp;
64 /* Prototypes for local functions. */
65 static struct expression *new_exp PARAMS ((int nargs, enum operator op,
66 struct expression * const *args));
67 static inline struct expression *new_exp_0 PARAMS ((enum operator op));
68 static inline struct expression *new_exp_1 PARAMS ((enum operator op,
69 struct expression *right));
70 static struct expression *new_exp_2 PARAMS ((enum operator op,
71 struct expression *left,
72 struct expression *right));
73 static inline struct expression *new_exp_3 PARAMS ((enum operator op,
74 struct expression *bexp,
75 struct expression *tbranch,
76 struct expression *fbranch));
77 static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
78 static void yyerror PARAMS ((const char *str));
80 /* Allocation of expressions. */
82 static struct expression *
83 new_exp (nargs, op, args)
84 int nargs;
85 enum operator op;
86 struct expression * const *args;
88 int i;
89 struct expression *newp;
91 /* If any of the argument could not be malloc'ed, just return NULL. */
92 for (i = nargs - 1; i >= 0; i--)
93 if (args[i] == NULL)
94 goto fail;
96 /* Allocate a new expression. */
97 newp = (struct expression *) malloc (sizeof (*newp));
98 if (newp != NULL)
100 newp->nargs = nargs;
101 newp->operation = op;
102 for (i = nargs - 1; i >= 0; i--)
103 newp->val.args[i] = args[i];
104 return newp;
107 fail:
108 for (i = nargs - 1; i >= 0; i--)
109 FREE_EXPRESSION (args[i]);
111 return NULL;
114 static inline struct expression *
115 new_exp_0 (op)
116 enum operator op;
118 return new_exp (0, op, NULL);
121 static inline struct expression *
122 new_exp_1 (op, right)
123 enum operator op;
124 struct expression *right;
126 struct expression *args[1];
128 args[0] = right;
129 return new_exp (1, op, args);
132 static struct expression *
133 new_exp_2 (op, left, right)
134 enum operator op;
135 struct expression *left;
136 struct expression *right;
138 struct expression *args[2];
140 args[0] = left;
141 args[1] = right;
142 return new_exp (2, op, args);
145 static inline struct expression *
146 new_exp_3 (op, bexp, tbranch, fbranch)
147 enum operator op;
148 struct expression *bexp;
149 struct expression *tbranch;
150 struct expression *fbranch;
152 struct expression *args[3];
154 args[0] = bexp;
155 args[1] = tbranch;
156 args[2] = fbranch;
157 return new_exp (3, op, args);
162 /* This declares that all operators have the same associativity and the
163 precedence order as in C. See [Harbison, Steele: C, A Reference Manual].
164 There is no unary minus and no bitwise operators.
165 Operators with the same syntactic behaviour have been merged into a single
166 token, to save space in the array generated by bison. */
167 %right '?' /* ? */
168 %left '|' /* || */
169 %left '&' /* && */
170 %left EQUOP2 /* == != */
171 %left CMPOP2 /* < > <= >= */
172 %left ADDOP2 /* + - */
173 %left MULOP2 /* * / % */
174 %right '!' /* ! */
176 %token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
177 %token <num> NUMBER
178 %type <exp> exp
182 start: exp
184 if ($1 == NULL)
185 YYABORT;
186 ((struct parse_args *) arg)->res = $1;
190 exp: exp '?' exp ':' exp
192 $$ = new_exp_3 (qmop, $1, $3, $5);
194 | exp '|' exp
196 $$ = new_exp_2 (lor, $1, $3);
198 | exp '&' exp
200 $$ = new_exp_2 (land, $1, $3);
202 | exp EQUOP2 exp
204 $$ = new_exp_2 ($2, $1, $3);
206 | exp CMPOP2 exp
208 $$ = new_exp_2 ($2, $1, $3);
210 | exp ADDOP2 exp
212 $$ = new_exp_2 ($2, $1, $3);
214 | exp MULOP2 exp
216 $$ = new_exp_2 ($2, $1, $3);
218 | '!' exp
220 $$ = new_exp_1 (lnot, $2);
222 | 'n'
224 $$ = new_exp_0 (var);
226 | NUMBER
228 if (($$ = new_exp_0 (num)) != NULL)
229 $$->val.num = $1;
231 | '(' exp ')'
233 $$ = $2;
239 void
240 internal_function
241 FREE_EXPRESSION (exp)
242 struct expression *exp;
244 if (exp == NULL)
245 return;
247 /* Handle the recursive case. */
248 switch (exp->nargs)
250 case 3:
251 FREE_EXPRESSION (exp->val.args[2]);
252 /* FALLTHROUGH */
253 case 2:
254 FREE_EXPRESSION (exp->val.args[1]);
255 /* FALLTHROUGH */
256 case 1:
257 FREE_EXPRESSION (exp->val.args[0]);
258 /* FALLTHROUGH */
259 default:
260 break;
263 free (exp);
267 static int
268 yylex (lval, pexp)
269 YYSTYPE *lval;
270 const char **pexp;
272 const char *exp = *pexp;
273 int result;
275 while (1)
277 if (exp[0] == '\0')
279 *pexp = exp;
280 return YYEOF;
283 if (exp[0] != ' ' && exp[0] != '\t')
284 break;
286 ++exp;
289 result = *exp++;
290 switch (result)
292 case '0': case '1': case '2': case '3': case '4':
293 case '5': case '6': case '7': case '8': case '9':
295 unsigned long int n = result - '0';
296 while (exp[0] >= '0' && exp[0] <= '9')
298 n *= 10;
299 n += exp[0] - '0';
300 ++exp;
302 lval->num = n;
303 result = NUMBER;
305 break;
307 case '=':
308 if (exp[0] == '=')
310 ++exp;
311 lval->op = equal;
312 result = EQUOP2;
314 else
315 result = YYERRCODE;
316 break;
318 case '!':
319 if (exp[0] == '=')
321 ++exp;
322 lval->op = not_equal;
323 result = EQUOP2;
325 break;
327 case '&':
328 case '|':
329 if (exp[0] == result)
330 ++exp;
331 else
332 result = YYERRCODE;
333 break;
335 case '<':
336 if (exp[0] == '=')
338 ++exp;
339 lval->op = less_or_equal;
341 else
342 lval->op = less_than;
343 result = CMPOP2;
344 break;
346 case '>':
347 if (exp[0] == '=')
349 ++exp;
350 lval->op = greater_or_equal;
352 else
353 lval->op = greater_than;
354 result = CMPOP2;
355 break;
357 case '*':
358 lval->op = mult;
359 result = MULOP2;
360 break;
362 case '/':
363 lval->op = divide;
364 result = MULOP2;
365 break;
367 case '%':
368 lval->op = module;
369 result = MULOP2;
370 break;
372 case '+':
373 lval->op = plus;
374 result = ADDOP2;
375 break;
377 case '-':
378 lval->op = minus;
379 result = ADDOP2;
380 break;
382 case 'n':
383 case '?':
384 case ':':
385 case '(':
386 case ')':
387 /* Nothing, just return the character. */
388 break;
390 case ';':
391 case '\n':
392 case '\0':
393 /* Be safe and let the user call this function again. */
394 --exp;
395 result = YYEOF;
396 break;
398 default:
399 result = YYERRCODE;
400 #if YYDEBUG != 0
401 --exp;
402 #endif
403 break;
406 *pexp = exp;
408 return result;
412 static void
413 yyerror (str)
414 const char *str;
416 /* Do nothing. We don't print error messages here. */