%{
/*
* Copyright (c) 1994
*/
#ifndef lint
static char rcsid[] = "@(#)$Id: parse.y,v 1.3 1994/12/02 19:10:24 ken Exp $";
static char copyright[] = "Copyright (c) 1993 All Rights Reserved";
#endif
/***********************************************************************
* FORMULA language Parser.
*/
#include <sys/types.h>
#include <stdio.h>
#include "ctools.h"
#include "formula.h"
#include "formulaP.h"
#define YYSTYPE union yystack
extern union yystack yylval;
%}
/* types of the non-terminals */
%type <sym> id ids id_list
%type <expr> lval factor func expr expr1 expr2 unary_expr
%type <expr> arg_list args optexpr nullexpr expr exprlist const_array const_item
%type <value> stat stat_list if_tail
/* Definition of returned tokens from the lexical analyzer */
%token ADDOP /* += */
%token SUBOP /* -= */
%token MULOP /* *= */
%token DIVOP /* /= */
%token MODOP /* %= */
%token OROP /* |= */
%token ANDOP /* &= */
%token LSHOP /* <<= */
%token RSHOP /* >>= */
%token XOROP /* ^= */
%token OR /* || */
%token AND /* && */
%token LE /* < */
%token GE /* > */
%token NE /* != */
%token EQ /* == */
%token SHIFTL /* >> */
%token SHIFTR /* << */
%token PLUSPLUS /* ++ */
%token MINUSMINUS /* -- */
%token BIN0 /* user defined binary operator 0 */
%token BIN1 /* user defined binary operator 1 */
%token BIN2 /* user defined binary operator 2 */
%token BIN3 /* user defined binary operator 3 */
%token BIN4 /* user defined binary operator 4 */
%token BIN5 /* user defined binary operator 5 */
%token BIN6 /* user defined binary operator 6 */
%token BIN7 /* user defined binary operator 7 */
%token BIN8 /* user defined binary operator 8 */
%token BIN9 /* user defined binary operator 9 */
%token UN0 /* user defined unary operator 0 */
%token UN1 /* user defined unary operator 1 */
%token UN2 /* user defined unary operator 2 */
%token UN3 /* user defined unary operator 3 */
%token UN4 /* user defined unary operator 4 */
%token UN5 /* user defined unary operator 5 */
%token UN6 /* user defined unary operator 6 */
%token UN7 /* user defined unary operator 7 */
%token UN8 /* user defined unary operator 8 */
%token UN9 /* user defined unary operator 9 */
%token <value> NUMBER
%token <fvalue> FLOAT
%token <string> STRING
%token <sym> FUNCTION
%token <sym> PARAMETER
%token <sym> IDENTIFIER
%token <sym> VARIABLE
%token <sym> BUILTIN
%token <sym> APPFUNC
%token <sym> APPVAR
%token <sym> BIN0 BIN1 BIN2 BIN3 BIN4 BIN5 BIN6 BIN7 BIN8 BIN9
%token <sym> UN0 UN1 UN2 UN3 UN4 UN5 UN6 UN7 UN8 UN9
%token BREAK
%token CONTINUE
%token DO
%token ELSE
%token FOR
%token IF
%token RETURN
%token WHILE
%right '=' ADDOP SUBOP MULOP DIVOP MODOP OROP ANDOP LSHOP RSHOP XOROP BIN0 BIN1
%left OR
%left AND
%left '|'
%left '^'
%left '&'
%left EQ NE BIN2 BIN3 BIN4 BIN5
%left '<' LE '>' GE
%left SHIFTL SHIFTR
%left '+' '-'
%left '*' '/' '%' BIN6 BIN7 BIN8 BIN9
%start program
%%
program : exprlist { gen_the_expr($1? $1 : gennumber(0)); }
| funclist exprlist { gen_the_expr($2? $2 : gennumber(0)); }
;
exprlist : nullexpr { $$ = $1; }
| exprlist ';' nullexpr {
if($3) {
if($1) gen_expr($1);
$$ = $3;
} else
$$ = $1;
}
;
nullexpr : expr { $$ = $1; }
| /* empty */ { $$ = NULL; }
;
funclist : func
| funclist func
;
func : IDENTIFIER id_list
{ func_1($1,$2); }
'{' opt_stat_list '}'
{ func_2($1,$2); }
;
opt_stat_list : stat_list
| /* empty */
;
id_list : '(' ids ')' { $$ = $2; }
| '(' ')'
{ $$ = NULL; }
;
ids : id
{ $1->type = PARAMETER;
$1->u.val = 0;
$1->w.param = NULL;
$$ = $1; }
| ids ',' id
{ $3->type = PARAMETER;
$3->u.val = $1->u.val + 1;
$3->w.param = $1;
$$ = $3; }
;
id : PARAMETER
{ formula_error("%s is already used as a parameter",
$1->name); }
| VARIABLE
{ formula_error("%s is already a being used as a variable",
$1->name); }
| APPVAR
{ formula_error("%s is already a being used as a variable",
$1->name); }
| IDENTIFIER
{ $$ = $1; }
| FUNCTION
{ formula_error("%s is being used as a function",
$1->name); }
| APPFUNC
{ formula_error("%s is being used as a function",
$1->name); }
;
stat : RETURN optexpr ';' { gen_return($2); }
| expr ';' { gen_expr($1); }
| BREAK ';' { gen_break(FG.lineno); }
| CONTINUE ';' { gen_continue(FG.lineno); }
| IF '(' expr ')'
{ $$ = gen_if1($3); }
stat if_tail
{ gen_if2($<value>5,$7); }
| FOR '(' optexpr ';' optexpr ';' optexpr ')'
{ $$ = gen1for($3,$5); }
stat
{ gen2for($<value>9,$7); }
| WHILE '(' expr ')'
{ $$ = gen1while($3); }
stat
{ gen2while($<value>5); }
| DO
{ $$ = gen_do1(); }
stat WHILE '(' expr ')' ';'
{ gen_do2($6,$<value>2); }
| '{' stat_list '}' {;}
| '{' '}' {;}
| ';' {;}
;
if_tail : /* empty */ { $$ = -1; }
| ELSE { $$ = gen_if3(); } stat
{ $$ = $<value>2; }
;
stat_list : stat_list stat {;}
| stat {;}
;
optexpr : expr { $$ = $1; }
| /* empty */ { $$ = gennumber(1); }
;
unary_expr : '!' unary_expr { $$ = genbinary(OP_NOT,NULL,$2); }
| '-' unary_expr { $$ = genbinary(OP_NEG,NULL,$2); }
| '~' unary_expr { $$ = genbinary(OP_BNOT,NULL,$2); }
| UN0 unary_expr { $$ = gen_userbinary(OP_USERUNOP,$1,NULL,$2); }
| UN1 unary_expr { $$ = gen_userbinary(OP_USERUNOP,$1,NULL,$2); }
| UN2 unary_expr { $$ = gen_userbinary(OP_USERUNOP,$1,NULL,$2); }
| UN3 unary_expr { $$ = gen_userbinary(OP_USERUNOP,$1,NULL,$2); }
| UN4 unary_expr { $$ = gen_userbinary(OP_USERUNOP,$1,NULL,$2); }
| UN5 unary_expr { $$ = gen_userbinary(OP_USERUNOP,$1,NULL,$2); }
| UN6 unary_expr { $$ = gen_userbinary(OP_USERUNOP,$1,NULL,$2); }
| UN7 unary_expr { $$ = gen_userbinary(OP_USERUNOP,$1,NULL,$2); }
| UN8 unary_expr { $$ = gen_userbinary(OP_USERUNOP,$1,NULL,$2); }
| UN9 unary_expr { $$ = gen_userbinary(OP_USERUNOP,$1,NULL,$2); }
| PLUSPLUS lval { $$ = genbinary(OP_ADDOP,$2,gennumber(1)); }
| MINUSMINUS lval { $$ = genbinary(OP_SUBOP,$2,gennumber(1)); }
| lval PLUSPLUS
{ $$ = genbinary(OP_PLUSPLUS,NULL,$1); }
| lval MINUSMINUS
{ $$ = genbinary(OP_MINUSMINUS,NULL,$1); }
| factor { $$ = $1; }
;
expr2 : expr2 OR expr2 { $$ = genbinary(OP_OR,$1,$3); }
| expr2 AND expr2 { $$ = genbinary(OP_AND,$1,$3); }
| expr2 '|' expr2 { $$ = genbinary(OP_BOR,$1,$3); }
| expr2 '^' expr2 { $$ = genbinary(OP_XOR,$1,$3); }
| expr2 '&' expr2 { $$ = genbinary(OP_BAND,$1,$3); }
| expr2 EQ expr2 { $$ = genbinary(OP_EQ,$1,$3); }
| expr2 NE expr2 { $$ = genbinary(OP_NE,$1,$3); }
| expr2 '>' expr2 { $$ = genbinary(OP_GT,$1,$3); }
| expr2 '<' expr2 { $$ = genbinary(OP_LT,$1,$3); }
| expr2 GE expr2 { $$ = genbinary(OP_GE,$1,$3); }
| expr2 LE expr2 { $$ = genbinary(OP_LE,$1,$3); }
| expr2 SHIFTL expr2 { $$ = genbinary(OP_SHL,$1,$3); }
| expr2 SHIFTR expr2 { $$ = genbinary(OP_SHR,$1,$3); }
| expr2 '+' expr2 { $$ = genbinary(OP_ADD,$1,$3); }
| expr2 '-' expr2 { $$ = genbinary(OP_SUB,$1,$3); }
| expr2 '%' expr2 { $$ = genbinary(OP_MOD,$1,$3); }
| expr2 '*' expr2 { $$ = genbinary(OP_MUL,$1,$3); }
| expr2 '/' expr2 { $$ = genbinary(OP_DIV,$1,$3); }
| expr2 BIN0 expr2 { $$ = gen_userbinary(OP_USERBINOP,$2,$1,$3); }
| expr2 BIN1 expr2 { $$ = gen_userbinary(OP_USERBINOP,$2,$1,$3); }
| expr2 BIN2 expr2 { $$ = gen_userbinary(OP_USERBINOP,$2,$1,$3); }
| expr2 BIN3 expr2 { $$ = gen_userbinary(OP_USERBINOP,$2,$1,$3); }
| expr2 BIN4 expr2 { $$ = gen_userbinary(OP_USERBINOP,$2,$1,$3); }
| expr2 BIN5 expr2 { $$ = gen_userbinary(OP_USERBINOP,$2,$1,$3); }
| expr2 BIN6 expr2 { $$ = gen_userbinary(OP_USERBINOP,$2,$1,$3); }
| expr2 BIN7 expr2 { $$ = gen_userbinary(OP_USERBINOP,$2,$1,$3); }
| expr2 BIN8 expr2 { $$ = gen_userbinary(OP_USERBINOP,$2,$1,$3); }
| expr2 BIN9 expr2 { $$ = gen_userbinary(OP_USERBINOP,$2,$1,$3); }
| unary_expr { $$ = $1; }
;
expr1 : expr2 '?' expr1 ':' expr1 { $$ = gentrinary($1,$3,$5); }
| expr2 { $$ = $1; }
;
expr : lval '=' expr { $$ = genbinary(OP_ASSIGN,$1,$3); }
| lval ADDOP expr { $$ = genbinary(OP_ADDOP,$1,$3); }
| lval SUBOP expr { $$ = genbinary(OP_SUBOP,$1,$3); }
| lval MULOP expr { $$ = genbinary(OP_MULOP,$1,$3); }
| lval DIVOP expr { $$ = genbinary(OP_DIVOP,$1,$3); }
| lval MODOP expr { $$ = genbinary(OP_MODOP,$1,$3); }
| lval RSHOP expr { $$ = genbinary(OP_RSHOP,$1,$3); }
| lval LSHOP expr { $$ = genbinary(OP_LSHOP,$1,$3); }
| lval OROP expr { $$ = genbinary(OP_OROP,$1,$3); }
| lval ANDOP expr { $$ = genbinary(OP_ANDOP,$1,$3); }
| lval XOROP expr { $$ = genbinary(OP_XOROP,$1,$3); }
| expr1 { $$ = $1; }
;
lval : VARIABLE { $$ = genvar($1,NULL); }
| VARIABLE '[' expr ']' { $$ = genvar($1,$3); }
| PARAMETER { $$ = genparam($1,NULL); }
| PARAMETER '[' expr ']' { $$ = genparam($1,$3); }
| APPVAR { $$ = genappvar($1,NULL); }
| APPVAR '[' expr ']' { $$ = genappvar($1,$3); }
| IDENTIFIER { $$ = genident($1,NULL); }
| IDENTIFIER '[' expr ']' { $$ = genident($1,$3); }
;
factor : '(' expr ')' { $$ = $2; }
| STRING { $$ = genstring($1); }
| NUMBER { $$ = gennumber($1); }
| FLOAT { $$ = genfloat($1); }
| lval { $$ = $1; }
| FUNCTION arg_list { $$ = genfunc($1,$2); }
| BUILTIN arg_list { $$ = genbuiltin($1,$2); }
| APPFUNC arg_list { $$ = genappfunc($1,$2); }
| '[' const_array ']' { $$ = $2; }
;
const_item : STRING { $$ = genstring($1); }
| NUMBER { $$ = gennumber($1); }
| FLOAT { $$ = genfloat($1); }
| '-' NUMBER { $$ = gennumber(-$2); }
| '-' FLOAT { $$ = genfloat(-$2); }
;
const_array : const_item { $$ = genconstarray(NULL,$1); }
| const_array ',' const_item { $$ = genconstarray($1,$3); }
arg_list : '(' args ')' { $$ = $2; }
| '(' ')' { $$ = NULL; }
| /* empty */ { $$ = NULL; }
;
args : expr { $$ = genargs(NULL,$1); }
| args ',' expr { $$ = genargs($1,$3); }
;
%%
/* yyerror -
* Pass control to the "real" error function.
*/
static void yyerror(s)
char *s;
{
formula_error(s);
}
