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