Blame intl/plural.y

Packit bbfece
%{
Packit bbfece
/* Expression parsing for plural form selection.
Packit bbfece
   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
Packit bbfece
   Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
Packit bbfece
Packit bbfece
   This program is free software; you can redistribute it and/or modify it
Packit bbfece
   under the terms of the GNU Library General Public License as published
Packit bbfece
   by the Free Software Foundation; either version 2, or (at your option)
Packit bbfece
   any later version.
Packit bbfece
Packit bbfece
   This program is distributed in the hope that it will be useful,
Packit bbfece
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit bbfece
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit bbfece
   Library General Public License for more details.
Packit bbfece
Packit bbfece
   You should have received a copy of the GNU Library General Public
Packit bbfece
   License along with this program; if not, write to the Free Software
Packit bbfece
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301,
Packit bbfece
   USA.  */
Packit bbfece
Packit bbfece
/* The bison generated parser uses alloca.  AIX 3 forces us to put this
Packit bbfece
   declaration at the beginning of the file.  The declaration in bison's
Packit bbfece
   skeleton file comes too late.  This must come before <config.h>
Packit bbfece
   because <config.h> may include arbitrary system headers.  */
Packit bbfece
#if defined _AIX && !defined __GNUC__
Packit bbfece
 #pragma alloca
Packit bbfece
#endif
Packit bbfece
Packit bbfece
#ifdef HAVE_CONFIG_H
Packit bbfece
# include <config.h>
Packit bbfece
#endif
Packit bbfece
Packit bbfece
#include <stddef.h>
Packit bbfece
#include <stdlib.h>
Packit bbfece
#include "plural-exp.h"
Packit bbfece
Packit bbfece
/* The main function generated by the parser is called __gettextparse,
Packit bbfece
   but we want it to be called PLURAL_PARSE.  */
Packit bbfece
#ifndef _LIBC
Packit bbfece
# define __gettextparse PLURAL_PARSE
Packit bbfece
#endif
Packit bbfece
Packit bbfece
#define YYLEX_PARAM	&((struct parse_args *) arg)->cp
Packit bbfece
#define YYPARSE_PARAM	arg
Packit bbfece
%}
Packit bbfece
%pure_parser
Packit bbfece
%expect 7
Packit bbfece
Packit bbfece
%union {
Packit bbfece
  unsigned long int num;
Packit bbfece
  enum operator op;
Packit bbfece
  struct expression *exp;
Packit bbfece
}
Packit bbfece
Packit bbfece
%{
Packit bbfece
/* Prototypes for local functions.  */
Packit bbfece
static struct expression *new_exp PARAMS ((int nargs, enum operator op,
Packit bbfece
					   struct expression * const *args));
Packit bbfece
static inline struct expression *new_exp_0 PARAMS ((enum operator op));
Packit bbfece
static inline struct expression *new_exp_1 PARAMS ((enum operator op,
Packit bbfece
						   struct expression *right));
Packit bbfece
static struct expression *new_exp_2 PARAMS ((enum operator op,
Packit bbfece
					     struct expression *left,
Packit bbfece
					     struct expression *right));
Packit bbfece
static inline struct expression *new_exp_3 PARAMS ((enum operator op,
Packit bbfece
						   struct expression *bexp,
Packit bbfece
						   struct expression *tbranch,
Packit bbfece
						   struct expression *fbranch));
Packit bbfece
static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
Packit bbfece
static void yyerror PARAMS ((const char *str));
Packit bbfece
Packit bbfece
/* Allocation of expressions.  */
Packit bbfece
Packit bbfece
static struct expression *
Packit bbfece
new_exp (nargs, op, args)
Packit bbfece
     int nargs;
Packit bbfece
     enum operator op;
Packit bbfece
     struct expression * const *args;
Packit bbfece
{
Packit bbfece
  int i;
Packit bbfece
  struct expression *newp;
Packit bbfece
Packit bbfece
  /* If any of the argument could not be malloc'ed, just return NULL.  */
Packit bbfece
  for (i = nargs - 1; i >= 0; i--)
Packit bbfece
    if (args[i] == NULL)
Packit bbfece
      goto fail;
Packit bbfece
Packit bbfece
  /* Allocate a new expression.  */
Packit bbfece
  newp = (struct expression *) malloc (sizeof (*newp));
Packit bbfece
  if (newp != NULL)
Packit bbfece
    {
Packit bbfece
      newp->nargs = nargs;
Packit bbfece
      newp->operation = op;
Packit bbfece
      for (i = nargs - 1; i >= 0; i--)
Packit bbfece
	newp->val.args[i] = args[i];
Packit bbfece
      return newp;
Packit bbfece
    }
Packit bbfece
Packit bbfece
 fail:
Packit bbfece
  for (i = nargs - 1; i >= 0; i--)
Packit bbfece
    FREE_EXPRESSION (args[i]);
Packit bbfece
Packit bbfece
  return NULL;
Packit bbfece
}
Packit bbfece
Packit bbfece
static inline struct expression *
Packit bbfece
new_exp_0 (op)
Packit bbfece
     enum operator op;
Packit bbfece
{
Packit bbfece
  return new_exp (0, op, NULL);
Packit bbfece
}
Packit bbfece
Packit bbfece
static inline struct expression *
Packit bbfece
new_exp_1 (op, right)
Packit bbfece
     enum operator op;
Packit bbfece
     struct expression *right;
Packit bbfece
{
Packit bbfece
  struct expression *args[1];
Packit bbfece
Packit bbfece
  args[0] = right;
Packit bbfece
  return new_exp (1, op, args);
Packit bbfece
}
Packit bbfece
Packit bbfece
static struct expression *
Packit bbfece
new_exp_2 (op, left, right)
Packit bbfece
     enum operator op;
Packit bbfece
     struct expression *left;
Packit bbfece
     struct expression *right;
Packit bbfece
{
Packit bbfece
  struct expression *args[2];
Packit bbfece
Packit bbfece
  args[0] = left;
Packit bbfece
  args[1] = right;
Packit bbfece
  return new_exp (2, op, args);
Packit bbfece
}
Packit bbfece
Packit bbfece
static inline struct expression *
Packit bbfece
new_exp_3 (op, bexp, tbranch, fbranch)
Packit bbfece
     enum operator op;
Packit bbfece
     struct expression *bexp;
Packit bbfece
     struct expression *tbranch;
Packit bbfece
     struct expression *fbranch;
Packit bbfece
{
Packit bbfece
  struct expression *args[3];
Packit bbfece
Packit bbfece
  args[0] = bexp;
Packit bbfece
  args[1] = tbranch;
Packit bbfece
  args[2] = fbranch;
Packit bbfece
  return new_exp (3, op, args);
Packit bbfece
}
Packit bbfece
Packit bbfece
%}
Packit bbfece
Packit bbfece
/* This declares that all operators have the same associativity and the
Packit bbfece
   precedence order as in C.  See [Harbison, Steele: C, A Reference Manual].
Packit bbfece
   There is no unary minus and no bitwise operators.
Packit bbfece
   Operators with the same syntactic behaviour have been merged into a single
Packit bbfece
   token, to save space in the array generated by bison.  */
Packit bbfece
%right '?'		/*   ?		*/
Packit bbfece
%left '|'		/*   ||		*/
Packit bbfece
%left '&'		/*   &&		*/
Packit bbfece
%left EQUOP2		/*   == !=	*/
Packit bbfece
%left CMPOP2		/*   < > <= >=	*/
Packit bbfece
%left ADDOP2		/*   + -	*/
Packit bbfece
%left MULOP2		/*   * / %	*/
Packit bbfece
%right '!'		/*   !		*/
Packit bbfece
Packit bbfece
%token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
Packit bbfece
%token <num> NUMBER
Packit bbfece
%type <exp> exp
Packit bbfece
Packit bbfece
%%
Packit bbfece
Packit bbfece
start:	  exp
Packit bbfece
	  {
Packit bbfece
	    if ($1 == NULL)
Packit bbfece
	      YYABORT;
Packit bbfece
	    ((struct parse_args *) arg)->res = $1;
Packit bbfece
	  }
Packit bbfece
	;
Packit bbfece
Packit bbfece
exp:	  exp '?' exp ':' exp
Packit bbfece
	  {
Packit bbfece
	    $$ = new_exp_3 (qmop, $1, $3, $5);
Packit bbfece
	  }
Packit bbfece
	| exp '|' exp
Packit bbfece
	  {
Packit bbfece
	    $$ = new_exp_2 (lor, $1, $3);
Packit bbfece
	  }
Packit bbfece
	| exp '&' exp
Packit bbfece
	  {
Packit bbfece
	    $$ = new_exp_2 (land, $1, $3);
Packit bbfece
	  }
Packit bbfece
	| exp EQUOP2 exp
Packit bbfece
	  {
Packit bbfece
	    $$ = new_exp_2 ($2, $1, $3);
Packit bbfece
	  }
Packit bbfece
	| exp CMPOP2 exp
Packit bbfece
	  {
Packit bbfece
	    $$ = new_exp_2 ($2, $1, $3);
Packit bbfece
	  }
Packit bbfece
	| exp ADDOP2 exp
Packit bbfece
	  {
Packit bbfece
	    $$ = new_exp_2 ($2, $1, $3);
Packit bbfece
	  }
Packit bbfece
	| exp MULOP2 exp
Packit bbfece
	  {
Packit bbfece
	    $$ = new_exp_2 ($2, $1, $3);
Packit bbfece
	  }
Packit bbfece
	| '!' exp
Packit bbfece
	  {
Packit bbfece
	    $$ = new_exp_1 (lnot, $2);
Packit bbfece
	  }
Packit bbfece
	| 'n'
Packit bbfece
	  {
Packit bbfece
	    $$ = new_exp_0 (var);
Packit bbfece
	  }
Packit bbfece
	| NUMBER
Packit bbfece
	  {
Packit bbfece
	    if (($$ = new_exp_0 (num)) != NULL)
Packit bbfece
	      $$->val.num = $1;
Packit bbfece
	  }
Packit bbfece
	| '(' exp ')'
Packit bbfece
	  {
Packit bbfece
	    $$ = $2;
Packit bbfece
	  }
Packit bbfece
	;
Packit bbfece
Packit bbfece
%%
Packit bbfece
Packit bbfece
void
Packit bbfece
internal_function
Packit bbfece
FREE_EXPRESSION (exp)
Packit bbfece
     struct expression *exp;
Packit bbfece
{
Packit bbfece
  if (exp == NULL)
Packit bbfece
    return;
Packit bbfece
Packit bbfece
  /* Handle the recursive case.  */
Packit bbfece
  switch (exp->nargs)
Packit bbfece
    {
Packit bbfece
    case 3:
Packit bbfece
      FREE_EXPRESSION (exp->val.args[2]);
Packit bbfece
      /* FALLTHROUGH */
Packit bbfece
    case 2:
Packit bbfece
      FREE_EXPRESSION (exp->val.args[1]);
Packit bbfece
      /* FALLTHROUGH */
Packit bbfece
    case 1:
Packit bbfece
      FREE_EXPRESSION (exp->val.args[0]);
Packit bbfece
      /* FALLTHROUGH */
Packit bbfece
    default:
Packit bbfece
      break;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  free (exp);
Packit bbfece
}
Packit bbfece
Packit bbfece
Packit bbfece
static int
Packit bbfece
yylex (lval, pexp)
Packit bbfece
     YYSTYPE *lval;
Packit bbfece
     const char **pexp;
Packit bbfece
{
Packit bbfece
  const char *exp = *pexp;
Packit bbfece
  int result;
Packit bbfece
Packit bbfece
  while (1)
Packit bbfece
    {
Packit bbfece
      if (exp[0] == '\0')
Packit bbfece
	{
Packit bbfece
	  *pexp = exp;
Packit bbfece
	  return YYEOF;
Packit bbfece
	}
Packit bbfece
Packit bbfece
      if (exp[0] != ' ' && exp[0] != '\t')
Packit bbfece
	break;
Packit bbfece
Packit bbfece
      ++exp;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  result = *exp++;
Packit bbfece
  switch (result)
Packit bbfece
    {
Packit bbfece
    case '0': case '1': case '2': case '3': case '4':
Packit bbfece
    case '5': case '6': case '7': case '8': case '9':
Packit bbfece
      {
Packit bbfece
	unsigned long int n = result - '0';
Packit bbfece
	while (exp[0] >= '0' && exp[0] <= '9')
Packit bbfece
	  {
Packit bbfece
	    n *= 10;
Packit bbfece
	    n += exp[0] - '0';
Packit bbfece
	    ++exp;
Packit bbfece
	  }
Packit bbfece
	lval->num = n;
Packit bbfece
	result = NUMBER;
Packit bbfece
      }
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case '=':
Packit bbfece
      if (exp[0] == '=')
Packit bbfece
	{
Packit bbfece
	  ++exp;
Packit bbfece
	  lval->op = equal;
Packit bbfece
	  result = EQUOP2;
Packit bbfece
	}
Packit bbfece
      else
Packit bbfece
	result = YYERRCODE;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case '!':
Packit bbfece
      if (exp[0] == '=')
Packit bbfece
	{
Packit bbfece
	  ++exp;
Packit bbfece
	  lval->op = not_equal;
Packit bbfece
	  result = EQUOP2;
Packit bbfece
	}
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case '&':
Packit bbfece
    case '|':
Packit bbfece
      if (exp[0] == result)
Packit bbfece
	++exp;
Packit bbfece
      else
Packit bbfece
	result = YYERRCODE;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case '<':
Packit bbfece
      if (exp[0] == '=')
Packit bbfece
	{
Packit bbfece
	  ++exp;
Packit bbfece
	  lval->op = less_or_equal;
Packit bbfece
	}
Packit bbfece
      else
Packit bbfece
	lval->op = less_than;
Packit bbfece
      result = CMPOP2;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case '>':
Packit bbfece
      if (exp[0] == '=')
Packit bbfece
	{
Packit bbfece
	  ++exp;
Packit bbfece
	  lval->op = greater_or_equal;
Packit bbfece
	}
Packit bbfece
      else
Packit bbfece
	lval->op = greater_than;
Packit bbfece
      result = CMPOP2;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case '*':
Packit bbfece
      lval->op = mult;
Packit bbfece
      result = MULOP2;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case '/':
Packit bbfece
      lval->op = divide;
Packit bbfece
      result = MULOP2;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case '%':
Packit bbfece
      lval->op = module;
Packit bbfece
      result = MULOP2;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case '+':
Packit bbfece
      lval->op = plus;
Packit bbfece
      result = ADDOP2;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case '-':
Packit bbfece
      lval->op = minus;
Packit bbfece
      result = ADDOP2;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case 'n':
Packit bbfece
    case '?':
Packit bbfece
    case ':':
Packit bbfece
    case '(':
Packit bbfece
    case ')':
Packit bbfece
      /* Nothing, just return the character.  */
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case ';':
Packit bbfece
    case '\n':
Packit bbfece
    case '\0':
Packit bbfece
      /* Be safe and let the user call this function again.  */
Packit bbfece
      --exp;
Packit bbfece
      result = YYEOF;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    default:
Packit bbfece
      result = YYERRCODE;
Packit bbfece
#if YYDEBUG != 0
Packit bbfece
      --exp;
Packit bbfece
#endif
Packit bbfece
      break;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  *pexp = exp;
Packit bbfece
Packit bbfece
  return result;
Packit bbfece
}
Packit bbfece
Packit bbfece
Packit bbfece
static void
Packit bbfece
yyerror (str)
Packit bbfece
     const char *str;
Packit bbfece
{
Packit bbfece
  /* Do nothing.  We don't print error messages here.  */
Packit bbfece
}