home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / share / gettext / intl / plural.y < prev    next >
Encoding:
Lex Description  |  2006-08-18  |  7.2 KB  |  382 lines

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