xref: /netbsd-src/external/gpl2/grep/dist/intl/plural.y (revision a8fa202a6440953be7b92a8960a811bff58203f4)
1 /*	$NetBSD: plural.y,v 1.1.1.1 2016/01/10 21:36:18 christos Exp $	*/
2 
3 %{
4 /* Expression parsing for plural form selection.
5    Copyright (C) 2000, 2001 Free Software Foundation, Inc.
6    Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
7 
8    This program is free software; you can redistribute it and/or modify it
9    under the terms of the GNU Library General Public License as published
10    by the Free Software Foundation; either version 2, or (at your option)
11    any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Library General Public License for more details.
17 
18    You should have received a copy of the GNU Library General Public
19    License along with this program; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21    USA.  */
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 *
new_exp(nargs,op,args)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 *
new_exp_0(op)109 new_exp_0 (op)
110      enum operator op;
111 {
112   return new_exp (0, op, NULL);
113 }
114 
115 static inline struct expression *
new_exp_1(op,right)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 *
new_exp_2(op,left,right)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 *
new_exp_3(op,bexp,tbranch,fbranch)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
FREE_EXPRESSION(exp)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
yylex(lval,pexp)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
yyerror(str)407 yyerror (str)
408      const char *str;
409 {
410   /* Do nothing.  We don't print error messages here.  */
411 }
412