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