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