Don't assume that $(inst_zonedir) is a subdir of $(inst_datadir).
[glibc/pb-stable.git] / intl / plural.y
blobf14dc29fd3fb95c3854cb267f9177f8dc96e844d
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 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C Library 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 GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include "gettext.h"
28 #include "gettextP.h"
30 #define YYLEX_PARAM &((struct parse_args *) arg)->cp
31 #define YYPARSE_PARAM arg
33 %pure_parser
34 %expect 10
36 %union {
37 unsigned long int num;
38 struct expression *exp;
42 /* Prototypes for local functions. */
43 static struct expression *new_exp (enum operator op, int n, ...);
44 static int yylex (YYSTYPE *lval, const char **pexp);
45 static void yyerror (const char *str);
48 %left '?'
49 %left '|'
50 %left '&'
51 %left '=', '!'
52 %left '+', '-'
53 %left '*', '/', '%'
54 %token <num> NUMBER
55 %type <exp> exp
59 start: exp
61 ((struct parse_args *) arg)->res = $1;
65 exp: exp '?' exp ':' exp
67 if (($$ = new_exp (qmop, 3, $1, $3, $5)) == NULL)
68 YYABORT
70 | exp '|' exp
72 if (($$ = new_exp (lor, 2, $1, $3)) == NULL)
73 YYABORT
75 | exp '&' exp
77 if (($$ = new_exp (land, 2, $1, $3)) == NULL)
78 YYABORT
80 | exp '=' exp
82 if (($$ = new_exp (equal, 2, $1, $3)) == NULL)
83 YYABORT
85 | exp '!' exp
87 if (($$ = new_exp (not_equal, 2, $1, $3)) == NULL)
88 YYABORT
90 | exp '+' exp
92 if (($$ = new_exp (plus, 2, $1, $3)) == NULL)
93 YYABORT
95 | exp '-' exp
97 if (($$ = new_exp (minus, 2, $1, $3)) == NULL)
98 YYABORT
100 | exp '*' exp
102 if (($$ = new_exp (mult, 2, $1, $3)) == NULL)
103 YYABORT
105 | exp '/' exp
107 if (($$ = new_exp (divide, 2, $1, $3)) == NULL)
108 YYABORT
110 | exp '%' exp
112 if (($$ = new_exp (module, 2, $1, $3)) == NULL)
113 YYABORT
115 | 'n'
117 if (($$ = new_exp (var, 0)) == NULL)
118 YYABORT
120 | NUMBER
122 if (($$ = new_exp (num, 0)) == NULL)
123 YYABORT;
124 $$->val.num = $1
126 | '(' exp ')'
128 $$ = $2
134 static struct expression *
135 new_exp (enum operator op, int n, ...)
137 struct expression *newp = (struct expression *) calloc (1, sizeof (*newp));
138 va_list va;
140 va_start (va, n);
142 if (newp == NULL)
143 while (n-- > 0)
144 __gettext_free_exp (va_arg (va, struct expression *));
145 else
147 newp->operation = op;
148 if (n > 0)
150 newp->val.args3.bexp = va_arg (va, struct expression *);
151 newp->val.args3.tbranch = va_arg (va, struct expression *);
153 if (n > 2)
154 newp->val.args3.fbranch = va_arg (va, struct expression *);
156 if (newp->val.args3.bexp == NULL
157 || newp->val.args3.tbranch == NULL
158 || (n > 2 && newp->val.args3.fbranch == NULL))
160 __gettext_free_exp (newp);
161 newp = NULL;
166 va_end (va);
168 return newp;
171 void
172 internal_function
173 __gettext_free_exp (struct expression *exp)
175 if (exp == NULL)
176 return;
178 /* Handle the recursive case. */
179 switch (exp->operation)
181 case qmop:
182 __gettext_free_exp (exp->val.args3.fbranch);
183 /* FALLTHROUGH */
185 case mult:
186 case divide:
187 case module:
188 case plus:
189 case minus:
190 case equal:
191 case not_equal:
192 case land:
193 case lor:
194 __gettext_free_exp (exp->val.args2.right);
195 __gettext_free_exp (exp->val.args2.left);
196 break;
198 default:
199 break;
202 free (exp);
206 static int
207 yylex (YYSTYPE *lval, const char **pexp)
209 const char *exp = *pexp;
210 int result;
212 while (1)
214 if (exp[0] == '\\' && exp[1] == '\n')
216 exp += 2;
217 continue;
220 if (exp[0] == '\0')
222 *pexp = exp;
223 return YYEOF;
226 if (exp[0] != ' ' && exp[0] != '\t')
227 break;
229 ++exp;
232 result = *exp++;
233 switch (result)
235 case '0': case '1': case '2': case '3': case '4':
236 case '5': case '6': case '7': case '8': case '9':
238 unsigned long int n = result - '0';
239 while (exp[0] >= '0' && exp[0] <= '9')
241 n *= 10;
242 n += exp[0] - '0';
243 ++exp;
245 lval->num = n;
246 result = NUMBER;
248 break;
250 case '=':
251 case '!':
252 if (exp[0] == '=')
253 ++exp;
254 else
255 result = YYERRCODE;
256 break;
258 case '&':
259 case '|':
260 if (exp[0] == result)
261 ++exp;
262 else
263 result = YYERRCODE;
264 break;
266 case 'n':
267 case '*':
268 case '/':
269 case '%':
270 case '+':
271 case '-':
272 case '?':
273 case ':':
274 case '(':
275 case ')':
276 /* Nothing, just return the character. */
277 break;
279 case ';':
280 case '\n':
281 case '\0':
282 /* Be safe and let the user call this function again. */
283 --exp;
284 result = YYEOF;
285 break;
287 default:
288 result = YYERRCODE;
289 #if YYDEBUG != 0
290 --exp;
291 #endif
292 break;
295 *pexp = exp;
297 return result;
301 static void
302 yyerror (const char *str)
304 /* Do nothing. We don't print error messages here. */