/* ----------------------------------------------------------------------
* FILE: rhparse.y
* PACKAGE: rh - recursive file finder.
* VERSION: 4.0
* DESCRIPTION:
* This contains the YACC parser for the rh language.
*
* REVISION HISTORY:
* Oct 20, 1990 - re-Created.
*
* AUTHOR:
* Ken Stauffer.
* ---------------------------------------------------------------------- */
%{
#include <time.h>
#include <varargs.h>
#include "rh.h"
#define YYSTYPE union yystack
int lineno; /* current line number */
static struct symbol *curfunc = NULL;
extern struct expr *genbinary(), *gentrinary(), *genvar(), *genparam(),
*genident(), *genstring(), *gennumber(), *genbuiltin(),
*genargs(), *genfunc();
extern union yystack yylval;
extern char *rhstr;
extern char *rhfilename;
extern FILE *rhfile;
%}
/* types of the non-terminals */
%type <sym> id ids id_list
%type <expr> lval factor func expr expr1 expr2 unary_expr arg_list args optexpr
%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 <value> NUMBER
%token <string> STRING
%token <sym> FIELD
%token <sym> FUNCTION
%token <sym> PARAMETER
%token <sym> IDENTIFIER
%token <sym> VARIABLE
%token <sym> BUILTIN
%token BEGIN
%token END
%token BREAK
%token CONTINUE
%token DO
%token ELSE
%token EXIT
%token FOR
%token IF
%token NEXT
%token RETURN
%token UNDEFINE
%token WHILE
%right '=' ADDOP SUBOP MULOP DIVOP MODOP OROP ANDOP LSHOP RSHOP XOROP
%left OR
%left AND
%left '|'
%left '^'
%left '&'
%left EQ NE
%left '<' LE '>' GE
%left SHIFTL SHIFTR
%left '+' '-'
%left '*' '/' '%'
%start program
%%
program : expr { gen1match($1);
gendefault(); }
| bigprogram
;
bigprogram : func
| matchrule
| undefine
| bigprogram func
| bigprogram matchrule
| bigprogram undefine
;
undefine : UNDEFINE undef_list ';'
undef : IDENTIFIER {}
| FUNCTION { remove($1->name); }
| VARIABLE
{ if( $1->bvar )
error("%s is a built in variable", $1->name);
else
remove($1->name);
}
;
undef_list : undef
| undef_list ',' undef
;
matchrule : expr
{ gen1match($1); }
'{' stat_list '}'
{ gen2match(); }
| expr ';' { gen1match($1);
gendefault(); }
| BEGIN
{ genbeg1(); }
'{' stat_list '}'
{ genbeg2(); }
| END
{ genend1(); }
'{' stat_list '}'
{ genend2(); }
| '{'
{ gen1match(NULL); }
stat_list '}'
{ gen2match(); }
;
func : IDENTIFIER id_list
{ func_1($1,$2);
curfunc = $1; }
'{' opt_stat_list '}'
{ func_2($1,$2);
curfunc = NULL; }
;
opt_stat_list : stat_list
| /* empty */
;
id_list : '(' ids ')' { $$ = $2; }
| '(' ')'
{ $$ = NULL; }
;
ids : id
{ $1->type = PARAMETER;
$1->val = 0;
$1->param = NULL;
$$ = $1; }
| ids ',' id
{ $3->type = PARAMETER;
$3->val = $1->val + 1;
$3->param = $1;
$$ = $3; }
;
id : PARAMETER
{ error("%s is already used as a parameter",
$1->name); }
| VARIABLE
{ error("%s is already a global variable",
$1->name); }
| IDENTIFIER
{ $$ = $1; }
| FUNCTION
{ error("%s is already a function",
$1->name); }
;
stat : RETURN optexpr ';' { gen_return($2,curfunc); }
| expr ';' { gen_expr($1); }
| BREAK ';' { gen_break(lineno); }
| CONTINUE ';' { gen_continue(lineno); }
| NEXT ';' { gen_next(curfunc); }
| 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); }
| 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_OR1,$1,$3); }
| expr2 AND expr2 { $$ = genbinary(OP_AND1,$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); }
| 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); }
| IDENTIFIER { $$ = genident($1,NULL); }
| IDENTIFIER '[' expr ']' { $$ = genident($1,$3); }
;
factor : '(' expr ')' { $$ = $2; }
| STRING { $$ = genstring($1); }
| NUMBER { $$ = gennumber($1); }
| lval { $$ = $1; }
| FUNCTION arg_list { $$ = genfunc($1,$2); }
| BUILTIN arg_list { $$ = genbuiltin($1,$2); }
;
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.
*/
yyerror(s)
char *s;
{
error(s);
}
/* error -
* Print an error and exit. Do not attempt to recover from
* the error.
*/
error(va_alist)
va_dcl
{
va_list ap;
char *fmt;
va_start(ap);
fmt = va_arg(ap, char *);
fprintf(stderr,"%s: line: %d, ",rhfilename, lineno);
vfprintf(stderr,fmt, ap);
fprintf(stderr,".\n");
va_end(ap);
exit(1);
}
