|
|
1.1 root 1: %{
2: #include "awk.h"
3: yywrap() { return(1); }
4: #ifndef DEBUG
5: # define PUTS(x)
6: #endif
7: Node *beginloc = 0, *endloc = 0;
8: int infunc = 0; /* = 1 if in arglist or body of func */
9: uchar *curfname = 0;
10: Node *arglist = 0; /* list of args for current function */
11: uchar *strnode();
12: %}
13:
14: %union {
15: Node *p;
16: Cell *cp;
17: int i;
18: uchar *s;
19: }
20:
21: %token <i> FIRSTTOKEN /* must be first */
22: %token <i> FATAL
23: %token <p> PROGRAM PASTAT PASTAT2 XBEGIN XEND
24: %token <i> NL ',' '{' '(' '|' ';' '/' ')' '}' '[' ']'
25: %token <i> ARRAY
26: %token <i> MATCH NOTMATCH MATCHOP
27: %token <i> FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS
28: %token <i> AND BOR APPEND EQ GE GT LE LT NE IN
29: %token <i> ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC
30: %token <i> SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT
31: %token <i> ADD MINUS MULT DIVIDE MOD
32: %token <i> ASSIGN ASGNOP ADDEQ SUBEQ MULTEQ DIVEQ MODEQ POWEQ
33: %token <i> PRINT PRINTF SPRINTF
34: %token <p> ELSE INTEST CONDEXPR
35: %token <i> POSTINCR PREINCR POSTDECR PREDECR
36: %token <cp> VAR IVAR VARNF CALL NUMBER STRING FIELD
37: %token <s> REGEXPR
38:
39: %type <p> pas pattern ppattern plist pplist patlist prarg term
40: %type <p> pa_pat pa_stat pa_stats reg_expr
41: %type <p> simple_stmt opt_simple_stmt stmt stmtlist
42: %type <p> var varname funcname varlist
43: %type <p> for if while
44: %type <i> pst opt_pst lbrace rparen comma nl opt_nl and bor
45: %type <i> subop print
46:
47: %right ASGNOP
48: %right '?'
49: %right ':'
50: %left BOR
51: %left AND
52: %left GETLINE
53: %nonassoc APPEND EQ GE GT LE LT NE MATCHOP IN '|'
54: %left ARG BLTIN BREAK CALL CLOSE CONTINUE DELETE DO EXIT FOR FIELD FUNC
55: %left GSUB IF INDEX LSUBSTR MATCHFCN NEXT NUMBER
56: %left PRINT PRINTF RETURN SPLIT SPRINTF STRING SUB SUBSTR
57: %left REGEXPR VAR VARNF IVAR WHILE '('
58: %left CAT
59: %left '+' '-'
60: %left '*' '/' '%'
61: %left NOT UMINUS
62: %right POWER
63: %right DECR INCR
64: %left INDIRECT
65: %token LASTTOKEN /* must be last */
66:
67: %%
68:
69: program:
70: pas { if (errorflag==0)
71: winner = (Node *)stat3(PROGRAM, beginloc, $1, endloc); }
72: | error { yyclearin; bracecheck(); yyerror("bailing out"); }
73: ;
74:
75: and:
76: AND | and NL
77: ;
78:
79: bor:
80: BOR | bor NL
81: ;
82:
83: comma:
84: ',' | comma NL
85: ;
86:
87: do:
88: DO | do NL
89: ;
90:
91: else:
92: ELSE | else NL
93: ;
94:
95: for:
96: FOR '(' opt_simple_stmt ';' pattern ';' opt_simple_stmt rparen stmt
97: { $$ = stat4(FOR, $3, op2(NE,$5,nullnode), $7, $9); }
98: | FOR '(' opt_simple_stmt ';' ';' opt_simple_stmt rparen stmt
99: { $$ = stat4(FOR, $3, NIL, $6, $8); }
100: | FOR '(' varname IN varname rparen stmt
101: { $$ = stat3(IN, $3, makearr($5), $7); }
102: ;
103:
104: funcname:
105: VAR { setfname($1); }
106: | CALL { setfname($1); }
107: ;
108:
109: if:
110: IF '(' pattern rparen { $$ = op2(NE,$3,nullnode); }
111: ;
112:
113: lbrace:
114: '{' | lbrace NL
115: ;
116:
117: nl:
118: NL | nl NL
119: ;
120:
121: opt_nl:
122: /* empty */ { $$ = 0; }
123: | nl
124: ;
125:
126: opt_pst:
127: /* empty */ { $$ = 0; }
128: | pst
129: ;
130:
131:
132: opt_simple_stmt:
133: /* empty */ { $$ = 0; }
134: | simple_stmt
135: ;
136:
137: pas:
138: opt_pst { $$ = 0; }
139: | opt_pst pa_stats opt_pst { $$ = $2; }
140: ;
141:
142: pa_pat:
143: pattern { $$ = op2(NE, $1, nullnode); }
144: ;
145:
146: pa_stat:
147: pa_pat { $$ = stat2(PASTAT, $1, stat2(PRINT, rectonode(), NIL)); }
148: | pa_pat lbrace stmtlist '}' { $$ = stat2(PASTAT, $1, $3); }
149: | pa_pat ',' pa_pat { $$ = pa2stat($1, $3, stat2(PRINT, rectonode(), NIL)); }
150: | pa_pat ',' pa_pat lbrace stmtlist '}' { $$ = pa2stat($1, $3, $5); }
151: | lbrace stmtlist '}' { $$ = stat2(PASTAT, NIL, $2); }
152: | XBEGIN lbrace stmtlist '}'
153: { beginloc = linkum(beginloc, $3); $$ = 0; }
154: | XEND lbrace stmtlist '}'
155: { endloc = linkum(endloc, $3); $$ = 0; }
156: | FUNC funcname '(' varlist rparen {infunc++;} lbrace stmtlist '}'
157: { infunc--; curfname=0; defn($2, $4, $8); $$ = 0; }
158: ;
159:
160: pa_stats:
161: pa_stat
162: | pa_stats pst pa_stat { $$ = linkum($1, $3); }
163: ;
164:
165: patlist:
166: pattern
167: | patlist comma pattern { $$ = linkum($1, $3); }
168: ;
169:
170: ppattern:
171: var ASGNOP ppattern { $$ = op2($2, $1, $3); }
172: | ppattern '?' ppattern ':' ppattern %prec '?'
173: { $$ = op3(CONDEXPR, op2(NE,$1,nullnode), $3, $5); }
174: | ppattern bor ppattern %prec BOR
175: { $$ = op2(BOR, op2(NE,$1,nullnode), op2(NE,$3,nullnode)); }
176: | ppattern and ppattern %prec AND
177: { $$ = op2(AND, op2(NE,$1,nullnode), op2(NE,$3,nullnode)); }
178: | NOT ppattern
179: { $$ = op1(NOT, op2(NE,$2,nullnode)); }
180: | ppattern MATCHOP reg_expr { $$ = op3($2, NIL, $1, makedfa($3, 0)); }
181: | ppattern MATCHOP ppattern
182: { if (constnode($3))
183: $$ = op3($2, NIL, $1, makedfa(strnode($3), 0));
184: else
185: $$ = op3($2, (Node *)1, $1, $3); }
186: | ppattern IN varname { $$ = op2(INTEST, $1, makearr($3)); }
187: | '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); }
188: | ppattern term %prec CAT { $$ = op2(CAT, $1, $2); }
189: | reg_expr
190: { $$ = op3(MATCH, NIL, rectonode(), makedfa($1, 0)); }
191: | term
192: ;
193:
194: pattern:
195: var ASGNOP pattern { $$ = op2($2, $1, $3); }
196: | pattern '?' pattern ':' pattern %prec '?'
197: { $$ = op3(CONDEXPR, op2(NE,$1,nullnode), $3, $5); }
198: | pattern bor pattern %prec BOR
199: { $$ = op2(BOR, op2(NE,$1,nullnode), op2(NE,$3,nullnode)); }
200: | pattern and pattern %prec AND
201: { $$ = op2(AND, op2(NE,$1,nullnode), op2(NE,$3,nullnode)); }
202: | NOT pattern
203: { $$ = op1(NOT, op2(NE,$2,valtonode(lookup("$zero&null",symtab),CCON))); }
204: | pattern EQ pattern { $$ = op2($2, $1, $3); }
205: | pattern GE pattern { $$ = op2($2, $1, $3); }
206: | pattern GT pattern { $$ = op2($2, $1, $3); }
207: | pattern LE pattern { $$ = op2($2, $1, $3); }
208: | pattern LT pattern { $$ = op2($2, $1, $3); }
209: | pattern NE pattern { $$ = op2($2, $1, $3); }
210: | pattern MATCHOP reg_expr { $$ = op3($2, NIL, $1, makedfa($3, 0)); }
211: | pattern MATCHOP pattern
212: { if (constnode($3))
213: $$ = op3($2, NIL, $1, makedfa(strnode($3), 0));
214: else
215: $$ = op3($2, (Node *)1, $1, $3); }
216: | pattern IN varname { $$ = op2(INTEST, $1, makearr($3)); }
217: | '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); }
218: | pattern '|' GETLINE var { $$ = op3(GETLINE, $4, (Node*)$2, $1); }
219: | pattern '|' GETLINE { $$ = op3(GETLINE, (Node*)0, (Node*)$2, $1); }
220: | pattern term %prec CAT { $$ = op2(CAT, $1, $2); }
221: | reg_expr
222: { $$ = op3(MATCH, NIL, rectonode(), makedfa($1, 0)); }
223: | term
224: ;
225:
226: plist:
227: pattern comma pattern { $$ = linkum($1, $3); }
228: | plist comma pattern { $$ = linkum($1, $3); }
229: ;
230:
231: pplist:
232: ppattern
233: | pplist comma ppattern { $$ = linkum($1, $3); }
234:
235: prarg:
236: /* empty */ { $$ = rectonode(); }
237: | pplist
238: | '(' plist ')' { $$ = $2; }
239: ;
240:
241: print:
242: PRINT | PRINTF
243: ;
244:
245: pst:
246: NL | ';' | pst NL | pst ';'
247: ;
248:
249: rbrace:
250: '}' | rbrace NL
251: ;
252:
253: reg_expr:
254: '/' {startreg();} REGEXPR '/' { $$ = (Node *) $3; }
255: ;
256:
257: rparen:
258: ')' | rparen NL
259: ;
260:
261: simple_stmt:
262: print prarg '|' term { $$ = stat3($1, $2, (Node *) $3, $4); }
263: | print prarg APPEND term { $$ = stat3($1, $2, (Node *) $3, $4); }
264: | print prarg GT term { $$ = stat3($1, $2, (Node *) $3, $4); }
265: | print prarg { $$ = stat3($1, $2, NIL, NIL); }
266: | DELETE varname '[' patlist ']' { $$ = stat2(DELETE, makearr($2), $4); }
267: | pattern { $$ = exptostat($1); }
268: | error { yyclearin; yyerror("illegal statement"); }
269: ;
270:
271: st:
272: nl | ';' opt_nl
273: ;
274:
275: stmt:
276: BREAK st { $$ = stat1(BREAK, NIL); }
277: | CLOSE pattern st { $$ = stat1(CLOSE, $2); }
278: | CONTINUE st { $$ = stat1(CONTINUE, NIL); }
279: | do stmt WHILE '(' pattern ')' st
280: { $$ = stat2(DO, $2, op2(NE,$5,nullnode)); }
281: | EXIT pattern st { $$ = stat1(EXIT, $2); }
282: | EXIT st { $$ = stat1(EXIT, NIL); }
283: | for
284: | if stmt else stmt { $$ = stat3(IF, $1, $2, $4); }
285: | if stmt { $$ = stat3(IF, $1, $2, NIL); }
286: | lbrace stmtlist rbrace { $$ = $2; }
287: | NEXT st { if (infunc)
288: yyerror("next is illegal inside a function");
289: $$ = stat1(NEXT, NIL); }
290: | RETURN pattern st { $$ = stat1(RETURN, $2); }
291: | RETURN st { $$ = stat1(RETURN, NIL); }
292: | simple_stmt st
293: | while stmt { $$ = stat2(WHILE, $1, $2); }
294: | ';' opt_nl { $$ = 0; }
295: ;
296:
297: stmtlist:
298: stmt
299: | stmtlist stmt { $$ = linkum($1, $2); }
300: ;
301:
302: subop:
303: SUB | GSUB
304: ;
305:
306: term:
307: term '+' term { $$ = op2(ADD, $1, $3); }
308: | term '-' term { $$ = op2(MINUS, $1, $3); }
309: | term '*' term { $$ = op2(MULT, $1, $3); }
310: | term '/' term { $$ = op2(DIVIDE, $1, $3); }
311: | term '%' term { $$ = op2(MOD, $1, $3); }
312: | term POWER term { $$ = op2(POWER, $1, $3); }
313: | '-' term %prec UMINUS { $$ = op1(UMINUS, $2); }
314: | '+' term %prec UMINUS { $$ = $2; }
315: | BLTIN '(' ')' { $$ = op2(BLTIN, (Node *) $1, rectonode()); }
316: | BLTIN '(' patlist ')' { $$ = op2(BLTIN, (Node *) $1, $3); }
317: | BLTIN { $$ = op2(BLTIN, (Node *) $1, rectonode()); }
318: | CALL '(' ')' { $$ = op2(CALL, valtonode($1,CVAR), NIL); }
319: | CALL '(' patlist ')' { $$ = op2(CALL, valtonode($1,CVAR), $3); }
320: | DECR var { $$ = op1(PREDECR, $2); }
321: | INCR var { $$ = op1(PREINCR, $2); }
322: | var DECR { $$ = op1(POSTDECR, $1); }
323: | var INCR { $$ = op1(POSTINCR, $1); }
324: | GETLINE var LT term { $$ = op3(GETLINE, $2, (Node *)$3, $4); }
325: | GETLINE LT term { $$ = op3(GETLINE, NIL, (Node *)$2, $3); }
326: | GETLINE var { $$ = op3(GETLINE, $2, NIL, NIL); }
327: | GETLINE { $$ = op3(GETLINE, NIL, NIL, NIL); }
328: | INDEX '(' pattern comma pattern ')'
329: { $$ = op2(INDEX, $3, $5); }
330: | INDEX '(' pattern comma reg_expr ')'
331: { yyerror("index() doesn't permit regular expressions");
332: $$ = op2(INDEX, $3, $5); }
333: | '(' pattern ')' { $$ = $2; }
334: | MATCHFCN '(' pattern comma reg_expr ')'
335: { $$ = op3(MATCHFCN, NIL, $3, makedfa($5, 1)); }
336: | MATCHFCN '(' pattern comma pattern ')'
337: { if (constnode($5))
338: $$ = op3(MATCHFCN, NIL, $3, makedfa(strnode($5), 1));
339: else
340: $$ = op3(MATCHFCN, (Node *)1, $3, $5); }
341: | NUMBER { $$ = valtonode($1, CCON); }
342: | SPLIT '(' pattern comma varname comma pattern ')' /* string */
343: { $$ = op4(SPLIT, $3, makearr($5), $7, (Node*)STRING); }
344: | SPLIT '(' pattern comma varname comma reg_expr ')' /* const /regexp/ */
345: { $$ = op4(SPLIT, $3, makearr($5), makedfa($7, 1), (Node *)REGEXPR); }
346: | SPLIT '(' pattern comma varname ')'
347: { $$ = op4(SPLIT, $3, makearr($5), NIL, (Node*)STRING); } /* default */
348: | SPRINTF '(' patlist ')' { $$ = op1($1, $3); }
349: | STRING { $$ = valtonode($1, CCON); }
350: | subop '(' reg_expr comma pattern ')'
351: { $$ = op4($1, NIL, makedfa($3, 1), $5, rectonode()); }
352: | subop '(' pattern comma pattern ')'
353: { if (constnode($3))
354: $$ = op4($1, NIL, makedfa(strnode($3), 1), $5, rectonode());
355: else
356: $$ = op4($1, (Node *)1, $3, $5, rectonode()); }
357: | subop '(' reg_expr comma pattern comma pattern ')'
358: { $$ = op4($1, NIL, makedfa($3, 1), $5, $7); }
359: | subop '(' pattern comma pattern comma pattern ')'
360: { if (constnode($3))
361: $$ = op4($1, NIL, makedfa(strnode($3), 1), $5, $7);
362: else
363: $$ = op4($1, (Node *)1, $3, $5, $7); }
364: | SUBSTR '(' pattern comma pattern comma pattern ')'
365: { $$ = op3(SUBSTR, $3, $5, $7); }
366: | SUBSTR '(' pattern comma pattern ')'
367: { $$ = op3(SUBSTR, $3, $5, NIL); }
368: | var
369: ;
370:
371: var:
372: varname
373: | varname '[' patlist ']' { $$ = op2(ARRAY, makearr($1), $3); }
374: | FIELD { $$ = valtonode($1, CFLD); }
375: | IVAR { $$ = op1(INDIRECT, valtonode($1, CVAR)); }
376: | INDIRECT term { $$ = op1(INDIRECT, $2); }
377: ;
378:
379: varlist:
380: /* nothing */ { arglist = $$ = 0; }
381: | VAR { arglist = $$ = valtonode($1,CVAR); }
382: | varlist comma VAR { arglist = $$ = linkum($1,valtonode($3,CVAR)); }
383: ;
384:
385: varname:
386: VAR { $$ = valtonode($1, CVAR); }
387: | ARG { $$ = op1(ARG, (Node *) $1); }
388: | VARNF { $$ = op1(VARNF, (Node *) $1); }
389: ;
390:
391:
392: while:
393: WHILE '(' pattern rparen { $$ = op2(NE,$3,nullnode); }
394: ;
395:
396: %%
397:
398: setfname(p)
399: Cell *p;
400: {
401: if (isarr(p))
402: yyerror("%s is an array, not a function", p->nval);
403: else if (isfunc(p))
404: yyerror("you can't define function %s more than once", p->nval);
405: curfname = p->nval;
406: }
407:
408: constnode(p)
409: Node *p;
410: {
411: return p->ntype == NVALUE && ((Cell *) (p->narg[0]))->csub == CCON;
412: }
413:
414: uchar *strnode(p)
415: Node *p;
416: {
417: return ((Cell *)(p->narg[0]))->sval;
418: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.