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