(linenum→info "unix/slp.c:2238")

glibc/2.7/intl/plural.y

    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: }
Syntax (Markdown)