17c478bd9Sstevel@tonic-gate %{
27c478bd9Sstevel@tonic-gate /*
37c478bd9Sstevel@tonic-gate * CDDL HEADER START
47c478bd9Sstevel@tonic-gate *
57c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
67c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
77c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
87c478bd9Sstevel@tonic-gate * with the License.
97c478bd9Sstevel@tonic-gate *
107c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
117c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
127c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
137c478bd9Sstevel@tonic-gate * and limitations under the License.
147c478bd9Sstevel@tonic-gate *
157c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
167c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
177c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
187c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
197c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
207c478bd9Sstevel@tonic-gate *
217c478bd9Sstevel@tonic-gate * CDDL HEADER END
227c478bd9Sstevel@tonic-gate */
237c478bd9Sstevel@tonic-gate %}
24*1ee2e5faSnakanon /*
25*1ee2e5faSnakanon * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
26*1ee2e5faSnakanon * Use is subject to license terms.
27*1ee2e5faSnakanon */
28*1ee2e5faSnakanon
297c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
307c478bd9Sstevel@tonic-gate /* All Rights Reserved */
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate %{
337c478bd9Sstevel@tonic-gate #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 2.10 */
347c478bd9Sstevel@tonic-gate %}
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate %{
377c478bd9Sstevel@tonic-gate #include "awk.h"
yywrap(void)38*1ee2e5faSnakanon int yywrap(void) { return(1); }
397c478bd9Sstevel@tonic-gate #ifndef DEBUG
407c478bd9Sstevel@tonic-gate # define PUTS(x)
417c478bd9Sstevel@tonic-gate #endif
427c478bd9Sstevel@tonic-gate Node *beginloc = 0, *endloc = 0;
437c478bd9Sstevel@tonic-gate int infunc = 0; /* = 1 if in arglist or body of func */
447c478bd9Sstevel@tonic-gate uchar *curfname = 0;
457c478bd9Sstevel@tonic-gate Node *arglist = 0; /* list of args for current function */
46*1ee2e5faSnakanon static void setfname(Cell *);
47*1ee2e5faSnakanon static int constnode(Node *);
48*1ee2e5faSnakanon static uchar *strnode(Node *);
49*1ee2e5faSnakanon static Node *notnull();
507c478bd9Sstevel@tonic-gate %}
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate %union {
537c478bd9Sstevel@tonic-gate Node *p;
547c478bd9Sstevel@tonic-gate Cell *cp;
557c478bd9Sstevel@tonic-gate int i;
567c478bd9Sstevel@tonic-gate uchar *s;
577c478bd9Sstevel@tonic-gate }
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate %token <i> FIRSTTOKEN /* must be first */
607c478bd9Sstevel@tonic-gate %token <p> PROGRAM PASTAT PASTAT2 XBEGIN XEND
617c478bd9Sstevel@tonic-gate %token <i> NL ',' '{' '(' '|' ';' '/' ')' '}' '[' ']'
627c478bd9Sstevel@tonic-gate %token <i> ARRAY
637c478bd9Sstevel@tonic-gate %token <i> MATCH NOTMATCH MATCHOP
647c478bd9Sstevel@tonic-gate %token <i> FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS
657c478bd9Sstevel@tonic-gate %token <i> AND BOR APPEND EQ GE GT LE LT NE IN
667c478bd9Sstevel@tonic-gate %token <i> ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC
677c478bd9Sstevel@tonic-gate %token <i> SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT
687c478bd9Sstevel@tonic-gate %token <i> ADD MINUS MULT DIVIDE MOD
697c478bd9Sstevel@tonic-gate %token <i> ASSIGN ASGNOP ADDEQ SUBEQ MULTEQ DIVEQ MODEQ POWEQ
707c478bd9Sstevel@tonic-gate %token <i> PRINT PRINTF SPRINTF
717c478bd9Sstevel@tonic-gate %token <p> ELSE INTEST CONDEXPR
727c478bd9Sstevel@tonic-gate %token <i> POSTINCR PREINCR POSTDECR PREDECR
737c478bd9Sstevel@tonic-gate %token <cp> VAR IVAR VARNF CALL NUMBER STRING FIELD
747c478bd9Sstevel@tonic-gate %token <s> REGEXPR
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate %type <p> pas pattern ppattern plist pplist patlist prarg term
777c478bd9Sstevel@tonic-gate %type <p> pa_pat pa_stat pa_stats
787c478bd9Sstevel@tonic-gate %type <s> reg_expr
797c478bd9Sstevel@tonic-gate %type <p> simple_stmt opt_simple_stmt stmt stmtlist
807c478bd9Sstevel@tonic-gate %type <p> var varname funcname varlist
817c478bd9Sstevel@tonic-gate %type <p> for if while
827c478bd9Sstevel@tonic-gate %type <i> pst opt_pst lbrace rparen comma nl opt_nl and bor
837c478bd9Sstevel@tonic-gate %type <i> subop print
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate %right ASGNOP
867c478bd9Sstevel@tonic-gate %right '?'
877c478bd9Sstevel@tonic-gate %right ':'
887c478bd9Sstevel@tonic-gate %left BOR
897c478bd9Sstevel@tonic-gate %left AND
907c478bd9Sstevel@tonic-gate %left GETLINE
917c478bd9Sstevel@tonic-gate %nonassoc APPEND EQ GE GT LE LT NE MATCHOP IN '|'
927c478bd9Sstevel@tonic-gate %left ARG BLTIN BREAK CALL CLOSE CONTINUE DELETE DO EXIT FOR FIELD FUNC
937c478bd9Sstevel@tonic-gate %left GSUB IF INDEX LSUBSTR MATCHFCN NEXT NUMBER
947c478bd9Sstevel@tonic-gate %left PRINT PRINTF RETURN SPLIT SPRINTF STRING SUB SUBSTR
957c478bd9Sstevel@tonic-gate %left REGEXPR VAR VARNF IVAR WHILE '('
967c478bd9Sstevel@tonic-gate %left CAT
977c478bd9Sstevel@tonic-gate %left '+' '-'
987c478bd9Sstevel@tonic-gate %left '*' '/' '%'
997c478bd9Sstevel@tonic-gate %left NOT UMINUS
1007c478bd9Sstevel@tonic-gate %right POWER
1017c478bd9Sstevel@tonic-gate %right DECR INCR
1027c478bd9Sstevel@tonic-gate %left INDIRECT
1037c478bd9Sstevel@tonic-gate %token LASTTOKEN /* must be last */
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate %%
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate program:
1087c478bd9Sstevel@tonic-gate pas { if (errorflag==0)
1097c478bd9Sstevel@tonic-gate winner = (Node *)stat3(PROGRAM, beginloc, $1, endloc); }
1107c478bd9Sstevel@tonic-gate | error { yyclearin; bracecheck(); ERROR "bailing out" SYNTAX; }
1117c478bd9Sstevel@tonic-gate ;
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate and:
1147c478bd9Sstevel@tonic-gate AND | and NL
1157c478bd9Sstevel@tonic-gate ;
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate bor:
1187c478bd9Sstevel@tonic-gate BOR | bor NL
1197c478bd9Sstevel@tonic-gate ;
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate comma:
1227c478bd9Sstevel@tonic-gate ',' | comma NL
1237c478bd9Sstevel@tonic-gate ;
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate do:
1267c478bd9Sstevel@tonic-gate DO | do NL
1277c478bd9Sstevel@tonic-gate ;
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate else:
1307c478bd9Sstevel@tonic-gate ELSE | else NL
1317c478bd9Sstevel@tonic-gate ;
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate for:
1347c478bd9Sstevel@tonic-gate FOR '(' opt_simple_stmt ';' pattern ';' opt_simple_stmt rparen stmt
1357c478bd9Sstevel@tonic-gate { $$ = stat4(FOR, $3, notnull($5), $7, $9); }
1367c478bd9Sstevel@tonic-gate | FOR '(' opt_simple_stmt ';' ';' opt_simple_stmt rparen stmt
1377c478bd9Sstevel@tonic-gate { $$ = stat4(FOR, $3, NIL, $6, $8); }
1387c478bd9Sstevel@tonic-gate | FOR '(' varname IN varname rparen stmt
1397c478bd9Sstevel@tonic-gate { $$ = stat3(IN, $3, makearr($5), $7); }
1407c478bd9Sstevel@tonic-gate ;
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate funcname:
1437c478bd9Sstevel@tonic-gate VAR { setfname($1); }
1447c478bd9Sstevel@tonic-gate | CALL { setfname($1); }
1457c478bd9Sstevel@tonic-gate ;
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate if:
1487c478bd9Sstevel@tonic-gate IF '(' pattern rparen { $$ = notnull($3); }
1497c478bd9Sstevel@tonic-gate ;
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate lbrace:
1527c478bd9Sstevel@tonic-gate '{' | lbrace NL
1537c478bd9Sstevel@tonic-gate ;
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate nl:
1567c478bd9Sstevel@tonic-gate NL | nl NL
1577c478bd9Sstevel@tonic-gate ;
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate opt_nl:
1607c478bd9Sstevel@tonic-gate /* empty */ { $$ = 0; }
1617c478bd9Sstevel@tonic-gate | nl
1627c478bd9Sstevel@tonic-gate ;
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate opt_pst:
1657c478bd9Sstevel@tonic-gate /* empty */ { $$ = 0; }
1667c478bd9Sstevel@tonic-gate | pst
1677c478bd9Sstevel@tonic-gate ;
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate opt_simple_stmt:
1717c478bd9Sstevel@tonic-gate /* empty */ { $$ = 0; }
1727c478bd9Sstevel@tonic-gate | simple_stmt
1737c478bd9Sstevel@tonic-gate ;
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate pas:
1767c478bd9Sstevel@tonic-gate opt_pst { $$ = 0; }
1777c478bd9Sstevel@tonic-gate | opt_pst pa_stats opt_pst { $$ = $2; }
1787c478bd9Sstevel@tonic-gate ;
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate pa_pat:
1817c478bd9Sstevel@tonic-gate pattern { $$ = notnull($1); }
1827c478bd9Sstevel@tonic-gate ;
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate pa_stat:
1857c478bd9Sstevel@tonic-gate pa_pat { $$ = stat2(PASTAT, $1, stat2(PRINT, rectonode(), NIL)); }
1867c478bd9Sstevel@tonic-gate | pa_pat lbrace stmtlist '}' { $$ = stat2(PASTAT, $1, $3); }
1877c478bd9Sstevel@tonic-gate | pa_pat ',' pa_pat { $$ = pa2stat($1, $3, stat2(PRINT, rectonode(), NIL)); }
1887c478bd9Sstevel@tonic-gate | pa_pat ',' pa_pat lbrace stmtlist '}' { $$ = pa2stat($1, $3, $5); }
1897c478bd9Sstevel@tonic-gate | lbrace stmtlist '}' { $$ = stat2(PASTAT, NIL, $2); }
1907c478bd9Sstevel@tonic-gate | XBEGIN lbrace stmtlist '}'
1917c478bd9Sstevel@tonic-gate { beginloc = linkum(beginloc, $3); $$ = 0; }
1927c478bd9Sstevel@tonic-gate | XEND lbrace stmtlist '}'
1937c478bd9Sstevel@tonic-gate { endloc = linkum(endloc, $3); $$ = 0; }
1947c478bd9Sstevel@tonic-gate | FUNC funcname '(' varlist rparen {infunc++;} lbrace stmtlist '}'
1957c478bd9Sstevel@tonic-gate { infunc--; curfname=0; defn((Cell *)$2, $4, $8); $$ = 0; }
1967c478bd9Sstevel@tonic-gate ;
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate pa_stats:
1997c478bd9Sstevel@tonic-gate pa_stat
2007c478bd9Sstevel@tonic-gate | pa_stats opt_pst pa_stat { $$ = linkum($1, $3); }
2017c478bd9Sstevel@tonic-gate ;
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate patlist:
2047c478bd9Sstevel@tonic-gate pattern
2057c478bd9Sstevel@tonic-gate | patlist comma pattern { $$ = linkum($1, $3); }
2067c478bd9Sstevel@tonic-gate ;
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate ppattern:
2097c478bd9Sstevel@tonic-gate var ASGNOP ppattern { $$ = op2($2, $1, $3); }
2107c478bd9Sstevel@tonic-gate | ppattern '?' ppattern ':' ppattern %prec '?'
2117c478bd9Sstevel@tonic-gate { $$ = op3(CONDEXPR, notnull($1), $3, $5); }
2127c478bd9Sstevel@tonic-gate | ppattern bor ppattern %prec BOR
2137c478bd9Sstevel@tonic-gate { $$ = op2(BOR, notnull($1), notnull($3)); }
2147c478bd9Sstevel@tonic-gate | ppattern and ppattern %prec AND
2157c478bd9Sstevel@tonic-gate { $$ = op2(AND, notnull($1), notnull($3)); }
2167c478bd9Sstevel@tonic-gate | NOT ppattern
2177c478bd9Sstevel@tonic-gate { $$ = op1(NOT, notnull($2)); }
2187c478bd9Sstevel@tonic-gate | ppattern MATCHOP reg_expr { $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); }
2197c478bd9Sstevel@tonic-gate | ppattern MATCHOP ppattern
2207c478bd9Sstevel@tonic-gate { if (constnode($3))
2217c478bd9Sstevel@tonic-gate $$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0));
2227c478bd9Sstevel@tonic-gate else
2237c478bd9Sstevel@tonic-gate $$ = op3($2, (Node *)1, $1, $3); }
2247c478bd9Sstevel@tonic-gate | ppattern IN varname { $$ = op2(INTEST, $1, makearr($3)); }
2257c478bd9Sstevel@tonic-gate | '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); }
2267c478bd9Sstevel@tonic-gate | ppattern term %prec CAT { $$ = op2(CAT, $1, $2); }
2277c478bd9Sstevel@tonic-gate | reg_expr
2287c478bd9Sstevel@tonic-gate { $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); }
2297c478bd9Sstevel@tonic-gate | term
2307c478bd9Sstevel@tonic-gate ;
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate pattern:
2337c478bd9Sstevel@tonic-gate var ASGNOP pattern { $$ = op2($2, $1, $3); }
2347c478bd9Sstevel@tonic-gate | pattern '?' pattern ':' pattern %prec '?'
2357c478bd9Sstevel@tonic-gate { $$ = op3(CONDEXPR, notnull($1), $3, $5); }
2367c478bd9Sstevel@tonic-gate | pattern bor pattern %prec BOR
2377c478bd9Sstevel@tonic-gate { $$ = op2(BOR, notnull($1), notnull($3)); }
2387c478bd9Sstevel@tonic-gate | pattern and pattern %prec AND
2397c478bd9Sstevel@tonic-gate { $$ = op2(AND, notnull($1), notnull($3)); }
2407c478bd9Sstevel@tonic-gate | NOT pattern
241*1ee2e5faSnakanon { $$ = op1(NOT, op2(NE,$2,valtonode(lookup((uchar *)"$zero&null",symtab),CCON))); }
2427c478bd9Sstevel@tonic-gate | pattern EQ pattern { $$ = op2($2, $1, $3); }
2437c478bd9Sstevel@tonic-gate | pattern GE pattern { $$ = op2($2, $1, $3); }
2447c478bd9Sstevel@tonic-gate | pattern GT pattern { $$ = op2($2, $1, $3); }
2457c478bd9Sstevel@tonic-gate | pattern LE pattern { $$ = op2($2, $1, $3); }
2467c478bd9Sstevel@tonic-gate | pattern LT pattern { $$ = op2($2, $1, $3); }
2477c478bd9Sstevel@tonic-gate | pattern NE pattern { $$ = op2($2, $1, $3); }
2487c478bd9Sstevel@tonic-gate | pattern MATCHOP reg_expr { $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); }
2497c478bd9Sstevel@tonic-gate | pattern MATCHOP pattern
2507c478bd9Sstevel@tonic-gate { if (constnode($3))
2517c478bd9Sstevel@tonic-gate $$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0));
2527c478bd9Sstevel@tonic-gate else
2537c478bd9Sstevel@tonic-gate $$ = op3($2, (Node *)1, $1, $3); }
2547c478bd9Sstevel@tonic-gate | pattern IN varname { $$ = op2(INTEST, $1, makearr($3)); }
2557c478bd9Sstevel@tonic-gate | '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); }
2567c478bd9Sstevel@tonic-gate | pattern '|' GETLINE var { $$ = op3(GETLINE, $4, (Node*)$2, $1); }
2577c478bd9Sstevel@tonic-gate | pattern '|' GETLINE { $$ = op3(GETLINE, (Node*)0, (Node*)$2, $1); }
2587c478bd9Sstevel@tonic-gate | pattern term %prec CAT { $$ = op2(CAT, $1, $2); }
2597c478bd9Sstevel@tonic-gate | reg_expr
2607c478bd9Sstevel@tonic-gate { $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); }
2617c478bd9Sstevel@tonic-gate | term
2627c478bd9Sstevel@tonic-gate ;
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate plist:
2657c478bd9Sstevel@tonic-gate pattern comma pattern { $$ = linkum($1, $3); }
2667c478bd9Sstevel@tonic-gate | plist comma pattern { $$ = linkum($1, $3); }
2677c478bd9Sstevel@tonic-gate ;
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate pplist:
2707c478bd9Sstevel@tonic-gate ppattern
2717c478bd9Sstevel@tonic-gate | pplist comma ppattern { $$ = linkum($1, $3); }
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate prarg:
2747c478bd9Sstevel@tonic-gate /* empty */ { $$ = rectonode(); }
2757c478bd9Sstevel@tonic-gate | pplist
2767c478bd9Sstevel@tonic-gate | '(' plist ')' { $$ = $2; }
2777c478bd9Sstevel@tonic-gate ;
2787c478bd9Sstevel@tonic-gate
2797c478bd9Sstevel@tonic-gate print:
2807c478bd9Sstevel@tonic-gate PRINT | PRINTF
2817c478bd9Sstevel@tonic-gate ;
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate pst:
2847c478bd9Sstevel@tonic-gate NL | ';' | pst NL | pst ';'
2857c478bd9Sstevel@tonic-gate ;
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate rbrace:
2887c478bd9Sstevel@tonic-gate '}' | rbrace NL
2897c478bd9Sstevel@tonic-gate ;
2907c478bd9Sstevel@tonic-gate
2917c478bd9Sstevel@tonic-gate reg_expr:
2927c478bd9Sstevel@tonic-gate '/' {startreg();} REGEXPR '/' { $$ = $3; }
2937c478bd9Sstevel@tonic-gate ;
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate rparen:
2967c478bd9Sstevel@tonic-gate ')' | rparen NL
2977c478bd9Sstevel@tonic-gate ;
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate simple_stmt:
3007c478bd9Sstevel@tonic-gate print prarg '|' term { $$ = stat3($1, $2, (Node *) $3, $4); }
3017c478bd9Sstevel@tonic-gate | print prarg APPEND term { $$ = stat3($1, $2, (Node *) $3, $4); }
3027c478bd9Sstevel@tonic-gate | print prarg GT term { $$ = stat3($1, $2, (Node *) $3, $4); }
3037c478bd9Sstevel@tonic-gate | print prarg { $$ = stat3($1, $2, NIL, NIL); }
3047c478bd9Sstevel@tonic-gate | DELETE varname '[' patlist ']' { $$ = stat2(DELETE, makearr($2), $4); }
3057c478bd9Sstevel@tonic-gate | DELETE varname { yyclearin; ERROR "you can only delete array[element]" SYNTAX; $$ = stat1(DELETE, $2); }
3067c478bd9Sstevel@tonic-gate | pattern { $$ = exptostat($1); }
3077c478bd9Sstevel@tonic-gate | error { yyclearin; ERROR "illegal statement" SYNTAX; }
3087c478bd9Sstevel@tonic-gate ;
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate st:
3117c478bd9Sstevel@tonic-gate nl | ';' opt_nl
3127c478bd9Sstevel@tonic-gate ;
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate stmt:
3157c478bd9Sstevel@tonic-gate BREAK st { $$ = stat1(BREAK, NIL); }
3167c478bd9Sstevel@tonic-gate | CLOSE pattern st { $$ = stat1(CLOSE, $2); }
3177c478bd9Sstevel@tonic-gate | CONTINUE st { $$ = stat1(CONTINUE, NIL); }
3187c478bd9Sstevel@tonic-gate | do stmt WHILE '(' pattern ')' st
3197c478bd9Sstevel@tonic-gate { $$ = stat2(DO, $2, notnull($5)); }
3207c478bd9Sstevel@tonic-gate | EXIT pattern st { $$ = stat1(EXIT, $2); }
3217c478bd9Sstevel@tonic-gate | EXIT st { $$ = stat1(EXIT, NIL); }
3227c478bd9Sstevel@tonic-gate | for
3237c478bd9Sstevel@tonic-gate | if stmt else stmt { $$ = stat3(IF, $1, $2, $4); }
3247c478bd9Sstevel@tonic-gate | if stmt { $$ = stat3(IF, $1, $2, NIL); }
3257c478bd9Sstevel@tonic-gate | lbrace stmtlist rbrace { $$ = $2; }
3267c478bd9Sstevel@tonic-gate | NEXT st { if (infunc)
3277c478bd9Sstevel@tonic-gate ERROR "next is illegal inside a function" SYNTAX;
3287c478bd9Sstevel@tonic-gate $$ = stat1(NEXT, NIL); }
3297c478bd9Sstevel@tonic-gate | RETURN pattern st { $$ = stat1(RETURN, $2); }
3307c478bd9Sstevel@tonic-gate | RETURN st { $$ = stat1(RETURN, NIL); }
3317c478bd9Sstevel@tonic-gate | simple_stmt st
3327c478bd9Sstevel@tonic-gate | while stmt { $$ = stat2(WHILE, $1, $2); }
3337c478bd9Sstevel@tonic-gate | ';' opt_nl { $$ = 0; }
3347c478bd9Sstevel@tonic-gate ;
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate stmtlist:
3377c478bd9Sstevel@tonic-gate stmt
3387c478bd9Sstevel@tonic-gate | stmtlist stmt { $$ = linkum($1, $2); }
3397c478bd9Sstevel@tonic-gate ;
3407c478bd9Sstevel@tonic-gate
3417c478bd9Sstevel@tonic-gate subop:
3427c478bd9Sstevel@tonic-gate SUB | GSUB
3437c478bd9Sstevel@tonic-gate ;
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate term:
3467c478bd9Sstevel@tonic-gate term '+' term { $$ = op2(ADD, $1, $3); }
3477c478bd9Sstevel@tonic-gate | term '-' term { $$ = op2(MINUS, $1, $3); }
3487c478bd9Sstevel@tonic-gate | term '*' term { $$ = op2(MULT, $1, $3); }
3497c478bd9Sstevel@tonic-gate | term '/' term { $$ = op2(DIVIDE, $1, $3); }
3507c478bd9Sstevel@tonic-gate | term '%' term { $$ = op2(MOD, $1, $3); }
3517c478bd9Sstevel@tonic-gate | term POWER term { $$ = op2(POWER, $1, $3); }
3527c478bd9Sstevel@tonic-gate | '-' term %prec UMINUS { $$ = op1(UMINUS, $2); }
3537c478bd9Sstevel@tonic-gate | '+' term %prec UMINUS { $$ = $2; }
3547c478bd9Sstevel@tonic-gate | BLTIN '(' ')' { $$ = op2(BLTIN, (Node *) $1, rectonode()); }
3557c478bd9Sstevel@tonic-gate | BLTIN '(' patlist ')' { $$ = op2(BLTIN, (Node *) $1, $3); }
3567c478bd9Sstevel@tonic-gate | BLTIN { $$ = op2(BLTIN, (Node *) $1, rectonode()); }
3577c478bd9Sstevel@tonic-gate | CALL '(' ')' { $$ = op2(CALL, valtonode($1,CVAR), NIL); }
3587c478bd9Sstevel@tonic-gate | CALL '(' patlist ')' { $$ = op2(CALL, valtonode($1,CVAR), $3); }
3597c478bd9Sstevel@tonic-gate | DECR var { $$ = op1(PREDECR, $2); }
3607c478bd9Sstevel@tonic-gate | INCR var { $$ = op1(PREINCR, $2); }
3617c478bd9Sstevel@tonic-gate | var DECR { $$ = op1(POSTDECR, $1); }
3627c478bd9Sstevel@tonic-gate | var INCR { $$ = op1(POSTINCR, $1); }
3637c478bd9Sstevel@tonic-gate | GETLINE var LT term { $$ = op3(GETLINE, $2, (Node *)$3, $4); }
3647c478bd9Sstevel@tonic-gate | GETLINE LT term { $$ = op3(GETLINE, NIL, (Node *)$2, $3); }
3657c478bd9Sstevel@tonic-gate | GETLINE var { $$ = op3(GETLINE, $2, NIL, NIL); }
3667c478bd9Sstevel@tonic-gate | GETLINE { $$ = op3(GETLINE, NIL, NIL, NIL); }
3677c478bd9Sstevel@tonic-gate | INDEX '(' pattern comma pattern ')'
3687c478bd9Sstevel@tonic-gate { $$ = op2(INDEX, $3, $5); }
3697c478bd9Sstevel@tonic-gate | INDEX '(' pattern comma reg_expr ')'
3707c478bd9Sstevel@tonic-gate { ERROR "index() doesn't permit regular expressions" SYNTAX;
3717c478bd9Sstevel@tonic-gate $$ = op2(INDEX, $3, (Node*)$5); }
3727c478bd9Sstevel@tonic-gate | '(' pattern ')' { $$ = $2; }
3737c478bd9Sstevel@tonic-gate | MATCHFCN '(' pattern comma reg_expr ')'
3747c478bd9Sstevel@tonic-gate { $$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa($5, 1)); }
3757c478bd9Sstevel@tonic-gate | MATCHFCN '(' pattern comma pattern ')'
3767c478bd9Sstevel@tonic-gate { if (constnode($5))
3777c478bd9Sstevel@tonic-gate $$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa(strnode($5), 1));
3787c478bd9Sstevel@tonic-gate else
3797c478bd9Sstevel@tonic-gate $$ = op3(MATCHFCN, (Node *)1, $3, $5); }
3807c478bd9Sstevel@tonic-gate | NUMBER { $$ = valtonode($1, CCON); }
3817c478bd9Sstevel@tonic-gate | SPLIT '(' pattern comma varname comma pattern ')' /* string */
3827c478bd9Sstevel@tonic-gate { $$ = op4(SPLIT, $3, makearr($5), $7, (Node*)STRING); }
3837c478bd9Sstevel@tonic-gate | SPLIT '(' pattern comma varname comma reg_expr ')' /* const /regexp/ */
3847c478bd9Sstevel@tonic-gate { $$ = op4(SPLIT, $3, makearr($5), (Node*)makedfa($7, 1), (Node *)REGEXPR); }
3857c478bd9Sstevel@tonic-gate | SPLIT '(' pattern comma varname ')'
3867c478bd9Sstevel@tonic-gate { $$ = op4(SPLIT, $3, makearr($5), NIL, (Node*)STRING); } /* default */
3877c478bd9Sstevel@tonic-gate | SPRINTF '(' patlist ')' { $$ = op1($1, $3); }
3887c478bd9Sstevel@tonic-gate | STRING { $$ = valtonode($1, CCON); }
3897c478bd9Sstevel@tonic-gate | subop '(' reg_expr comma pattern ')'
3907c478bd9Sstevel@tonic-gate { $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, rectonode()); }
3917c478bd9Sstevel@tonic-gate | subop '(' pattern comma pattern ')'
3927c478bd9Sstevel@tonic-gate { if (constnode($3))
3937c478bd9Sstevel@tonic-gate $$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, rectonode());
3947c478bd9Sstevel@tonic-gate else
3957c478bd9Sstevel@tonic-gate $$ = op4($1, (Node *)1, $3, $5, rectonode()); }
3967c478bd9Sstevel@tonic-gate | subop '(' reg_expr comma pattern comma var ')'
3977c478bd9Sstevel@tonic-gate { $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, $7); }
3987c478bd9Sstevel@tonic-gate | subop '(' pattern comma pattern comma var ')'
3997c478bd9Sstevel@tonic-gate { if (constnode($3))
4007c478bd9Sstevel@tonic-gate $$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, $7);
4017c478bd9Sstevel@tonic-gate else
4027c478bd9Sstevel@tonic-gate $$ = op4($1, (Node *)1, $3, $5, $7); }
4037c478bd9Sstevel@tonic-gate | SUBSTR '(' pattern comma pattern comma pattern ')'
4047c478bd9Sstevel@tonic-gate { $$ = op3(SUBSTR, $3, $5, $7); }
4057c478bd9Sstevel@tonic-gate | SUBSTR '(' pattern comma pattern ')'
4067c478bd9Sstevel@tonic-gate { $$ = op3(SUBSTR, $3, $5, NIL); }
4077c478bd9Sstevel@tonic-gate | var
4087c478bd9Sstevel@tonic-gate ;
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate var:
4117c478bd9Sstevel@tonic-gate varname
4127c478bd9Sstevel@tonic-gate | varname '[' patlist ']' { $$ = op2(ARRAY, makearr($1), $3); }
4137c478bd9Sstevel@tonic-gate | FIELD { $$ = valtonode($1, CFLD); }
4147c478bd9Sstevel@tonic-gate | IVAR { $$ = op1(INDIRECT, valtonode($1, CVAR)); }
4157c478bd9Sstevel@tonic-gate | INDIRECT term { $$ = op1(INDIRECT, $2); }
4167c478bd9Sstevel@tonic-gate ;
4177c478bd9Sstevel@tonic-gate
4187c478bd9Sstevel@tonic-gate varlist:
4197c478bd9Sstevel@tonic-gate /* nothing */ { arglist = $$ = 0; }
4207c478bd9Sstevel@tonic-gate | VAR { arglist = $$ = valtonode($1,CVAR); }
4217c478bd9Sstevel@tonic-gate | varlist comma VAR { arglist = $$ = linkum($1,valtonode($3,CVAR)); }
4227c478bd9Sstevel@tonic-gate ;
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate varname:
4257c478bd9Sstevel@tonic-gate VAR { $$ = valtonode($1, CVAR); }
4267c478bd9Sstevel@tonic-gate | ARG { $$ = op1(ARG, (Node *) $1); }
4277c478bd9Sstevel@tonic-gate | VARNF { $$ = op1(VARNF, (Node *) $1); }
4287c478bd9Sstevel@tonic-gate ;
4297c478bd9Sstevel@tonic-gate
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate while:
4327c478bd9Sstevel@tonic-gate WHILE '(' pattern rparen { $$ = notnull($3); }
4337c478bd9Sstevel@tonic-gate ;
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate %%
4367c478bd9Sstevel@tonic-gate
437*1ee2e5faSnakanon static void
438*1ee2e5faSnakanon setfname(Cell *p)
4397c478bd9Sstevel@tonic-gate {
4407c478bd9Sstevel@tonic-gate if (isarr(p))
4417c478bd9Sstevel@tonic-gate ERROR "%s is an array, not a function", p->nval SYNTAX;
4427c478bd9Sstevel@tonic-gate else if (isfunc(p))
4437c478bd9Sstevel@tonic-gate ERROR "you can't define function %s more than once", p->nval SYNTAX;
4447c478bd9Sstevel@tonic-gate curfname = p->nval;
4457c478bd9Sstevel@tonic-gate }
4467c478bd9Sstevel@tonic-gate
447*1ee2e5faSnakanon
448*1ee2e5faSnakanon static int
449*1ee2e5faSnakanon constnode(Node *p)
4507c478bd9Sstevel@tonic-gate {
4517c478bd9Sstevel@tonic-gate return p->ntype == NVALUE && ((Cell *) (p->narg[0]))->csub == CCON;
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate
454*1ee2e5faSnakanon static uchar *
455*1ee2e5faSnakanon strnode(Node *p)
4567c478bd9Sstevel@tonic-gate {
4577c478bd9Sstevel@tonic-gate return ((Cell *)(p->narg[0]))->sval;
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate
460*1ee2e5faSnakanon static Node *
461*1ee2e5faSnakanon notnull(Node *n)
4627c478bd9Sstevel@tonic-gate {
4637c478bd9Sstevel@tonic-gate switch (n->nobj) {
4647c478bd9Sstevel@tonic-gate case LE: case LT: case EQ: case NE: case GT: case GE:
4657c478bd9Sstevel@tonic-gate case BOR: case AND: case NOT:
4667c478bd9Sstevel@tonic-gate return n;
4677c478bd9Sstevel@tonic-gate default:
4687c478bd9Sstevel@tonic-gate return op2(NE, n, nullnode);
4697c478bd9Sstevel@tonic-gate }
4707c478bd9Sstevel@tonic-gate }
471