* sysdeps/unix/sysv/linux/m68k/bits/fcntl.h: New file.
[glibc.git] / intl / plural.y
blobc13dbafab88dcf176b56569958759809e96e887f
1 %{
2 /* Expression parsing for plural form selection.
3 Copyright (C) 2000 Free Software Foundation, Inc.
4 Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C Library 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.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include "gettext.h"
24 #include "gettextP.h"
26 #define YYLEX_PARAM &((struct parse_args *) arg)->cp
27 #define YYPARSE_PARAM arg
29 %pure_parser
30 %expect 10
32 %union {
33 unsigned long int num;
34 struct expression *exp;
38 /* Prototypes for local functions. */
39 static struct expression *new_exp (enum operator op, int n, ...);
40 static int yylex (YYSTYPE *lval, const char **pexp);
41 static void yyerror (const char *str);
44 %left '?'
45 %left '|'
46 %left '&'
47 %left '=', '!'
48 %left '+', '-'
49 %left '*', '/', '%'
50 %token <num> NUMBER
51 %type <exp> exp
55 start: exp
57 ((struct parse_args *) arg)->res = $1;
61 exp: exp '?' exp ':' exp
63 if (($$ = new_exp (qmop, 3, $1, $3, $5)) == NULL)
64 YYABORT
66 | exp '|' exp
68 if (($$ = new_exp (lor, 2, $1, $3)) == NULL)
69 YYABORT
71 | exp '&' exp
73 if (($$ = new_exp (land, 2, $1, $3)) == NULL)
74 YYABORT
76 | exp '=' exp
78 if (($$ = new_exp (equal, 2, $1, $3)) == NULL)
79 YYABORT
81 | exp '!' exp
83 if (($$ = new_exp (not_equal, 2, $1, $3)) == NULL)
84 YYABORT
86 | exp '+' exp
88 if (($$ = new_exp (plus, 2, $1, $3)) == NULL)
89 YYABORT
91 | exp '-' exp
93 if (($$ = new_exp (minus, 2, $1, $3)) == NULL)
94 YYABORT
96 | exp '*' exp
98 if (($$ = new_exp (mult, 2, $1, $3)) == NULL)
99 YYABORT
101 | exp '/' exp
103 if (($$ = new_exp (divide, 2, $1, $3)) == NULL)
104 YYABORT
106 | exp '%' exp
108 if (($$ = new_exp (module, 2, $1, $3)) == NULL)
109 YYABORT
111 | 'n'
113 if (($$ = new_exp (var, 0)) == NULL)
114 YYABORT
116 | NUMBER
118 if (($$ = new_exp (num, 0)) == NULL)
119 YYABORT;
120 $$->val.num = $1
122 | '(' exp ')'
124 $$ = $2
130 static struct expression *
131 new_exp (enum operator op, int n, ...)
133 struct expression *newp = (struct expression *) calloc (1, sizeof (*newp));
134 va_list va;
136 va_start (va, n);
138 if (newp == NULL)
139 while (n-- > 0)
140 __gettext_free_exp (va_arg (va, struct expression *));
141 else
143 newp->operation = op;
144 if (n > 0)
146 newp->val.args3.bexp = va_arg (va, struct expression *);
147 newp->val.args3.tbranch = va_arg (va, struct expression *);
149 if (n > 2)
150 newp->val.args3.fbranch = va_arg (va, struct expression *);
152 if (newp->val.args3.bexp == NULL
153 || newp->val.args3.tbranch == NULL
154 || (n > 2 && newp->val.args3.fbranch == NULL))
156 __gettext_free_exp (newp);
157 newp = NULL;
162 va_end (va);
164 return newp;
167 void
168 internal_function
169 __gettext_free_exp (struct expression *exp)
171 if (exp == NULL)
172 return;
174 /* Handle the recursive case. */
175 switch (exp->operation)
177 case qmop:
178 __gettext_free_exp (exp->val.args3.fbranch);
179 /* FALLTHROUGH */
181 case mult:
182 case divide:
183 case module:
184 case plus:
185 case minus:
186 case equal:
187 case not_equal:
188 case land:
189 case lor:
190 __gettext_free_exp (exp->val.args2.right);
191 __gettext_free_exp (exp->val.args2.left);
192 break;
194 default:
195 break;
198 free (exp);
202 static int
203 yylex (YYSTYPE *lval, const char **pexp)
205 const char *exp = *pexp;
206 int result;
208 while (1)
210 if (exp[0] == '\\' && exp[1] == '\n')
212 exp += 2;
213 continue;
216 if (exp[0] == '\0')
218 *pexp = exp;
219 return YYEOF;
222 if (exp[0] != ' ' && exp[0] != '\t')
223 break;
225 ++exp;
228 result = *exp++;
229 switch (result)
231 case '0' ... '9':
233 unsigned long int n = exp[-1] - '0';
234 while (exp[0] >= '0' && exp[0] <= '9')
236 n *= 10;
237 n += exp[0] - '0';
238 ++exp;
240 lval->num = n;
241 result = NUMBER;
243 break;
245 case '=':
246 case '!':
247 if (exp[0] == '=')
248 ++exp;
249 else
250 result = YYERRCODE;
251 break;
253 case '&':
254 case '|':
255 if (exp[0] == result)
256 ++exp;
257 else
258 result = YYERRCODE;
259 break;
261 case 'n':
262 case '*':
263 case '/':
264 case '%':
265 case '+':
266 case '-':
267 case '?':
268 case ':':
269 case '(':
270 case ')':
271 /* Nothing, just return the character. */
272 break;
274 case ';':
275 case '\n':
276 case '\0':
277 /* Be safe and let the user call this function again. */
278 --exp;
279 result = YYEOF;
280 break;
282 default:
283 result = YYERRCODE;
284 #if YYDEBUG != 0
285 --exp;
286 #endif
287 break;
290 *pexp = exp;
292 return result;
296 static void
297 yyerror (const char *str)
299 /* Do nothing. We don't print error messages here. */