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