source: trunk/third/gaim-encryption/intl/plural.y @ 22512

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