1
by Ryan Murray
Import upstream version 2.2.5.5 |
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.
|
|
5 |
||
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.
|
|
10 |
||
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.
|
|
15 |
||
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. */
|
|
19 |
||
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
|
|
27 |
||
28 |
#ifdef HAVE_CONFIG_H
|
|
29 |
# include <config.h>
|
|
30 |
#endif
|
|
31 |
||
32 |
#include <stdlib.h>
|
|
33 |
#include "gettextP.h"
|
|
34 |
||
35 |
/* Names for the libintl functions are a problem. They must not clash
|
|
36 |
with existing names and they should follow ANSI C. But this source
|
|
37 |
code is also used in GNU C Library where the names have a __
|
|
38 |
prefix. So we have to make a difference here. */
|
|
39 |
#ifdef _LIBC
|
|
40 |
# define FREE_EXPRESSION __gettext_free_exp
|
|
41 |
#else
|
|
42 |
# define FREE_EXPRESSION gettext_free_exp__
|
|
43 |
# define __gettextparse gettextparse__
|
|
44 |
#endif
|
|
45 |
||
46 |
#define YYLEX_PARAM &((struct parse_args *) arg)->cp
|
|
47 |
#define YYPARSE_PARAM arg
|
|
48 |
%}
|
|
49 |
%pure_parser
|
|
50 |
%expect 10
|
|
51 |
||
52 |
%union {
|
|
53 |
unsigned long int num; |
|
54 |
enum operator op; |
|
55 |
struct expression *exp; |
|
56 |
}
|
|
57 |
||
58 |
%{
|
|
59 |
/* Prototypes for local functions. */
|
|
60 |
static struct expression *new_exp PARAMS ((int nargs, enum operator op,
|
|
61 |
struct expression * const *args));
|
|
62 |
static inline struct expression *new_exp_0 PARAMS ((enum operator op));
|
|
63 |
static inline struct expression *new_exp_1 PARAMS ((enum operator op,
|
|
64 |
struct expression *right));
|
|
65 |
static struct expression *new_exp_2 PARAMS ((enum operator op,
|
|
66 |
struct expression *left,
|
|
67 |
struct expression *right));
|
|
68 |
static inline struct expression *new_exp_3 PARAMS ((enum operator op,
|
|
69 |
struct expression *bexp,
|
|
70 |
struct expression *tbranch,
|
|
71 |
struct expression *fbranch));
|
|
72 |
static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
|
|
73 |
static void yyerror PARAMS ((const char *str));
|
|
74 |
||
75 |
/* Allocation of expressions. */
|
|
76 |
||
77 |
static struct expression *
|
|
78 |
new_exp (nargs, op, args)
|
|
79 |
int nargs;
|
|
80 |
enum operator op;
|
|
81 |
struct expression * const *args;
|
|
82 |
{
|
|
83 |
int i;
|
|
84 |
struct expression *newp;
|
|
85 |
||
86 |
/* If any of the argument could not be malloc'ed, just return NULL. */
|
|
87 |
for (i = nargs - 1; i >= 0; i--)
|
|
88 |
if (args[i] == NULL)
|
|
89 |
goto fail;
|
|
90 |
||
91 |
/* Allocate a new expression. */
|
|
92 |
newp = (struct expression *) malloc (sizeof (*newp));
|
|
93 |
if (newp != NULL)
|
|
94 |
{
|
|
95 |
newp->nargs = nargs;
|
|
96 |
newp->operation = op;
|
|
97 |
for (i = nargs - 1; i >= 0; i--)
|
|
98 |
newp->val.args[i] = args[i];
|
|
99 |
return newp;
|
|
100 |
}
|
|
101 |
||
102 |
fail:
|
|
103 |
for (i = nargs - 1; i >= 0; i--)
|
|
104 |
FREE_EXPRESSION (args[i]);
|
|
105 |
||
106 |
return NULL;
|
|
107 |
}
|
|
108 |
||
109 |
static inline struct expression *
|
|
110 |
new_exp_0 (op)
|
|
111 |
enum operator op;
|
|
112 |
{
|
|
113 |
return new_exp (0, op, NULL);
|
|
114 |
}
|
|
115 |
||
116 |
static inline struct expression *
|
|
117 |
new_exp_1 (op, right)
|
|
118 |
enum operator op;
|
|
119 |
struct expression *right;
|
|
120 |
{
|
|
121 |
struct expression *args[1];
|
|
122 |
||
123 |
args[0] = right;
|
|
124 |
return new_exp (1, op, args);
|
|
125 |
}
|
|
126 |
||
127 |
static struct expression *
|
|
128 |
new_exp_2 (op, left, right)
|
|
129 |
enum operator op;
|
|
130 |
struct expression *left;
|
|
131 |
struct expression *right;
|
|
132 |
{
|
|
133 |
struct expression *args[2];
|
|
134 |
||
135 |
args[0] = left;
|
|
136 |
args[1] = right;
|
|
137 |
return new_exp (2, op, args);
|
|
138 |
}
|
|
139 |
||
140 |
static inline struct expression *
|
|
141 |
new_exp_3 (op, bexp, tbranch, fbranch)
|
|
142 |
enum operator op;
|
|
143 |
struct expression *bexp;
|
|
144 |
struct expression *tbranch;
|
|
145 |
struct expression *fbranch;
|
|
146 |
{
|
|
147 |
struct expression *args[3];
|
|
148 |
||
149 |
args[0] = bexp;
|
|
150 |
args[1] = tbranch;
|
|
151 |
args[2] = fbranch;
|
|
152 |
return new_exp (3, op, args);
|
|
153 |
}
|
|
154 |
||
155 |
%}
|
|
156 |
||
157 |
/* This declares that all operators have the same associativity and the |
|
158 |
precedence order as in C. See [Harbison, Steele: C, A Reference Manual]. |
|
159 |
There is no unary minus and no bitwise operators. |
|
160 |
Operators with the same syntactic behaviour have been merged into a single |
|
161 |
token, to save space in the array generated by bison. */ |
|
162 |
%right '?' /* ? */
|
|
163 |
%left '|' /* || */
|
|
164 |
%left '&' /* && */
|
|
165 |
%left EQUOP2 /* == != */
|
|
166 |
%left CMPOP2 /* < > <= >= */
|
|
167 |
%left ADDOP2 /* + - */
|
|
168 |
%left MULOP2 /* * / % */
|
|
169 |
%right '!' /* ! */
|
|
170 |
||
171 |
%token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
|
|
172 |
%token <num> NUMBER
|
|
173 |
%type <exp> exp
|
|
174 |
||
175 |
%%
|
|
176 |
||
177 |
start: exp |
|
178 |
{
|
|
179 |
if ($1 == NULL) |
|
180 |
YYABORT; |
|
181 |
((struct parse_args *) arg)->res = $1; |
|
182 |
}
|
|
183 |
;
|
|
184 |
||
185 |
exp: exp '?' exp ':' exp |
|
186 |
{
|
|
187 |
$$ = new_exp_3 (qmop, $1, $3, $5); |
|
188 |
}
|
|
189 |
| exp '|' exp |
|
190 |
{
|
|
191 |
$$ = new_exp_2 (lor, $1, $3); |
|
192 |
}
|
|
193 |
| exp '&' exp |
|
194 |
{
|
|
195 |
$$ = new_exp_2 (land, $1, $3); |
|
196 |
}
|
|
197 |
| exp EQUOP2 exp |
|
198 |
{
|
|
199 |
$$ = new_exp_2 ($2, $1, $3); |
|
200 |
}
|
|
201 |
| exp CMPOP2 exp |
|
202 |
{
|
|
203 |
$$ = new_exp_2 ($2, $1, $3); |
|
204 |
}
|
|
205 |
| exp ADDOP2 exp |
|
206 |
{
|
|
207 |
$$ = new_exp_2 ($2, $1, $3); |
|
208 |
}
|
|
209 |
| exp MULOP2 exp |
|
210 |
{
|
|
211 |
$$ = new_exp_2 ($2, $1, $3); |
|
212 |
}
|
|
213 |
| '!' exp |
|
214 |
{
|
|
215 |
$$ = new_exp_1 (lnot, $2); |
|
216 |
}
|
|
217 |
| 'n' |
|
218 |
{
|
|
219 |
$$ = new_exp_0 (var); |
|
220 |
}
|
|
221 |
| NUMBER |
|
222 |
{
|
|
223 |
if (($$ = new_exp_0 (num)) != NULL) |
|
224 |
$$->val.num = $1; |
|
225 |
}
|
|
226 |
| '(' exp ')' |
|
227 |
{
|
|
228 |
$$ = $2; |
|
229 |
}
|
|
230 |
;
|
|
231 |
||
232 |
%%
|
|
233 |
||
234 |
void
|
|
235 |
internal_function
|
|
236 |
FREE_EXPRESSION (exp) |
|
237 |
struct expression *exp; |
|
238 |
{
|
|
239 |
if (exp == NULL) |
|
240 |
return; |
|
241 |
||
242 |
/* Handle the recursive case. */ |
|
243 |
switch (exp->nargs) |
|
244 |
{
|
|
245 |
case 3: |
|
246 |
FREE_EXPRESSION (exp->val.args[2]); |
|
247 |
/* FALLTHROUGH */ |
|
248 |
case 2: |
|
249 |
FREE_EXPRESSION (exp->val.args[1]); |
|
250 |
/* FALLTHROUGH */ |
|
251 |
case 1: |
|
252 |
FREE_EXPRESSION (exp->val.args[0]); |
|
253 |
/* FALLTHROUGH */ |
|
254 |
default: |
|
255 |
break; |
|
256 |
}
|
|
257 |
||
258 |
free (exp); |
|
259 |
}
|
|
260 |
||
261 |
||
262 |
static int |
|
263 |
yylex (lval, pexp) |
|
264 |
YYSTYPE *lval; |
|
265 |
const char **pexp; |
|
266 |
{
|
|
267 |
const char *exp = *pexp; |
|
268 |
int result; |
|
269 |
||
270 |
while (1) |
|
271 |
{
|
|
272 |
if (exp[0] == '\0') |
|
273 |
{
|
|
274 |
*pexp = exp; |
|
275 |
return YYEOF; |
|
276 |
}
|
|
277 |
||
278 |
if (exp[0] != ' ' && exp[0] != '\t') |
|
279 |
break; |
|
280 |
||
281 |
++exp; |
|
282 |
}
|
|
283 |
||
284 |
result = *exp++; |
|
285 |
switch (result) |
|
286 |
{
|
|
287 |
case '0': case '1': case '2': case '3': case '4': |
|
288 |
case '5': case '6': case '7': case '8': case '9': |
|
289 |
{
|
|
290 |
unsigned long int n = result - '0'; |
|
291 |
while (exp[0] >= '0' && exp[0] <= '9') |
|
292 |
{
|
|
293 |
n *= 10; |
|
294 |
n += exp[0] - '0'; |
|
295 |
++exp; |
|
296 |
}
|
|
297 |
lval->num = n; |
|
298 |
result = NUMBER; |
|
299 |
}
|
|
300 |
break; |
|
301 |
||
302 |
case '=': |
|
303 |
if (exp[0] == '=') |
|
304 |
{
|
|
305 |
++exp; |
|
306 |
lval->op = equal; |
|
307 |
result = EQUOP2; |
|
308 |
}
|
|
309 |
else
|
|
310 |
result = YYERRCODE; |
|
311 |
break; |
|
312 |
||
313 |
case '!': |
|
314 |
if (exp[0] == '=') |
|
315 |
{
|
|
316 |
++exp; |
|
317 |
lval->op = not_equal; |
|
318 |
result = EQUOP2; |
|
319 |
}
|
|
320 |
break; |
|
321 |
||
322 |
case '&': |
|
323 |
case '|': |
|
324 |
if (exp[0] == result) |
|
325 |
++exp; |
|
326 |
else
|
|
327 |
result = YYERRCODE; |
|
328 |
break; |
|
329 |
||
330 |
case '<': |
|
331 |
if (exp[0] == '=') |
|
332 |
{
|
|
333 |
++exp; |
|
334 |
lval->op = less_or_equal; |
|
335 |
}
|
|
336 |
else
|
|
337 |
lval->op = less_than; |
|
338 |
result = CMPOP2; |
|
339 |
break; |
|
340 |
||
341 |
case '>': |
|
342 |
if (exp[0] == '=') |
|
343 |
{
|
|
344 |
++exp; |
|
345 |
lval->op = greater_or_equal; |
|
346 |
}
|
|
347 |
else
|
|
348 |
lval->op = greater_than; |
|
349 |
result = CMPOP2; |
|
350 |
break; |
|
351 |
||
352 |
case '*': |
|
353 |
lval->op = mult; |
|
354 |
result = MULOP2; |
|
355 |
break; |
|
356 |
||
357 |
case '/': |
|
358 |
lval->op = divide; |
|
359 |
result = MULOP2; |
|
360 |
break; |
|
361 |
||
362 |
case '%': |
|
363 |
lval->op = module; |
|
364 |
result = MULOP2; |
|
365 |
break; |
|
366 |
||
367 |
case '+': |
|
368 |
lval->op = plus; |
|
369 |
result = ADDOP2; |
|
370 |
break; |
|
371 |
||
372 |
case '-': |
|
373 |
lval->op = minus; |
|
374 |
result = ADDOP2; |
|
375 |
break; |
|
376 |
||
377 |
case 'n': |
|
378 |
case '?': |
|
379 |
case ':': |
|
380 |
case '(': |
|
381 |
case ')': |
|
382 |
/* Nothing, just return the character. */ |
|
383 |
break; |
|
384 |
||
385 |
case ';': |
|
386 |
case '\n': |
|
387 |
case '\0': |
|
388 |
/* Be safe and let the user call this function again. */ |
|
389 |
--exp; |
|
390 |
result = YYEOF; |
|
391 |
break; |
|
392 |
||
393 |
default: |
|
394 |
result = YYERRCODE; |
|
395 |
#if YYDEBUG != 0 |
|
396 |
--exp; |
|
397 |
#endif
|
|
398 |
break; |
|
399 |
}
|
|
400 |
||
401 |
*pexp = exp; |
|
402 |
||
403 |
return result; |
|
404 |
}
|
|
405 |
||
406 |
||
407 |
static void |
|
408 |
yyerror (str) |
|
409 |
const char *str; |
|
410 |
{
|
|
411 |
/* Do nothing. We don't print error messages here. */ |
|
412 |
}
|