1 %{ 2 /* Expression parsing for plural form selection. 3 Copyright (C) 2000-2001, 2003 Free Software Foundation, Inc. 4 Written by Ulrich Drepper <drepper (at) 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 } 382