1*4b588458SPeter Avalos /**************************************************************** 2*4b588458SPeter Avalos Copyright (C) Lucent Technologies 1997 3*4b588458SPeter Avalos All Rights Reserved 4*4b588458SPeter Avalos 5*4b588458SPeter Avalos Permission to use, copy, modify, and distribute this software and 6*4b588458SPeter Avalos its documentation for any purpose and without fee is hereby 7*4b588458SPeter Avalos granted, provided that the above copyright notice appear in all 8*4b588458SPeter Avalos copies and that both that the copyright notice and this 9*4b588458SPeter Avalos permission notice and warranty disclaimer appear in supporting 10*4b588458SPeter Avalos documentation, and that the name Lucent Technologies or any of 11*4b588458SPeter Avalos its entities not be used in advertising or publicity pertaining 12*4b588458SPeter Avalos to distribution of the software without specific, written prior 13*4b588458SPeter Avalos permission. 14*4b588458SPeter Avalos 15*4b588458SPeter Avalos LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16*4b588458SPeter Avalos INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 17*4b588458SPeter Avalos IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 18*4b588458SPeter Avalos SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19*4b588458SPeter Avalos WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 20*4b588458SPeter Avalos IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 21*4b588458SPeter Avalos ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 22*4b588458SPeter Avalos THIS SOFTWARE. 23*4b588458SPeter Avalos ****************************************************************/ 24*4b588458SPeter Avalos 25*4b588458SPeter Avalos %{ 26*4b588458SPeter Avalos #include <stdio.h> 27*4b588458SPeter Avalos #include <string.h> 28*4b588458SPeter Avalos #include "awk.h" 29*4b588458SPeter Avalos 30*4b588458SPeter Avalos void checkdup(Node *list, Cell *item); 31*4b588458SPeter Avalos int yywrap(void) { return(1); } 32*4b588458SPeter Avalos 33*4b588458SPeter Avalos Node *beginloc = 0; 34*4b588458SPeter Avalos Node *endloc = 0; 35*4b588458SPeter Avalos int infunc = 0; /* = 1 if in arglist or body of func */ 36*4b588458SPeter Avalos int inloop = 0; /* = 1 if in while, for, do */ 37*4b588458SPeter Avalos char *curfname = 0; /* current function name */ 38*4b588458SPeter Avalos Node *arglist = 0; /* list of args for current function */ 39*4b588458SPeter Avalos %} 40*4b588458SPeter Avalos 41*4b588458SPeter Avalos %union { 42*4b588458SPeter Avalos Node *p; 43*4b588458SPeter Avalos Cell *cp; 44*4b588458SPeter Avalos int i; 45*4b588458SPeter Avalos char *s; 46*4b588458SPeter Avalos } 47*4b588458SPeter Avalos 48*4b588458SPeter Avalos %token <i> FIRSTTOKEN /* must be first */ 49*4b588458SPeter Avalos %token <p> PROGRAM PASTAT PASTAT2 XBEGIN XEND 50*4b588458SPeter Avalos %token <i> NL ',' '{' '(' '|' ';' '/' ')' '}' '[' ']' 51*4b588458SPeter Avalos %token <i> ARRAY 52*4b588458SPeter Avalos %token <i> MATCH NOTMATCH MATCHOP 53*4b588458SPeter Avalos %token <i> FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS EMPTYRE 54*4b588458SPeter Avalos %token <i> AND BOR APPEND EQ GE GT LE LT NE IN 55*4b588458SPeter Avalos %token <i> ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC 56*4b588458SPeter Avalos %token <i> SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT NEXTFILE 57*4b588458SPeter Avalos %token <i> ADD MINUS MULT DIVIDE MOD 58*4b588458SPeter Avalos %token <i> ASSIGN ASGNOP ADDEQ SUBEQ MULTEQ DIVEQ MODEQ POWEQ 59*4b588458SPeter Avalos %token <i> PRINT PRINTF SPRINTF 60*4b588458SPeter Avalos %token <p> ELSE INTEST CONDEXPR 61*4b588458SPeter Avalos %token <i> POSTINCR PREINCR POSTDECR PREDECR 62*4b588458SPeter Avalos %token <cp> VAR IVAR VARNF CALL NUMBER STRING 63*4b588458SPeter Avalos %token <s> REGEXPR 64*4b588458SPeter Avalos 65*4b588458SPeter Avalos %type <p> pas pattern ppattern plist pplist patlist prarg term re 66*4b588458SPeter Avalos %type <p> pa_pat pa_stat pa_stats 67*4b588458SPeter Avalos %type <s> reg_expr 68*4b588458SPeter Avalos %type <p> simple_stmt opt_simple_stmt stmt stmtlist 69*4b588458SPeter Avalos %type <p> var varname funcname varlist 70*4b588458SPeter Avalos %type <p> for if else while 71*4b588458SPeter Avalos %type <i> do st 72*4b588458SPeter Avalos %type <i> pst opt_pst lbrace rbrace rparen comma nl opt_nl and bor 73*4b588458SPeter Avalos %type <i> subop print 74*4b588458SPeter Avalos 75*4b588458SPeter Avalos %right ASGNOP 76*4b588458SPeter Avalos %right '?' 77*4b588458SPeter Avalos %right ':' 78*4b588458SPeter Avalos %left BOR 79*4b588458SPeter Avalos %left AND 80*4b588458SPeter Avalos %left GETLINE 81*4b588458SPeter Avalos %nonassoc APPEND EQ GE GT LE LT NE MATCHOP IN '|' 82*4b588458SPeter Avalos %left ARG BLTIN BREAK CALL CLOSE CONTINUE DELETE DO EXIT FOR FUNC 83*4b588458SPeter Avalos %left GSUB IF INDEX LSUBSTR MATCHFCN NEXT NUMBER 84*4b588458SPeter Avalos %left PRINT PRINTF RETURN SPLIT SPRINTF STRING SUB SUBSTR 85*4b588458SPeter Avalos %left REGEXPR VAR VARNF IVAR WHILE '(' 86*4b588458SPeter Avalos %left CAT 87*4b588458SPeter Avalos %left '+' '-' 88*4b588458SPeter Avalos %left '*' '/' '%' 89*4b588458SPeter Avalos %left NOT UMINUS 90*4b588458SPeter Avalos %right POWER 91*4b588458SPeter Avalos %right DECR INCR 92*4b588458SPeter Avalos %left INDIRECT 93*4b588458SPeter Avalos %token LASTTOKEN /* must be last */ 94*4b588458SPeter Avalos 95*4b588458SPeter Avalos %% 96*4b588458SPeter Avalos 97*4b588458SPeter Avalos program: 98*4b588458SPeter Avalos pas { if (errorflag==0) 99*4b588458SPeter Avalos winner = (Node *)stat3(PROGRAM, beginloc, $1, endloc); } 100*4b588458SPeter Avalos | error { yyclearin; bracecheck(); SYNTAX("bailing out"); } 101*4b588458SPeter Avalos ; 102*4b588458SPeter Avalos 103*4b588458SPeter Avalos and: 104*4b588458SPeter Avalos AND | and NL 105*4b588458SPeter Avalos ; 106*4b588458SPeter Avalos 107*4b588458SPeter Avalos bor: 108*4b588458SPeter Avalos BOR | bor NL 109*4b588458SPeter Avalos ; 110*4b588458SPeter Avalos 111*4b588458SPeter Avalos comma: 112*4b588458SPeter Avalos ',' | comma NL 113*4b588458SPeter Avalos ; 114*4b588458SPeter Avalos 115*4b588458SPeter Avalos do: 116*4b588458SPeter Avalos DO | do NL 117*4b588458SPeter Avalos ; 118*4b588458SPeter Avalos 119*4b588458SPeter Avalos else: 120*4b588458SPeter Avalos ELSE | else NL 121*4b588458SPeter Avalos ; 122*4b588458SPeter Avalos 123*4b588458SPeter Avalos for: 124*4b588458SPeter Avalos FOR '(' opt_simple_stmt ';' opt_nl pattern ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt 125*4b588458SPeter Avalos { --inloop; $$ = stat4(FOR, $3, notnull($6), $9, $12); } 126*4b588458SPeter Avalos | FOR '(' opt_simple_stmt ';' ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt 127*4b588458SPeter Avalos { --inloop; $$ = stat4(FOR, $3, NIL, $7, $10); } 128*4b588458SPeter Avalos | FOR '(' varname IN varname rparen {inloop++;} stmt 129*4b588458SPeter Avalos { --inloop; $$ = stat3(IN, $3, makearr($5), $8); } 130*4b588458SPeter Avalos ; 131*4b588458SPeter Avalos 132*4b588458SPeter Avalos funcname: 133*4b588458SPeter Avalos VAR { setfname($1); } 134*4b588458SPeter Avalos | CALL { setfname($1); } 135*4b588458SPeter Avalos ; 136*4b588458SPeter Avalos 137*4b588458SPeter Avalos if: 138*4b588458SPeter Avalos IF '(' pattern rparen { $$ = notnull($3); } 139*4b588458SPeter Avalos ; 140*4b588458SPeter Avalos 141*4b588458SPeter Avalos lbrace: 142*4b588458SPeter Avalos '{' | lbrace NL 143*4b588458SPeter Avalos ; 144*4b588458SPeter Avalos 145*4b588458SPeter Avalos nl: 146*4b588458SPeter Avalos NL | nl NL 147*4b588458SPeter Avalos ; 148*4b588458SPeter Avalos 149*4b588458SPeter Avalos opt_nl: 150*4b588458SPeter Avalos /* empty */ { $$ = 0; } 151*4b588458SPeter Avalos | nl 152*4b588458SPeter Avalos ; 153*4b588458SPeter Avalos 154*4b588458SPeter Avalos opt_pst: 155*4b588458SPeter Avalos /* empty */ { $$ = 0; } 156*4b588458SPeter Avalos | pst 157*4b588458SPeter Avalos ; 158*4b588458SPeter Avalos 159*4b588458SPeter Avalos 160*4b588458SPeter Avalos opt_simple_stmt: 161*4b588458SPeter Avalos /* empty */ { $$ = 0; } 162*4b588458SPeter Avalos | simple_stmt 163*4b588458SPeter Avalos ; 164*4b588458SPeter Avalos 165*4b588458SPeter Avalos pas: 166*4b588458SPeter Avalos opt_pst { $$ = 0; } 167*4b588458SPeter Avalos | opt_pst pa_stats opt_pst { $$ = $2; } 168*4b588458SPeter Avalos ; 169*4b588458SPeter Avalos 170*4b588458SPeter Avalos pa_pat: 171*4b588458SPeter Avalos pattern { $$ = notnull($1); } 172*4b588458SPeter Avalos ; 173*4b588458SPeter Avalos 174*4b588458SPeter Avalos pa_stat: 175*4b588458SPeter Avalos pa_pat { $$ = stat2(PASTAT, $1, stat2(PRINT, rectonode(), NIL)); } 176*4b588458SPeter Avalos | pa_pat lbrace stmtlist '}' { $$ = stat2(PASTAT, $1, $3); } 177*4b588458SPeter Avalos | pa_pat ',' pa_pat { $$ = pa2stat($1, $3, stat2(PRINT, rectonode(), NIL)); } 178*4b588458SPeter Avalos | pa_pat ',' pa_pat lbrace stmtlist '}' { $$ = pa2stat($1, $3, $5); } 179*4b588458SPeter Avalos | lbrace stmtlist '}' { $$ = stat2(PASTAT, NIL, $2); } 180*4b588458SPeter Avalos | XBEGIN lbrace stmtlist '}' 181*4b588458SPeter Avalos { beginloc = linkum(beginloc, $3); $$ = 0; } 182*4b588458SPeter Avalos | XEND lbrace stmtlist '}' 183*4b588458SPeter Avalos { endloc = linkum(endloc, $3); $$ = 0; } 184*4b588458SPeter Avalos | FUNC funcname '(' varlist rparen {infunc++;} lbrace stmtlist '}' 185*4b588458SPeter Avalos { infunc--; curfname=0; defn((Cell *)$2, $4, $8); $$ = 0; } 186*4b588458SPeter Avalos ; 187*4b588458SPeter Avalos 188*4b588458SPeter Avalos pa_stats: 189*4b588458SPeter Avalos pa_stat 190*4b588458SPeter Avalos | pa_stats opt_pst pa_stat { $$ = linkum($1, $3); } 191*4b588458SPeter Avalos ; 192*4b588458SPeter Avalos 193*4b588458SPeter Avalos patlist: 194*4b588458SPeter Avalos pattern 195*4b588458SPeter Avalos | patlist comma pattern { $$ = linkum($1, $3); } 196*4b588458SPeter Avalos ; 197*4b588458SPeter Avalos 198*4b588458SPeter Avalos ppattern: 199*4b588458SPeter Avalos var ASGNOP ppattern { $$ = op2($2, $1, $3); } 200*4b588458SPeter Avalos | ppattern '?' ppattern ':' ppattern %prec '?' 201*4b588458SPeter Avalos { $$ = op3(CONDEXPR, notnull($1), $3, $5); } 202*4b588458SPeter Avalos | ppattern bor ppattern %prec BOR 203*4b588458SPeter Avalos { $$ = op2(BOR, notnull($1), notnull($3)); } 204*4b588458SPeter Avalos | ppattern and ppattern %prec AND 205*4b588458SPeter Avalos { $$ = op2(AND, notnull($1), notnull($3)); } 206*4b588458SPeter Avalos | ppattern MATCHOP reg_expr { $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); } 207*4b588458SPeter Avalos | ppattern MATCHOP ppattern 208*4b588458SPeter Avalos { if (constnode($3)) 209*4b588458SPeter Avalos $$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0)); 210*4b588458SPeter Avalos else 211*4b588458SPeter Avalos $$ = op3($2, (Node *)1, $1, $3); } 212*4b588458SPeter Avalos | ppattern IN varname { $$ = op2(INTEST, $1, makearr($3)); } 213*4b588458SPeter Avalos | '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); } 214*4b588458SPeter Avalos | ppattern term %prec CAT { $$ = op2(CAT, $1, $2); } 215*4b588458SPeter Avalos | re 216*4b588458SPeter Avalos | term 217*4b588458SPeter Avalos ; 218*4b588458SPeter Avalos 219*4b588458SPeter Avalos pattern: 220*4b588458SPeter Avalos var ASGNOP pattern { $$ = op2($2, $1, $3); } 221*4b588458SPeter Avalos | pattern '?' pattern ':' pattern %prec '?' 222*4b588458SPeter Avalos { $$ = op3(CONDEXPR, notnull($1), $3, $5); } 223*4b588458SPeter Avalos | pattern bor pattern %prec BOR 224*4b588458SPeter Avalos { $$ = op2(BOR, notnull($1), notnull($3)); } 225*4b588458SPeter Avalos | pattern and pattern %prec AND 226*4b588458SPeter Avalos { $$ = op2(AND, notnull($1), notnull($3)); } 227*4b588458SPeter Avalos | pattern EQ pattern { $$ = op2($2, $1, $3); } 228*4b588458SPeter Avalos | pattern GE pattern { $$ = op2($2, $1, $3); } 229*4b588458SPeter Avalos | pattern GT pattern { $$ = op2($2, $1, $3); } 230*4b588458SPeter Avalos | pattern LE pattern { $$ = op2($2, $1, $3); } 231*4b588458SPeter Avalos | pattern LT pattern { $$ = op2($2, $1, $3); } 232*4b588458SPeter Avalos | pattern NE pattern { $$ = op2($2, $1, $3); } 233*4b588458SPeter Avalos | pattern MATCHOP reg_expr { $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); } 234*4b588458SPeter Avalos | pattern MATCHOP pattern 235*4b588458SPeter Avalos { if (constnode($3)) 236*4b588458SPeter Avalos $$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0)); 237*4b588458SPeter Avalos else 238*4b588458SPeter Avalos $$ = op3($2, (Node *)1, $1, $3); } 239*4b588458SPeter Avalos | pattern IN varname { $$ = op2(INTEST, $1, makearr($3)); } 240*4b588458SPeter Avalos | '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); } 241*4b588458SPeter Avalos | pattern '|' GETLINE var { 242*4b588458SPeter Avalos if (safe) SYNTAX("cmd | getline is unsafe"); 243*4b588458SPeter Avalos else $$ = op3(GETLINE, $4, itonp($2), $1); } 244*4b588458SPeter Avalos | pattern '|' GETLINE { 245*4b588458SPeter Avalos if (safe) SYNTAX("cmd | getline is unsafe"); 246*4b588458SPeter Avalos else $$ = op3(GETLINE, (Node*)0, itonp($2), $1); } 247*4b588458SPeter Avalos | pattern term %prec CAT { $$ = op2(CAT, $1, $2); } 248*4b588458SPeter Avalos | re 249*4b588458SPeter Avalos | term 250*4b588458SPeter Avalos ; 251*4b588458SPeter Avalos 252*4b588458SPeter Avalos plist: 253*4b588458SPeter Avalos pattern comma pattern { $$ = linkum($1, $3); } 254*4b588458SPeter Avalos | plist comma pattern { $$ = linkum($1, $3); } 255*4b588458SPeter Avalos ; 256*4b588458SPeter Avalos 257*4b588458SPeter Avalos pplist: 258*4b588458SPeter Avalos ppattern 259*4b588458SPeter Avalos | pplist comma ppattern { $$ = linkum($1, $3); } 260*4b588458SPeter Avalos ; 261*4b588458SPeter Avalos 262*4b588458SPeter Avalos prarg: 263*4b588458SPeter Avalos /* empty */ { $$ = rectonode(); } 264*4b588458SPeter Avalos | pplist 265*4b588458SPeter Avalos | '(' plist ')' { $$ = $2; } 266*4b588458SPeter Avalos ; 267*4b588458SPeter Avalos 268*4b588458SPeter Avalos print: 269*4b588458SPeter Avalos PRINT | PRINTF 270*4b588458SPeter Avalos ; 271*4b588458SPeter Avalos 272*4b588458SPeter Avalos pst: 273*4b588458SPeter Avalos NL | ';' | pst NL | pst ';' 274*4b588458SPeter Avalos ; 275*4b588458SPeter Avalos 276*4b588458SPeter Avalos rbrace: 277*4b588458SPeter Avalos '}' | rbrace NL 278*4b588458SPeter Avalos ; 279*4b588458SPeter Avalos 280*4b588458SPeter Avalos re: 281*4b588458SPeter Avalos reg_expr 282*4b588458SPeter Avalos { $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); } 283*4b588458SPeter Avalos | NOT re { $$ = op1(NOT, notnull($2)); } 284*4b588458SPeter Avalos ; 285*4b588458SPeter Avalos 286*4b588458SPeter Avalos reg_expr: 287*4b588458SPeter Avalos '/' {startreg();} REGEXPR '/' { $$ = $3; } 288*4b588458SPeter Avalos ; 289*4b588458SPeter Avalos 290*4b588458SPeter Avalos rparen: 291*4b588458SPeter Avalos ')' | rparen NL 292*4b588458SPeter Avalos ; 293*4b588458SPeter Avalos 294*4b588458SPeter Avalos simple_stmt: 295*4b588458SPeter Avalos print prarg '|' term { 296*4b588458SPeter Avalos if (safe) SYNTAX("print | is unsafe"); 297*4b588458SPeter Avalos else $$ = stat3($1, $2, itonp($3), $4); } 298*4b588458SPeter Avalos | print prarg APPEND term { 299*4b588458SPeter Avalos if (safe) SYNTAX("print >> is unsafe"); 300*4b588458SPeter Avalos else $$ = stat3($1, $2, itonp($3), $4); } 301*4b588458SPeter Avalos | print prarg GT term { 302*4b588458SPeter Avalos if (safe) SYNTAX("print > is unsafe"); 303*4b588458SPeter Avalos else $$ = stat3($1, $2, itonp($3), $4); } 304*4b588458SPeter Avalos | print prarg { $$ = stat3($1, $2, NIL, NIL); } 305*4b588458SPeter Avalos | DELETE varname '[' patlist ']' { $$ = stat2(DELETE, makearr($2), $4); } 306*4b588458SPeter Avalos | DELETE varname { $$ = stat2(DELETE, makearr($2), 0); } 307*4b588458SPeter Avalos | pattern { $$ = exptostat($1); } 308*4b588458SPeter Avalos | error { yyclearin; SYNTAX("illegal statement"); } 309*4b588458SPeter Avalos ; 310*4b588458SPeter Avalos 311*4b588458SPeter Avalos st: 312*4b588458SPeter Avalos nl 313*4b588458SPeter Avalos | ';' opt_nl 314*4b588458SPeter Avalos ; 315*4b588458SPeter Avalos 316*4b588458SPeter Avalos stmt: 317*4b588458SPeter Avalos BREAK st { if (!inloop) SYNTAX("break illegal outside of loops"); 318*4b588458SPeter Avalos $$ = stat1(BREAK, NIL); } 319*4b588458SPeter Avalos | CONTINUE st { if (!inloop) SYNTAX("continue illegal outside of loops"); 320*4b588458SPeter Avalos $$ = stat1(CONTINUE, NIL); } 321*4b588458SPeter Avalos | do {inloop++;} stmt {--inloop;} WHILE '(' pattern ')' st 322*4b588458SPeter Avalos { $$ = stat2(DO, $3, notnull($7)); } 323*4b588458SPeter Avalos | EXIT pattern st { $$ = stat1(EXIT, $2); } 324*4b588458SPeter Avalos | EXIT st { $$ = stat1(EXIT, NIL); } 325*4b588458SPeter Avalos | for 326*4b588458SPeter Avalos | if stmt else stmt { $$ = stat3(IF, $1, $2, $4); } 327*4b588458SPeter Avalos | if stmt { $$ = stat3(IF, $1, $2, NIL); } 328*4b588458SPeter Avalos | lbrace stmtlist rbrace { $$ = $2; } 329*4b588458SPeter Avalos | NEXT st { if (infunc) 330*4b588458SPeter Avalos SYNTAX("next is illegal inside a function"); 331*4b588458SPeter Avalos $$ = stat1(NEXT, NIL); } 332*4b588458SPeter Avalos | NEXTFILE st { if (infunc) 333*4b588458SPeter Avalos SYNTAX("nextfile is illegal inside a function"); 334*4b588458SPeter Avalos $$ = stat1(NEXTFILE, NIL); } 335*4b588458SPeter Avalos | RETURN pattern st { $$ = stat1(RETURN, $2); } 336*4b588458SPeter Avalos | RETURN st { $$ = stat1(RETURN, NIL); } 337*4b588458SPeter Avalos | simple_stmt st 338*4b588458SPeter Avalos | while {inloop++;} stmt { --inloop; $$ = stat2(WHILE, $1, $3); } 339*4b588458SPeter Avalos | ';' opt_nl { $$ = 0; } 340*4b588458SPeter Avalos ; 341*4b588458SPeter Avalos 342*4b588458SPeter Avalos stmtlist: 343*4b588458SPeter Avalos stmt 344*4b588458SPeter Avalos | stmtlist stmt { $$ = linkum($1, $2); } 345*4b588458SPeter Avalos ; 346*4b588458SPeter Avalos 347*4b588458SPeter Avalos subop: 348*4b588458SPeter Avalos SUB | GSUB 349*4b588458SPeter Avalos ; 350*4b588458SPeter Avalos 351*4b588458SPeter Avalos term: 352*4b588458SPeter Avalos term '/' ASGNOP term { $$ = op2(DIVEQ, $1, $4); } 353*4b588458SPeter Avalos | term '+' term { $$ = op2(ADD, $1, $3); } 354*4b588458SPeter Avalos | term '-' term { $$ = op2(MINUS, $1, $3); } 355*4b588458SPeter Avalos | term '*' term { $$ = op2(MULT, $1, $3); } 356*4b588458SPeter Avalos | term '/' term { $$ = op2(DIVIDE, $1, $3); } 357*4b588458SPeter Avalos | term '%' term { $$ = op2(MOD, $1, $3); } 358*4b588458SPeter Avalos | term POWER term { $$ = op2(POWER, $1, $3); } 359*4b588458SPeter Avalos | '-' term %prec UMINUS { $$ = op1(UMINUS, $2); } 360*4b588458SPeter Avalos | '+' term %prec UMINUS { $$ = $2; } 361*4b588458SPeter Avalos | NOT term %prec UMINUS { $$ = op1(NOT, notnull($2)); } 362*4b588458SPeter Avalos | BLTIN '(' ')' { $$ = op2(BLTIN, itonp($1), rectonode()); } 363*4b588458SPeter Avalos | BLTIN '(' patlist ')' { $$ = op2(BLTIN, itonp($1), $3); } 364*4b588458SPeter Avalos | BLTIN { $$ = op2(BLTIN, itonp($1), rectonode()); } 365*4b588458SPeter Avalos | CALL '(' ')' { $$ = op2(CALL, celltonode($1,CVAR), NIL); } 366*4b588458SPeter Avalos | CALL '(' patlist ')' { $$ = op2(CALL, celltonode($1,CVAR), $3); } 367*4b588458SPeter Avalos | CLOSE term { $$ = op1(CLOSE, $2); } 368*4b588458SPeter Avalos | DECR var { $$ = op1(PREDECR, $2); } 369*4b588458SPeter Avalos | INCR var { $$ = op1(PREINCR, $2); } 370*4b588458SPeter Avalos | var DECR { $$ = op1(POSTDECR, $1); } 371*4b588458SPeter Avalos | var INCR { $$ = op1(POSTINCR, $1); } 372*4b588458SPeter Avalos | GETLINE var LT term { $$ = op3(GETLINE, $2, itonp($3), $4); } 373*4b588458SPeter Avalos | GETLINE LT term { $$ = op3(GETLINE, NIL, itonp($2), $3); } 374*4b588458SPeter Avalos | GETLINE var { $$ = op3(GETLINE, $2, NIL, NIL); } 375*4b588458SPeter Avalos | GETLINE { $$ = op3(GETLINE, NIL, NIL, NIL); } 376*4b588458SPeter Avalos | INDEX '(' pattern comma pattern ')' 377*4b588458SPeter Avalos { $$ = op2(INDEX, $3, $5); } 378*4b588458SPeter Avalos | INDEX '(' pattern comma reg_expr ')' 379*4b588458SPeter Avalos { SYNTAX("index() doesn't permit regular expressions"); 380*4b588458SPeter Avalos $$ = op2(INDEX, $3, (Node*)$5); } 381*4b588458SPeter Avalos | '(' pattern ')' { $$ = $2; } 382*4b588458SPeter Avalos | MATCHFCN '(' pattern comma reg_expr ')' 383*4b588458SPeter Avalos { $$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa($5, 1)); } 384*4b588458SPeter Avalos | MATCHFCN '(' pattern comma pattern ')' 385*4b588458SPeter Avalos { if (constnode($5)) 386*4b588458SPeter Avalos $$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa(strnode($5), 1)); 387*4b588458SPeter Avalos else 388*4b588458SPeter Avalos $$ = op3(MATCHFCN, (Node *)1, $3, $5); } 389*4b588458SPeter Avalos | NUMBER { $$ = celltonode($1, CCON); } 390*4b588458SPeter Avalos | SPLIT '(' pattern comma varname comma pattern ')' /* string */ 391*4b588458SPeter Avalos { $$ = op4(SPLIT, $3, makearr($5), $7, (Node*)STRING); } 392*4b588458SPeter Avalos | SPLIT '(' pattern comma varname comma reg_expr ')' /* const /regexp/ */ 393*4b588458SPeter Avalos { $$ = op4(SPLIT, $3, makearr($5), (Node*)makedfa($7, 1), (Node *)REGEXPR); } 394*4b588458SPeter Avalos | SPLIT '(' pattern comma varname ')' 395*4b588458SPeter Avalos { $$ = op4(SPLIT, $3, makearr($5), NIL, (Node*)STRING); } /* default */ 396*4b588458SPeter Avalos | SPRINTF '(' patlist ')' { $$ = op1($1, $3); } 397*4b588458SPeter Avalos | STRING { $$ = celltonode($1, CCON); } 398*4b588458SPeter Avalos | subop '(' reg_expr comma pattern ')' 399*4b588458SPeter Avalos { $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, rectonode()); } 400*4b588458SPeter Avalos | subop '(' pattern comma pattern ')' 401*4b588458SPeter Avalos { if (constnode($3)) 402*4b588458SPeter Avalos $$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, rectonode()); 403*4b588458SPeter Avalos else 404*4b588458SPeter Avalos $$ = op4($1, (Node *)1, $3, $5, rectonode()); } 405*4b588458SPeter Avalos | subop '(' reg_expr comma pattern comma var ')' 406*4b588458SPeter Avalos { $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, $7); } 407*4b588458SPeter Avalos | subop '(' pattern comma pattern comma var ')' 408*4b588458SPeter Avalos { if (constnode($3)) 409*4b588458SPeter Avalos $$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, $7); 410*4b588458SPeter Avalos else 411*4b588458SPeter Avalos $$ = op4($1, (Node *)1, $3, $5, $7); } 412*4b588458SPeter Avalos | SUBSTR '(' pattern comma pattern comma pattern ')' 413*4b588458SPeter Avalos { $$ = op3(SUBSTR, $3, $5, $7); } 414*4b588458SPeter Avalos | SUBSTR '(' pattern comma pattern ')' 415*4b588458SPeter Avalos { $$ = op3(SUBSTR, $3, $5, NIL); } 416*4b588458SPeter Avalos | var 417*4b588458SPeter Avalos ; 418*4b588458SPeter Avalos 419*4b588458SPeter Avalos var: 420*4b588458SPeter Avalos varname 421*4b588458SPeter Avalos | varname '[' patlist ']' { $$ = op2(ARRAY, makearr($1), $3); } 422*4b588458SPeter Avalos | IVAR { $$ = op1(INDIRECT, celltonode($1, CVAR)); } 423*4b588458SPeter Avalos | INDIRECT term { $$ = op1(INDIRECT, $2); } 424*4b588458SPeter Avalos ; 425*4b588458SPeter Avalos 426*4b588458SPeter Avalos varlist: 427*4b588458SPeter Avalos /* nothing */ { arglist = $$ = 0; } 428*4b588458SPeter Avalos | VAR { arglist = $$ = celltonode($1,CVAR); } 429*4b588458SPeter Avalos | varlist comma VAR { 430*4b588458SPeter Avalos checkdup($1, $3); 431*4b588458SPeter Avalos arglist = $$ = linkum($1,celltonode($3,CVAR)); } 432*4b588458SPeter Avalos ; 433*4b588458SPeter Avalos 434*4b588458SPeter Avalos varname: 435*4b588458SPeter Avalos VAR { $$ = celltonode($1, CVAR); } 436*4b588458SPeter Avalos | ARG { $$ = op1(ARG, itonp($1)); } 437*4b588458SPeter Avalos | VARNF { $$ = op1(VARNF, (Node *) $1); } 438*4b588458SPeter Avalos ; 439*4b588458SPeter Avalos 440*4b588458SPeter Avalos 441*4b588458SPeter Avalos while: 442*4b588458SPeter Avalos WHILE '(' pattern rparen { $$ = notnull($3); } 443*4b588458SPeter Avalos ; 444*4b588458SPeter Avalos 445*4b588458SPeter Avalos %% 446*4b588458SPeter Avalos 447*4b588458SPeter Avalos void setfname(Cell *p) 448*4b588458SPeter Avalos { 449*4b588458SPeter Avalos if (isarr(p)) 450*4b588458SPeter Avalos SYNTAX("%s is an array, not a function", p->nval); 451*4b588458SPeter Avalos else if (isfcn(p)) 452*4b588458SPeter Avalos SYNTAX("you can't define function %s more than once", p->nval); 453*4b588458SPeter Avalos curfname = p->nval; 454*4b588458SPeter Avalos } 455*4b588458SPeter Avalos 456*4b588458SPeter Avalos int constnode(Node *p) 457*4b588458SPeter Avalos { 458*4b588458SPeter Avalos return isvalue(p) && ((Cell *) (p->narg[0]))->csub == CCON; 459*4b588458SPeter Avalos } 460*4b588458SPeter Avalos 461*4b588458SPeter Avalos char *strnode(Node *p) 462*4b588458SPeter Avalos { 463*4b588458SPeter Avalos return ((Cell *)(p->narg[0]))->sval; 464*4b588458SPeter Avalos } 465*4b588458SPeter Avalos 466*4b588458SPeter Avalos Node *notnull(Node *n) 467*4b588458SPeter Avalos { 468*4b588458SPeter Avalos switch (n->nobj) { 469*4b588458SPeter Avalos case LE: case LT: case EQ: case NE: case GT: case GE: 470*4b588458SPeter Avalos case BOR: case AND: case NOT: 471*4b588458SPeter Avalos return n; 472*4b588458SPeter Avalos default: 473*4b588458SPeter Avalos return op2(NE, n, nullnode); 474*4b588458SPeter Avalos } 475*4b588458SPeter Avalos } 476*4b588458SPeter Avalos 477*4b588458SPeter Avalos void checkdup(Node *vl, Cell *cp) /* check if name already in list */ 478*4b588458SPeter Avalos { 479*4b588458SPeter Avalos char *s = cp->nval; 480*4b588458SPeter Avalos for ( ; vl; vl = vl->nnext) { 481*4b588458SPeter Avalos if (strcmp(s, ((Cell *)(vl->narg[0]))->nval) == 0) { 482*4b588458SPeter Avalos SYNTAX("duplicate argument %s", s); 483*4b588458SPeter Avalos break; 484*4b588458SPeter Avalos } 485*4b588458SPeter Avalos } 486*4b588458SPeter Avalos } 487