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