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