V8/usr/src/cmd/awk/awk.g.y
%token FIRSTTOKEN /* must be first */
%token FATAL
%token PROGRAM PASTAT PASTAT2 XBEGIN XEND
%token NL
%token LT LE GT GE EQ NE APPEND
%token MATCH NOTMATCH
%token FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS
%token ADD MINUS MULT DIVIDE MOD
%token ASSIGN ADDEQ SUBEQ MULTEQ DIVEQ MODEQ POWEQ
%token PRINT PRINTF
%token DELETE
%token IF ELSE WHILE FOR IN INTEST NEXT EXIT BREAK CONTINUE
%right ASGNOP
%left BOR
%left AND
%nonassoc RELOP MATCHOP
%left CAT
%left '+' '-'
%left '*' '/' '%'
%left NOT UMINUS
%right POWER
%left POSTINCR PREINCR POSTDECR PREDECR INCR DECR
%left FIELD INDIRECT SUB GSUB SUBSTR LSUBSTR INDEX CALL RETURN FUNC BLTIN
%left SPRINTF GETLINE CLOSE
%token STRING NUMBER REGEXPR VAR ARG VARNF ARRAY SPLIT
%token LASTTOKEN /* must be last */
%{
#include "awk.h"
yywrap() { return(1); }
#ifndef DEBUG
# define PUTS(x)
#endif
Node *beginloc = 0, *endloc = 0;
int infunc = 0; /* = 1 if in arglist or body of func */
char *curfname = 0;
Node *arglist = 0; /* list of args for current function */
%}
%%
program:
pa_stats { if (errorflag==0)
winner = (Node *)stat3(PROGRAM, beginloc, $1, endloc); }
| error { yyclearin; bracecheck(); yyerror("bailing out"); }
;
andNL:
AND | andNL NL
;
begin:
XBEGIN '{' stmtlist '}' { beginloc = (Node*) linkum(beginloc,(Node *) $3); }
;
borNL:
BOR | borNL NL
;
commaNL:
',' | commaNL NL
;
compound_conditional:
conditional borNL conditional { $$ = op2(BOR, $1, $3); }
| conditional andNL conditional { $$ = op2(AND, $1, $3); }
| NOT conditional { $$ = op1(NOT, $2); }
| '(' compound_conditional ')' { $$ = $2; }
;
compound_pattern:
pattern borNL pattern { $$ = op2(BOR, $1, $3); }
| pattern andNL pattern { $$ = op2(AND, $1, $3); }
| NOT pattern { $$ = op1(NOT, $2); }
| '(' compound_pattern ')' { $$ = $2; }
;
conditional:
expr { $$ = op2(NE,$1,valtonode(lookup("$zero&null",symtab),CCON)); }
| compound_conditional
;
cond_expr:
rel_expr
| lex_expr
| in_expr
;
easy_expr:
term
| easy_expr term %prec CAT { $$ = op2(CAT, $1, $2); }
| var ASGNOP easy_expr { $$ = op2($2, $1, $3); }
;
elseNL:
ELSE | elseNL NL
;
end:
XEND '{' stmtlist '}' { endloc = (Node*) linkum(endloc,(Node *) $3); }
;
expr:
easy_expr
| getpipe
| cond_expr
;
exprlist:
expr
| exprlist commaNL expr { $$ = linkum($1, $3); }
;
field:
FIELD { $$ = valtonode($1, CFLD); }
| INDIRECT term { $$ = op1(INDIRECT, $2); }
;
for:
FOR '(' simple_stmt ';' conditional ';' simple_stmt rparenNL stmt
{ $$ = stat4(FOR, $3, $5, $7, $9); }
| FOR '(' simple_stmt ';' ';' simple_stmt rparenNL stmt
{ $$ = stat4(FOR, $3, 0, $6, $8); }
| FOR '(' varname IN varname rparenNL stmt
{ $$ = stat3(IN, $3, makearr($5), $7); }
;
func:
FUNC funcname '(' varlist rparenNL {infunc++;} '{' stmtlist '}'
{ infunc--; curfname=0; defn($2, $4, $8); }
;
funcname:
VAR { setfname($1); }
| CALL { setfname($1); }
;
getpipe:
easy_expr '|' GETLINE var { $$ = op3(GETLINE, $4, $2, $1); }
| easy_expr '|' GETLINE { $$ = op3(GETLINE, 0, $2, $1); }
;
if:
IF '(' conditional rparenNL { $$ = $3; }
;
in_expr:
expr IN varname { $$ = op2(INTEST, $1, makearr($3)); }
| '(' in_expr ')' { $$ = $2; }
;
lex_expr:
expr MATCHOP reg_expr { $$ = op3($2, 0, $1, makedfa(reparse($3), 0)); }
| expr MATCHOP expr
{ if (((Node*)$3)->ntype == NVALUE && ((Cell*)((Node*)$3)->narg[0])->csub == CCON)
$$ = op3($2, 0, $1, makedfa(reparse( ((Cell*)((Node*)$3)->narg[0])->sval)), 0);
else
$$ = op3($2, 1, $1, $3); }
| '(' lex_expr ')' { $$ = $2; }
;
opt_plist:
/* nothing */ { $$ = rectonode(); }
| plist
;
pa_stat:
pattern { $$ = stat2(PASTAT, $1, stat2(PRINT, rectonode(), 0)); }
| pattern '{' stmtlist '}' { $$ = stat2(PASTAT, $1, $3); }
| pattern ',' pattern { $$ = pa2stat($1, $3, stat2(PRINT, rectonode(), 0)); }
| pattern ',' pattern '{' stmtlist '}' { $$ = pa2stat($1, $3, $5); }
| '{' stmtlist '}' { $$ = stat2(PASTAT, 0, $2); }
;
pa_stats:
/* nothing */ { $$ = (int)0; }
| pa_stats NL
| pa_stats pa_stat { $$ = linkum($1, $2); }
| pa_stats begin
| pa_stats end
| pa_stats func
;
pattern:
reg_expr { $$ = op3(MATCH, 0, rectonode(), makedfa(reparse($1), 0)); }
| rel_expr
| lex_expr
| in_expr
| compound_pattern
;
plist:
easy_expr
| plist commaNL easy_expr { $$ = linkum($1, $3); }
| '(' plist ')' { $$ = $2; }
;
redir:
GT | APPEND | LT | '|'
;
reg_expr:
'/' {startreg();} REGEXPR '/' { $$ = $3; }
;
rel_expr:
expr relop expr { $$ = op2($2, $1, $3); }
| '(' rel_expr ')' { $$ = $2; }
;
relop:
EQ | NE | LT | LE | GT | GE
;
rparenNL:
')' | rparenNL NL
;
simple_stmt:
PRINT opt_plist redir expr { $$ = stat3($1, $2, $3, $4); }
| PRINT opt_plist { $$ = stat3($1, $2, 0, 0); }
| PRINTF plist redir expr { $$ = stat3($1, $2, $3, $4); }
| PRINTF plist { $$ = stat3($1, $2, 0, 0); }
| DELETE varname '[' expr ']' { $$ = stat2(DELETE, makearr($2), $4); }
| expr { $$ = exptostat($1); }
| /* nothing */ { $$ = (int)0; }
| error { yyclearin; yyerror("illegal statement"); }
;
st:
NL | ';'
;
stmt:
simple_stmt st
| RETURN st { $$ = stat1(RETURN, 0); }
| RETURN expr st { $$ = stat1(RETURN, $2); }
| NEXT st { $$ = stat1(NEXT, 0); }
| EXIT st { $$ = stat1(EXIT, 0); }
| EXIT expr st { $$ = stat1(EXIT, $2); }
| BREAK st { $$ = stat1(BREAK, 0); }
| CONTINUE st { $$ = stat1(CONTINUE, 0); }
| '{' stmtlist '}' { $$ = $2; }
| if stmt { $$ = stat3(IF, $1, $2, 0); }
| if stmt elseNL stmt { $$ = stat3(IF, $1, $2, $4); }
| while stmt { $$ = stat2(WHILE, $1, $2); }
| for
| varname st { yyerror("no-effect statement"); $$ = 0; }
;
stmtlist:
/* nothing */ { $$ = (int) 0; }
| stmtlist NL
| stmtlist ';'
| stmtlist stmt { $$ = linkum($1, $2); }
;
subop:
SUB | GSUB
;
term:
var
| CALL '(' ')' { $$ = op2(CALL, valtonode($1,CVAR), 0); }
| CALL '(' exprlist ')' { $$ = op2(CALL, valtonode($1,CVAR), $3); }
| NUMBER { $$ = valtonode($1, CCON); }
| STRING { $$ = valtonode($1, CCON); }
| CLOSE easy_expr { $$ = op1(CLOSE, $2); }
| GETLINE var LT easy_expr { $$ = op3(GETLINE, $2, $3, $4); }
| GETLINE LT easy_expr { $$ = op3(GETLINE, 0, $2, $3); }
| GETLINE var { $$ = op3(GETLINE, $2, 0, 0); }
| GETLINE { $$ = op3(GETLINE, 0, 0, 0); }
| BLTIN { $$ = op2(BLTIN, $1, rectonode()); }
| BLTIN '(' ')' { $$ = op2(BLTIN, $1, rectonode()); }
| BLTIN '(' exprlist ')' { $$ = op2(BLTIN, $1, $3); }
| SPRINTF '(' plist ')' { $$ = op1($1, $3); }
| SUBSTR '(' expr commaNL expr commaNL expr ')' { $$ = op3(SUBSTR, $3, $5, $7); }
| SUBSTR '(' expr commaNL expr ')' { $$ = op3(SUBSTR, $3, $5, 0); }
| subop '(' reg_expr commaNL expr ')' { $$ = op4($1, 0, makedfa(reparse($3), 1), $5, rectonode()); }
| subop '(' expr commaNL expr ')' { $$ = op4($1, 1, $3, $5, rectonode()); }
| subop '(' reg_expr commaNL expr commaNL expr ')' { $$ = op4($1, 0, makedfa(reparse($3), 1), $5, $7); }
| subop '(' expr commaNL expr commaNL expr ')' { $$ = op4($1, 1, $3, $5, $7); }
| SPLIT '(' expr commaNL varname commaNL expr ')' { $$ = op3(SPLIT, $3, makearr($5), $7); }
| SPLIT '(' expr commaNL varname ')' { $$ = op3(SPLIT, $3, makearr($5), 0); }
| INDEX '(' expr commaNL expr ')' { $$ = op2(INDEX, $3, $5); }
| '(' expr ')' { $$ = $2; }
| term '+' term { $$ = op2(ADD, $1, $3); }
| term '-' term { $$ = op2(MINUS, $1, $3); }
| term '*' term { $$ = op2(MULT, $1, $3); }
| term '/' term { $$ = op2(DIVIDE, $1, $3); }
| term '%' term { $$ = op2(MOD, $1, $3); }
| term POWER term { $$ = op2(POWER, $1, $3); }
| '-' term %prec UMINUS { $$ = op1(UMINUS, $2); }
| '+' term %prec UMINUS { $$ = $2; }
| INCR var { $$ = op1(PREINCR, $2); }
| DECR var { $$ = op1(PREDECR, $2); }
| var INCR { $$ = op1(POSTINCR, $1); }
| var DECR { $$ = op1(POSTDECR, $1); }
;
var:
varname
| varname '[' expr ']' { $$ = op2(ARRAY, makearr($1), $3); }
| field
;
varlist:
/* nothing */ { arglist = (Node *)($$ = 0); }
| VAR { $$ = valtonode($1,CVAR); arglist = (Node*) $$; }
| varlist commaNL VAR { $$ = linkum($1,valtonode($3,CVAR)); arglist = (Node*) $$; }
;
varname:
VAR { $$ = valtonode($1, CVAR); }
| ARG { $$ = op1(ARG, $1); }
| VARNF { $$ = op1(VARNF, $1); }
;
while:
WHILE '(' conditional rparenNL { $$ = $3; }
;
%%
setfname(p)
Cell *p;
{
extern int bracecnt, brackcnt, parencnt;
curfname = p->nval;
/*bracecnt = brackcnt = parencnt = 0;*/
}