~ubuntu-branches/ubuntu/lucid/mc/lucid

« back to all changes in this revision

Viewing changes to intl/plural.y

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-09-16 10:38:59 UTC
  • mfrom: (3.1.6 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080916103859-2uwn8w61xk5mbxxq
Tags: 2:4.6.2~git20080311-4
Corrected fix for odt2txt issue (Closes: #492019) 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
%{
2
 
/* Expression parsing for plural form selection.
3
 
   Copyright (C) 2000, 2001 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 struct expression *new_exp PARAMS ((int nargs, enum operator op,
58
 
                                           struct expression * const *args));
59
 
static inline struct expression *new_exp_0 PARAMS ((enum operator op));
60
 
static inline struct expression *new_exp_1 PARAMS ((enum operator op,
61
 
                                                   struct expression *right));
62
 
static struct expression *new_exp_2 PARAMS ((enum operator op,
63
 
                                             struct expression *left,
64
 
                                             struct expression *right));
65
 
static inline struct expression *new_exp_3 PARAMS ((enum operator op,
66
 
                                                   struct expression *bexp,
67
 
                                                   struct expression *tbranch,
68
 
                                                   struct expression *fbranch));
69
 
static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
70
 
static void yyerror PARAMS ((const char *str));
71
 
 
72
 
/* Allocation of expressions.  */
73
 
 
74
 
static struct expression *
75
 
new_exp (nargs, op, args)
76
 
     int nargs;
77
 
     enum operator op;
78
 
     struct expression * const *args;
79
 
{
80
 
  int i;
81
 
  struct expression *newp;
82
 
 
83
 
  /* If any of the argument could not be malloc'ed, just return NULL.  */
84
 
  for (i = nargs - 1; i >= 0; i--)
85
 
    if (args[i] == NULL)
86
 
      goto fail;
87
 
 
88
 
  /* Allocate a new expression.  */
89
 
  newp = (struct expression *) malloc (sizeof (*newp));
90
 
  if (newp != NULL)
91
 
    {
92
 
      newp->nargs = nargs;
93
 
      newp->operation = op;
94
 
      for (i = nargs - 1; i >= 0; i--)
95
 
        newp->val.args[i] = args[i];
96
 
      return newp;
97
 
    }
98
 
 
99
 
 fail:
100
 
  for (i = nargs - 1; i >= 0; i--)
101
 
    FREE_EXPRESSION (args[i]);
102
 
 
103
 
  return NULL;
104
 
}
105
 
 
106
 
static inline struct expression *
107
 
new_exp_0 (op)
108
 
     enum operator op;
109
 
{
110
 
  return new_exp (0, op, NULL);
111
 
}
112
 
 
113
 
static inline struct expression *
114
 
new_exp_1 (op, right)
115
 
     enum operator op;
116
 
     struct expression *right;
117
 
{
118
 
  struct expression *args[1];
119
 
 
120
 
  args[0] = right;
121
 
  return new_exp (1, op, args);
122
 
}
123
 
 
124
 
static struct expression *
125
 
new_exp_2 (op, left, right)
126
 
     enum operator op;
127
 
     struct expression *left;
128
 
     struct expression *right;
129
 
{
130
 
  struct expression *args[2];
131
 
 
132
 
  args[0] = left;
133
 
  args[1] = right;
134
 
  return new_exp (2, op, args);
135
 
}
136
 
 
137
 
static inline struct expression *
138
 
new_exp_3 (op, bexp, tbranch, fbranch)
139
 
     enum operator op;
140
 
     struct expression *bexp;
141
 
     struct expression *tbranch;
142
 
     struct expression *fbranch;
143
 
{
144
 
  struct expression *args[3];
145
 
 
146
 
  args[0] = bexp;
147
 
  args[1] = tbranch;
148
 
  args[2] = fbranch;
149
 
  return new_exp (3, op, args);
150
 
}
151
 
 
152
 
%}
153
 
 
154
 
/* This declares that all operators have the same associativity and the
155
 
   precedence order as in C.  See [Harbison, Steele: C, A Reference Manual].
156
 
   There is no unary minus and no bitwise operators.
157
 
   Operators with the same syntactic behaviour have been merged into a single
158
 
   token, to save space in the array generated by bison.  */
159
 
%right '?'              /*   ?          */
160
 
%left '|'               /*   ||         */
161
 
%left '&'               /*   &&         */
162
 
%left EQUOP2            /*   == !=      */
163
 
%left CMPOP2            /*   < > <= >=  */
164
 
%left ADDOP2            /*   + -        */
165
 
%left MULOP2            /*   * / %      */
166
 
%right '!'              /*   !          */
167
 
 
168
 
%token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
169
 
%token <num> NUMBER
170
 
%type <exp> exp
171
 
 
172
 
%%
173
 
 
174
 
start:    exp
175
 
          {
176
 
            if ($1 == NULL)
177
 
              YYABORT;
178
 
            ((struct parse_args *) arg)->res = $1;
179
 
          }
180
 
        ;
181
 
 
182
 
exp:      exp '?' exp ':' exp
183
 
          {
184
 
            $$ = new_exp_3 (qmop, $1, $3, $5);
185
 
          }
186
 
        | exp '|' exp
187
 
          {
188
 
            $$ = new_exp_2 (lor, $1, $3);
189
 
          }
190
 
        | exp '&' exp
191
 
          {
192
 
            $$ = new_exp_2 (land, $1, $3);
193
 
          }
194
 
        | exp EQUOP2 exp
195
 
          {
196
 
            $$ = new_exp_2 ($2, $1, $3);
197
 
          }
198
 
        | exp CMPOP2 exp
199
 
          {
200
 
            $$ = new_exp_2 ($2, $1, $3);
201
 
          }
202
 
        | exp ADDOP2 exp
203
 
          {
204
 
            $$ = new_exp_2 ($2, $1, $3);
205
 
          }
206
 
        | exp MULOP2 exp
207
 
          {
208
 
            $$ = new_exp_2 ($2, $1, $3);
209
 
          }
210
 
        | '!' exp
211
 
          {
212
 
            $$ = new_exp_1 (lnot, $2);
213
 
          }
214
 
        | 'n'
215
 
          {
216
 
            $$ = new_exp_0 (var);
217
 
          }
218
 
        | NUMBER
219
 
          {
220
 
            if (($$ = new_exp_0 (num)) != NULL)
221
 
              $$->val.num = $1;
222
 
          }
223
 
        | '(' exp ')'
224
 
          {
225
 
            $$ = $2;
226
 
          }
227
 
        ;
228
 
 
229
 
%%
230
 
 
231
 
void
232
 
internal_function
233
 
FREE_EXPRESSION (exp)
234
 
     struct expression *exp;
235
 
{
236
 
  if (exp == NULL)
237
 
    return;
238
 
 
239
 
  /* Handle the recursive case.  */
240
 
  switch (exp->nargs)
241
 
    {
242
 
    case 3:
243
 
      FREE_EXPRESSION (exp->val.args[2]);
244
 
      /* FALLTHROUGH */
245
 
    case 2:
246
 
      FREE_EXPRESSION (exp->val.args[1]);
247
 
      /* FALLTHROUGH */
248
 
    case 1:
249
 
      FREE_EXPRESSION (exp->val.args[0]);
250
 
      /* FALLTHROUGH */
251
 
    default:
252
 
      break;
253
 
    }
254
 
 
255
 
  free (exp);
256
 
}
257
 
 
258
 
 
259
 
static int
260
 
yylex (lval, pexp)
261
 
     YYSTYPE *lval;
262
 
     const char **pexp;
263
 
{
264
 
  const char *exp = *pexp;
265
 
  int result;
266
 
 
267
 
  while (1)
268
 
    {
269
 
      if (exp[0] == '\0')
270
 
        {
271
 
          *pexp = exp;
272
 
          return YYEOF;
273
 
        }
274
 
 
275
 
      if (exp[0] != ' ' && exp[0] != '\t')
276
 
        break;
277
 
 
278
 
      ++exp;
279
 
    }
280
 
 
281
 
  result = *exp++;
282
 
  switch (result)
283
 
    {
284
 
    case '0': case '1': case '2': case '3': case '4':
285
 
    case '5': case '6': case '7': case '8': case '9':
286
 
      {
287
 
        unsigned long int n = result - '0';
288
 
        while (exp[0] >= '0' && exp[0] <= '9')
289
 
          {
290
 
            n *= 10;
291
 
            n += exp[0] - '0';
292
 
            ++exp;
293
 
          }
294
 
        lval->num = n;
295
 
        result = NUMBER;
296
 
      }
297
 
      break;
298
 
 
299
 
    case '=':
300
 
      if (exp[0] == '=')
301
 
        {
302
 
          ++exp;
303
 
          lval->op = equal;
304
 
          result = EQUOP2;
305
 
        }
306
 
      else
307
 
        result = YYERRCODE;
308
 
      break;
309
 
 
310
 
    case '!':
311
 
      if (exp[0] == '=')
312
 
        {
313
 
          ++exp;
314
 
          lval->op = not_equal;
315
 
          result = EQUOP2;
316
 
        }
317
 
      break;
318
 
 
319
 
    case '&':
320
 
    case '|':
321
 
      if (exp[0] == result)
322
 
        ++exp;
323
 
      else
324
 
        result = YYERRCODE;
325
 
      break;
326
 
 
327
 
    case '<':
328
 
      if (exp[0] == '=')
329
 
        {
330
 
          ++exp;
331
 
          lval->op = less_or_equal;
332
 
        }
333
 
      else
334
 
        lval->op = less_than;
335
 
      result = CMPOP2;
336
 
      break;
337
 
 
338
 
    case '>':
339
 
      if (exp[0] == '=')
340
 
        {
341
 
          ++exp;
342
 
          lval->op = greater_or_equal;
343
 
        }
344
 
      else
345
 
        lval->op = greater_than;
346
 
      result = CMPOP2;
347
 
      break;
348
 
 
349
 
    case '*':
350
 
      lval->op = mult;
351
 
      result = MULOP2;
352
 
      break;
353
 
 
354
 
    case '/':
355
 
      lval->op = divide;
356
 
      result = MULOP2;
357
 
      break;
358
 
 
359
 
    case '%':
360
 
      lval->op = module;
361
 
      result = MULOP2;
362
 
      break;
363
 
 
364
 
    case '+':
365
 
      lval->op = plus;
366
 
      result = ADDOP2;
367
 
      break;
368
 
 
369
 
    case '-':
370
 
      lval->op = minus;
371
 
      result = ADDOP2;
372
 
      break;
373
 
 
374
 
    case 'n':
375
 
    case '?':
376
 
    case ':':
377
 
    case '(':
378
 
    case ')':
379
 
      /* Nothing, just return the character.  */
380
 
      break;
381
 
 
382
 
    case ';':
383
 
    case '\n':
384
 
    case '\0':
385
 
      /* Be safe and let the user call this function again.  */
386
 
      --exp;
387
 
      result = YYEOF;
388
 
      break;
389
 
 
390
 
    default:
391
 
      result = YYERRCODE;
392
 
#if YYDEBUG != 0
393
 
      --exp;
394
 
#endif
395
 
      break;
396
 
    }
397
 
 
398
 
  *pexp = exp;
399
 
 
400
 
  return result;
401
 
}
402
 
 
403
 
 
404
 
static void
405
 
yyerror (str)
406
 
     const char *str;
407
 
{
408
 
  /* Do nothing.  We don't print error messages here.  */
409
 
}