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