1 %{ 2 /* Expression parsing for plural form selection. 3 Copyright (C) 2000-2022 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 7 it under the terms of the GNU Lesser General Public License as published by 8 the Free Software Foundation; either version 2.1 of the License, or 9 (at your option) 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 14 GNU Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public License 17 along with this program. If not, see <https://www.gnu.org/licenses/>. */ 18 19 /* For bison < 2.0, the bison generated parser uses alloca. AIX 3 forces us 20 to put this declaration at the beginning of the file. The declaration in 21 bison's skeleton file comes too late. This must come before <config.h> 22 because <config.h> may include arbitrary system headers. 23 This can go away once the AM_INTL_SUBDIR macro requires bison >= 2.0. */ 24 #if defined _AIX && !defined __GNUC__ 25 #pragma alloca 26 #endif 27 28 #ifdef HAVE_CONFIG_H 29 # include <config.h> 30 #endif 31 32 #include <stddef.h> 33 #include <stdlib.h> 34 #include <string.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 /* Later we provide those prototypes. Without these macros, bison may 44 generate its own prototypes with possible conflicts. */ 45 #define YYLEX_IS_DECLARED 46 #define YYERROR_IS_DECLARED 47 48 %} 49 %parse-param {struct parse_args *arg} 50 %lex-param {struct parse_args *arg} 51 %define api.pure full 52 %expect 7 53 54 %union { 55 unsigned long int num; 56 enum expression_operator op; 57 struct expression *exp; 58 } 59 60 %{ 61 /* Prototypes for local functions. */ 62 static int yylex (YYSTYPE *lval, struct parse_args *arg); 63 static void yyerror (struct parse_args *arg, const char *str); 64 65 /* Allocation of expressions. */ 66 67 static struct expression * 68 new_exp (int nargs, enum expression_operator op, 69 struct expression * const *args) 70 { 71 int i; 72 struct expression *newp; 73 74 /* If any of the argument could not be malloc'ed, just return NULL. */ 75 for (i = nargs - 1; i >= 0; i--) 76 if (args[i] == NULL) 77 goto fail; 78 79 /* Allocate a new expression. */ 80 newp = (struct expression *) malloc (sizeof (*newp)); 81 if (newp != NULL) 82 { 83 newp->nargs = nargs; 84 newp->operation = op; 85 for (i = nargs - 1; i >= 0; i--) 86 newp->val.args[i] = args[i]; 87 return newp; 88 } 89 90 fail: 91 for (i = nargs - 1; i >= 0; i--) 92 FREE_EXPRESSION (args[i]); 93 94 return NULL; 95 } 96 97 static inline struct expression * 98 new_exp_0 (enum expression_operator op) 99 { 100 return new_exp (0, op, NULL); 101 } 102 103 static inline struct expression * 104 new_exp_1 (enum expression_operator op, struct expression *right) 105 { 106 struct expression *args[1]; 107 108 args[0] = right; 109 return new_exp (1, op, args); 110 } 111 112 static struct expression * 113 new_exp_2 (enum expression_operator op, struct expression *left, 114 struct expression *right) 115 { 116 struct expression *args[2]; 117 118 args[0] = left; 119 args[1] = right; 120 return new_exp (2, op, args); 121 } 122 123 static inline struct expression * 124 new_exp_3 (enum expression_operator op, struct expression *bexp, 125 struct expression *tbranch, struct expression *fbranch) 126 { 127 struct expression *args[3]; 128 129 args[0] = bexp; 130 args[1] = tbranch; 131 args[2] = fbranch; 132 return new_exp (3, op, args); 133 } 134 135 %} 136 137 /* This declares that all operators have the same associativity and the 138 precedence order as in C. See [Harbison, Steele: C, A Reference Manual]. 139 There is no unary minus and no bitwise operators. 140 Operators with the same syntactic behaviour have been merged into a single 141 token, to save space in the array generated by bison. */ 142 %right '?' /* ? */ 143 %left '|' /* || */ 144 %left '&' /* && */ 145 %left EQUOP2 /* == != */ 146 %left CMPOP2 /* < > <= >= */ 147 %left ADDOP2 /* + - */ 148 %left MULOP2 /* * / % */ 149 %right '!' /* ! */ 150 151 %token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2 152 %token <num> NUMBER 153 %type <exp> exp 154 155 %% 156 157 start: exp 158 { 159 if ($1 == NULL) 160 YYABORT; 161 arg->res = $1; 162 } 163 ; 164 165 exp: exp '?' exp ':' exp 166 { 167 $$ = new_exp_3 (qmop, $1, $3, $5); 168 } 169 | exp '|' exp 170 { 171 $$ = new_exp_2 (lor, $1, $3); 172 } 173 | exp '&' exp 174 { 175 $$ = new_exp_2 (land, $1, $3); 176 } 177 | exp EQUOP2 exp 178 { 179 $$ = new_exp_2 ($2, $1, $3); 180 } 181 | exp CMPOP2 exp 182 { 183 $$ = new_exp_2 ($2, $1, $3); 184 } 185 | exp ADDOP2 exp 186 { 187 $$ = new_exp_2 ($2, $1, $3); 188 } 189 | exp MULOP2 exp 190 { 191 $$ = new_exp_2 ($2, $1, $3); 192 } 193 | '!' exp 194 { 195 $$ = new_exp_1 (lnot, $2); 196 } 197 | 'n' 198 { 199 $$ = new_exp_0 (var); 200 } 201 | NUMBER 202 { 203 if (($$ = new_exp_0 (num)) != NULL) 204 $$->val.num = $1; 205 } 206 | '(' exp ')' 207 { 208 $$ = $2; 209 } 210 ; 211 212 %% 213 214 void 215 FREE_EXPRESSION (struct expression *exp) 216 { 217 if (exp == NULL) 218 return; 219 220 /* Handle the recursive case. */ 221 switch (exp->nargs) 222 { 223 case 3: 224 FREE_EXPRESSION (exp->val.args[2]); 225 /* FALLTHROUGH */ 226 case 2: 227 FREE_EXPRESSION (exp->val.args[1]); 228 /* FALLTHROUGH */ 229 case 1: 230 FREE_EXPRESSION (exp->val.args[0]); 231 /* FALLTHROUGH */ 232 default: 233 break; 234 } 235 236 free (exp); 237 } 238 239 240 static int 241 yylex (YYSTYPE *lval, struct parse_args *arg) 242 { 243 const char *exp = arg->cp; 244 int result; 245 246 while (1) 247 { 248 if (exp[0] == '\0') 249 { 250 arg->cp = exp; 251 return YYEOF; 252 } 253 254 if (exp[0] != ' ' && exp[0] != '\t') 255 break; 256 257 ++exp; 258 } 259 260 result = *exp++; 261 switch (result) 262 { 263 case '0': case '1': case '2': case '3': case '4': 264 case '5': case '6': case '7': case '8': case '9': 265 { 266 unsigned long int n = result - '0'; 267 while (exp[0] >= '0' && exp[0] <= '9') 268 { 269 n *= 10; 270 n += exp[0] - '0'; 271 ++exp; 272 } 273 lval->num = n; 274 result = NUMBER; 275 } 276 break; 277 278 case '=': 279 if (exp[0] == '=') 280 { 281 ++exp; 282 lval->op = equal; 283 result = EQUOP2; 284 } 285 else 286 result = YYERRCODE; 287 break; 288 289 case '!': 290 if (exp[0] == '=') 291 { 292 ++exp; 293 lval->op = not_equal; 294 result = EQUOP2; 295 } 296 break; 297 298 case '&': 299 case '|': 300 if (exp[0] == result) 301 ++exp; 302 else 303 result = YYERRCODE; 304 break; 305 306 case '<': 307 if (exp[0] == '=') 308 { 309 ++exp; 310 lval->op = less_or_equal; 311 } 312 else 313 lval->op = less_than; 314 result = CMPOP2; 315 break; 316 317 case '>': 318 if (exp[0] == '=') 319 { 320 ++exp; 321 lval->op = greater_or_equal; 322 } 323 else 324 lval->op = greater_than; 325 result = CMPOP2; 326 break; 327 328 case '*': 329 lval->op = mult; 330 result = MULOP2; 331 break; 332 333 case '/': 334 lval->op = divide; 335 result = MULOP2; 336 break; 337 338 case '%': 339 lval->op = module; 340 result = MULOP2; 341 break; 342 343 case '+': 344 lval->op = plus; 345 result = ADDOP2; 346 break; 347 348 case '-': 349 lval->op = minus; 350 result = ADDOP2; 351 break; 352 353 case 'n': 354 case '?': 355 case ':': 356 case '(': 357 case ')': 358 /* Nothing, just return the character. */ 359 break; 360 361 case ';': 362 case '\n': 363 case '\0': 364 /* Be safe and let the user call this function again. */ 365 --exp; 366 result = YYEOF; 367 break; 368 369 default: 370 result = YYERRCODE; 371 #if YYDEBUG != 0 372 --exp; 373 #endif 374 break; 375 } 376 377 arg->cp = exp; 378 379 return result; 380 } 381 382 383 static void 384 yyerror (struct parse_args *arg, const char *str) 385 { 386 /* Do nothing. We don't print error messages here. */ 387 } 388