Statistics
| Revision:

root / intl / plural.y @ 1

History | View | Annotate | Download (7.18 KB)

1
%{
2
/* Expression parsing for plural form selection.
3
   Copyright (C) 2000-2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19
   USA.  */
20

    
21
/* The bison generated parser uses alloca.  AIX 3 forces us to put this
22
   declaration at the beginning of the file.  The declaration in bison's
23
   skeleton file comes too late.  This must come before <config.h>
24
   because <config.h> may include arbitrary system headers.  */
25
#if defined _AIX && !defined __GNUC__
26
 #pragma alloca
27
#endif
28

    
29
#ifdef HAVE_CONFIG_H
30
# include <config.h>
31
#endif
32

    
33
#include <stddef.h>
34
#include <stdlib.h>
35
#include "plural-exp.h"
36

    
37
/* The main function generated by the parser is called __gettextparse,
38
   but we want it to be called PLURAL_PARSE.  */
39
#ifndef _LIBC
40
# define __gettextparse PLURAL_PARSE
41
#endif
42

    
43
#define YYLEX_PARAM	&((struct parse_args *) arg)->cp
44
#define YYPARSE_PARAM	arg
45
%}
46
%pure_parser
47
%expect 7
48

    
49
%union {
50
  unsigned long int num;
51
  enum operator op;
52
  struct expression *exp;
53
}
54

    
55
%{
56
/* Prototypes for local functions.  */
57
static int yylex (YYSTYPE *lval, const char **pexp);
58
static void yyerror (const char *str);
59

    
60
/* Allocation of expressions.  */
61

    
62
static struct expression *
63
new_exp (int nargs, enum operator op, struct expression * const *args)
64
{
65
  int i;
66
  struct expression *newp;
67

    
68
  /* If any of the argument could not be malloc'ed, just return NULL.  */
69
  for (i = nargs - 1; i >= 0; i--)
70
    if (args[i] == NULL)
71
      goto fail;
72

    
73
  /* Allocate a new expression.  */
74
  newp = (struct expression *) malloc (sizeof (*newp));
75
  if (newp != NULL)
76
    {
77
      newp->nargs = nargs;
78
      newp->operation = op;
79
      for (i = nargs - 1; i >= 0; i--)
80
	newp->val.args[i] = args[i];
81
      return newp;
82
    }
83

    
84
 fail:
85
  for (i = nargs - 1; i >= 0; i--)
86
    FREE_EXPRESSION (args[i]);
87

    
88
  return NULL;
89
}
90

    
91
static inline struct expression *
92
new_exp_0 (enum operator op)
93
{
94
  return new_exp (0, op, NULL);
95
}
96

    
97
static inline struct expression *
98
new_exp_1 (enum operator op, struct expression *right)
99
{
100
  struct expression *args[1];
101

    
102
  args[0] = right;
103
  return new_exp (1, op, args);
104
}
105

    
106
static struct expression *
107
new_exp_2 (enum operator op, struct expression *left, struct expression *right)
108
{
109
  struct expression *args[2];
110

    
111
  args[0] = left;
112
  args[1] = right;
113
  return new_exp (2, op, args);
114
}
115

    
116
static inline struct expression *
117
new_exp_3 (enum operator op, struct expression *bexp,
118
	   struct expression *tbranch, struct expression *fbranch)
119
{
120
  struct expression *args[3];
121

    
122
  args[0] = bexp;
123
  args[1] = tbranch;
124
  args[2] = fbranch;
125
  return new_exp (3, op, args);
126
}
127

    
128
%}
129

    
130
/* This declares that all operators have the same associativity and the
131
   precedence order as in C.  See [Harbison, Steele: C, A Reference Manual].
132
   There is no unary minus and no bitwise operators.
133
   Operators with the same syntactic behaviour have been merged into a single
134
   token, to save space in the array generated by bison.  */
135
%right '?'		/*   ?		*/
136
%left '|'		/*   ||		*/
137
%left '&'		/*   &&		*/
138
%left EQUOP2		/*   == !=	*/
139
%left CMPOP2		/*   < > <= >=	*/
140
%left ADDOP2		/*   + -	*/
141
%left MULOP2		/*   * / %	*/
142
%right '!'		/*   !		*/
143

    
144
%token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
145
%token <num> NUMBER
146
%type <exp> exp
147

    
148
%%
149

    
150
start:	  exp
151
	  {
152
	    if ($1 == NULL)
153
	      YYABORT;
154
	    ((struct parse_args *) arg)->res = $1;
155
	  }
156
	;
157

    
158
exp:	  exp '?' exp ':' exp
159
	  {
160
	    $$ = new_exp_3 (qmop, $1, $3, $5);
161
	  }
162
	| exp '|' exp
163
	  {
164
	    $$ = new_exp_2 (lor, $1, $3);
165
	  }
166
	| exp '&' exp
167
	  {
168
	    $$ = new_exp_2 (land, $1, $3);
169
	  }
170
	| exp EQUOP2 exp
171
	  {
172
	    $$ = new_exp_2 ($2, $1, $3);
173
	  }
174
	| exp CMPOP2 exp
175
	  {
176
	    $$ = new_exp_2 ($2, $1, $3);
177
	  }
178
	| exp ADDOP2 exp
179
	  {
180
	    $$ = new_exp_2 ($2, $1, $3);
181
	  }
182
	| exp MULOP2 exp
183
	  {
184
	    $$ = new_exp_2 ($2, $1, $3);
185
	  }
186
	| '!' exp
187
	  {
188
	    $$ = new_exp_1 (lnot, $2);
189
	  }
190
	| 'n'
191
	  {
192
	    $$ = new_exp_0 (var);
193
	  }
194
	| NUMBER
195
	  {
196
	    if (($$ = new_exp_0 (num)) != NULL)
197
	      $$->val.num = $1;
198
	  }
199
	| '(' exp ')'
200
	  {
201
	    $$ = $2;
202
	  }
203
	;
204

    
205
%%
206

    
207
void
208
internal_function
209
FREE_EXPRESSION (struct expression *exp)
210
{
211
  if (exp == NULL)
212
    return;
213

    
214
  /* Handle the recursive case.  */
215
  switch (exp->nargs)
216
    {
217
    case 3:
218
      FREE_EXPRESSION (exp->val.args[2]);
219
      /* FALLTHROUGH */
220
    case 2:
221
      FREE_EXPRESSION (exp->val.args[1]);
222
      /* FALLTHROUGH */
223
    case 1:
224
      FREE_EXPRESSION (exp->val.args[0]);
225
      /* FALLTHROUGH */
226
    default:
227
      break;
228
    }
229

    
230
  free (exp);
231
}
232

    
233

    
234
static int
235
yylex (YYSTYPE *lval, const char **pexp)
236
{
237
  const char *exp = *pexp;
238
  int result;
239

    
240
  while (1)
241
    {
242
      if (exp[0] == '\0')
243
	{
244
	  *pexp = exp;
245
	  return YYEOF;
246
	}
247

    
248
      if (exp[0] != ' ' && exp[0] != '\t')
249
	break;
250

    
251
      ++exp;
252
    }
253

    
254
  result = *exp++;
255
  switch (result)
256
    {
257
    case '0': case '1': case '2': case '3': case '4':
258
    case '5': case '6': case '7': case '8': case '9':
259
      {
260
	unsigned long int n = result - '0';
261
	while (exp[0] >= '0' && exp[0] <= '9')
262
	  {
263
	    n *= 10;
264
	    n += exp[0] - '0';
265
	    ++exp;
266
	  }
267
	lval->num = n;
268
	result = NUMBER;
269
      }
270
      break;
271

    
272
    case '=':
273
      if (exp[0] == '=')
274
	{
275
	  ++exp;
276
	  lval->op = equal;
277
	  result = EQUOP2;
278
	}
279
      else
280
	result = YYERRCODE;
281
      break;
282

    
283
    case '!':
284
      if (exp[0] == '=')
285
	{
286
	  ++exp;
287
	  lval->op = not_equal;
288
	  result = EQUOP2;
289
	}
290
      break;
291

    
292
    case '&':
293
    case '|':
294
      if (exp[0] == result)
295
	++exp;
296
      else
297
	result = YYERRCODE;
298
      break;
299

    
300
    case '<':
301
      if (exp[0] == '=')
302
	{
303
	  ++exp;
304
	  lval->op = less_or_equal;
305
	}
306
      else
307
	lval->op = less_than;
308
      result = CMPOP2;
309
      break;
310

    
311
    case '>':
312
      if (exp[0] == '=')
313
	{
314
	  ++exp;
315
	  lval->op = greater_or_equal;
316
	}
317
      else
318
	lval->op = greater_than;
319
      result = CMPOP2;
320
      break;
321

    
322
    case '*':
323
      lval->op = mult;
324
      result = MULOP2;
325
      break;
326

    
327
    case '/':
328
      lval->op = divide;
329
      result = MULOP2;
330
      break;
331

    
332
    case '%':
333
      lval->op = module;
334
      result = MULOP2;
335
      break;
336

    
337
    case '+':
338
      lval->op = plus;
339
      result = ADDOP2;
340
      break;
341

    
342
    case '-':
343
      lval->op = minus;
344
      result = ADDOP2;
345
      break;
346

    
347
    case 'n':
348
    case '?':
349
    case ':':
350
    case '(':
351
    case ')':
352
      /* Nothing, just return the character.  */
353
      break;
354

    
355
    case ';':
356
    case '\n':
357
    case '\0':
358
      /* Be safe and let the user call this function again.  */
359
      --exp;
360
      result = YYEOF;
361
      break;
362

    
363
    default:
364
      result = YYERRCODE;
365
#if YYDEBUG != 0
366
      --exp;
367
#endif
368
      break;
369
    }
370

    
371
  *pexp = exp;
372

    
373
  return result;
374
}
375

    
376

    
377
static void
378
yyerror (const char *str)
379
{
380
  /* Do nothing.  We don't print error messages here.  */
381
}