|
|
1.1 root 1: /*
2: * AWK grammar
3: * yacc -prods 120 -terms 80 -nterms 40 -states 200 awk.y
4: * to make it fit on the PDP-11 (non separated I/D).
5: * Do not be surprised at the 48 S/R
6: * conflicts that this grammar gets
7: * from yacc. Worry if you get more
8: * though. This is mostly due to
9: * the combination of implicit string
10: * concatenation mixed with embedded assignments.
11: * In addition, 12 of these come from regular
12: * expressions.
13: * (NOTE: unary minus cannot be done because
14: * it is totally ambiguous with string concatentation.
15: * and output redirection is disambiguated by disallowing
16: * the relation '>' in `print' and `printf' statements.)
17: */
18:
19: %{
20: #include "awk.h"
21:
22: %}
23:
24: %union {
25: int u_char;
26: CHAR *u_charp;
27: NODE *u_node;
28: int (*u_func)();
29: }
30:
31: %token IF_ WHILE_ FOR_ ELSE_ BREAK_ CONTINUE_ NEXT_ EXIT_
32: %token IN_
33: %token PRINT_ PRINTF_
34: %token BEGIN_ END_
35: %token FAPPEND_ FOUT_
36: %token <u_node> ID_ STRING_ NUMBER_ FUNCTION_
37:
38: %type <u_node> linelist line pattern regexp re
39: %type <u_node> stat stlist compound assignment
40: %type <u_node> variable terminal constant exp e
41: %type <u_node> output elist altlst error
42: %type <u_char> reclosure assignop
43:
44: %left SCON_
45: %right ASADD_ ASSUB_ ASMUL_ ASDIV_ ASMOD_ '='
46: %left OROR_
47: %left ANDAND_
48: %left '~' NMATCH_
49: %nonassoc EQ_ NE_
50: %nonassoc GE_ LE_ '>' '<'
51: %left '+' '-'
52: %left '*' '/' '%'
53: %nonassoc '!' INC_ DEC_
54: %nonassoc '$'
55: %nonassoc '(' '['
56:
57: /*
58: * Special tokens for
59: * regular expressions
60: * and expression precedences.
61: */
62: %token REEOL_ REBOL_ REANY_
63: %token <u_charp> RECLASS_
64: %token <u_char> RECHAR_
65:
66: %left REOR_
67: %left RECON_
68: %nonassoc RECLOS_ RENECL_ REZOCL_
69:
70: %%
71: code:
72: linelist {
73: codep = $1;
74: }
75: ;
76:
77: linelist:
78: line linelist {
79: $$ = node(ALIST, $1, $2);
80: }
81: | line
82: ;
83:
84: line:
85: compound '\n' {
86: $$ = node(AROOT, NULL, $1);
87: }
88: | pattern '\n' {
89: $$ = node(AROOT, $1, NULL);
90: }
91: | pattern compound '\n' {
92: $$ = node(AROOT, $1, $2);
93: }
94: ;
95:
96: pattern:
97: BEGIN_ {
98: $$ = node(ABEGIN);
99: }
100: | END_ {
101: $$ = node(AEND);
102: }
103: | e
104: | e ',' e {
105: $$ = node(ARANGE, $1, $3);
106: }
107: ;
108:
109: regexp:
110: '/' { lexre=1; } re '/' {
111: lexre = 0;
112: $$ = $3;
113: }
114: | error '\n' {
115: yyerrok;
116: yyerror("Badly formed regular expression");
117: } regexp {
118: $$ = $4;
119: }
120: ;
121:
122: re:
123: re re %prec RECON_ {
124: register NODE *np;
125:
126: for (np = $1; np->n_O3!=NULL; np = np->n_O3)
127: ;
128: np->n_O3 = $2;
129: $$ = $1;
130: }
131: | '(' re ')' {
132: $$ = $2;
133: }
134: | re REOR_ re {
135: $$ = node(AROR, $1, $3, NULL);
136: }
137: | re reclosure {
138: $$ = node($2, $1, NULL, NULL);
139: }
140: | RECLASS_ {
141: $$ = node(yflag?ARDCLASS:ARCLASS, NULL, NULL, NULL);
142: $$->n_o1.n_charp = $1;
143: }
144: | REANY_ {
145: $$ = node(ARANY, NULL, NULL, NULL);
146: }
147: | REBOL_ {
148: $$ = node(ARBOL, NULL, NULL, NULL);
149: }
150: | REEOL_ {
151: $$ = node(AREOL, NULL, NULL, NULL);
152: }
153: | RECHAR_ {
154: $$ = cnode(yflag?ARDCHAR:ARCHAR, $1);
155: }
156: ;
157:
158: reclosure:
159: RECLOS_ {
160: $$ = ARCLOS;
161: }
162: | REZOCL_ {
163: $$ = ARZOCL;
164: }
165: | RENECL_ {
166: $$ = ARNECL;
167: }
168: ;
169:
170: compound:
171: '{' stlist '}' {
172: $$ = $2;
173: }
174: ;
175:
176: stat:
177: IF_ '(' e specparen stat {
178: $$ = node(AIF, $3, $5, NULL);
179: }
180: | IF_ '(' e specparen stat ELSE_ {nlskip = 1;} stat {
181: $$ = node(AIF, $3, $5, $8);
182: }
183: | WHILE_ '(' e specparen stat {
184: $$ = node(AWHILE, $3, $5);
185: }
186: | FOR_ '(' variable IN_ variable specparen stat {
187: $$ = node(AFORIN, $3, $5, $7);
188: }
189: | FOR_ '(' e ';' e ';' e specparen stat {
190: $$ = node(AFOR, $3, $5, $7, $9);
191: }
192: | FOR_ '(' ';' e ';' e specparen stat {
193: $$ = node(AFOR, NULL, $4, $6, $8);
194: }
195: | BREAK_ ';' {
196: $$ = node(ABREAK);
197: }
198: | CONTINUE_ ';' {
199: $$ = node(ACONTIN);
200: }
201: | compound
202: | e ';'
203: | PRINT_ {outflag++;} altlst output {
204: $$ = node(APRINT, $3, $4);
205: }
206: | PRINT_ {outflag++;} output {
207: $$ = node(APRINT, &xfield0, $3);
208: }
209: | PRINTF_ {outflag++;} altlst output {
210: $$ = node(APRINTF, $3, $4);
211: }
212: | NEXT_ ';' {
213: $$ = node(ANEXT);
214: }
215: | EXIT_ ';' {
216: $$ = node(AEXIT);
217: }
218: | ';' {
219: $$ = NULL;
220: }
221: ;
222:
223: stlist:
224: stat
225: | stat stlist {
226: if ($1!=NULL && $2!=NULL)
227: $$ = node(ALIST, $1, $2);
228: else if ($1 != NULL)
229: $$ = $1;
230: else
231: $$ = $2;
232: }
233: ;
234:
235: specparen:
236: ')' {
237: nlskip = 1;
238: }
239: ;
240:
241: assignment:
242: variable '=' exp {
243: $$ = node(AASGN, $1, $3);
244: }
245: | variable assignop exp {
246: $$ = node(AASGN, $1, node($2, $1, $3));
247: }
248: | INC_ variable {
249: $$ = node(AASGN, $2, node(AADD, $2, &xone));
250: }
251: | variable INC_ {
252: $$ = node(AINCA, $1);
253: }
254: | DEC_ variable {
255: $$ = node(AASGN, $2, node(ASUB, $2, &xone));
256: }
257: | variable DEC_ {
258: $$ = node(ADECA, $1);
259: }
260: ;
261:
262: assignop:
263: ASADD_ {
264: $$ = AADD;
265: }
266: | ASSUB_ {
267: $$ = ASUB;
268: }
269: | ASMUL_ {
270: $$ = AMUL;
271: }
272: | ASDIV_ {
273: $$ = ADIV;
274: }
275: | ASMOD_ {
276: $$ = AMOD;
277: }
278: ;
279:
280: variable:
281: '$' '(' e ')' {
282: $$ = node(AFIELD, $3);
283: }
284: | '$' terminal {
285: $$ = node(AFIELD, $2);
286: }
287: | ID_ '[' exp ']' {
288: $$ = node(AARRAY, $1, $3);
289: }
290: | ID_
291: ;
292:
293: constant:
294: STRING_
295: | NUMBER_
296: ;
297:
298: terminal:
299: variable
300: | constant
301: ;
302:
303: exp:
304: e
305: | exp e %prec SCON_ {
306: $$ = node(ACONC, $1, $2);
307: }
308: ;
309:
310: e:
311: '(' exp ')' {
312: $$ = $2;
313: }
314: | e ANDAND_ e {
315: $$ = node(AANDAND, $1, $3);
316: }
317: | e OROR_ e {
318: $$ = node(AOROR, $1, $3);
319: }
320: | '!' e {
321: $$ = node(ANOT, $2);
322: }
323: | '-' e %prec '!' {
324: $$ = node(ANEG, $2);
325: }
326: | terminal
327: | assignment
328: | e '+' e {
329: $$ = node(AADD, $1, $3);
330: }
331: | e '-' e {
332: $$ = node(ASUB, $1, $3);
333: }
334: | e '*' e {
335: $$ = node(AMUL, $1, $3);
336: }
337: | e '/' e {
338: $$ = node(ADIV, $1, $3);
339: }
340: | e '%' e {
341: $$ = node(AMOD, $1, $3);
342: }
343: | e '>' e {
344: $$ = node(AGT, $1, $3);
345: }
346: | e '<' e {
347: $$ = node(ALT, $1, $3);
348: }
349: | e EQ_ e {
350: $$ = node(AEQ, $1, $3);
351: }
352: | e NE_ e {
353: $$ = node(ANE, $1, $3);
354: }
355: | e GE_ e {
356: $$ = node(AGE, $1,$3);
357: }
358: | e LE_ e {
359: $$ = node(ALE, $1, $3);
360: }
361: | e '~' regexp {
362: $$ = node(AREMAT, $1, $3);
363: }
364: | e NMATCH_ regexp {
365: $$ = node(ARENMAT, $1, $3);
366: }
367: | regexp {
368: if (brlevel)
369: awkerr("Regular expression illegal in action");
370: $$ = node(ARE, $1);
371: }
372: | FUNCTION_ '(' elist ')' {
373: $$ = node(AFUNC, $1, $3);
374: }
375: | FUNCTION_ {
376: $$ = node(AFUNC, $1, NULL);
377: }
378: ;
379:
380: output:
381: FAPPEND_ terminal ';' {
382: $$ = node(AFAPP, $2);
383: }
384: | FOUT_ terminal %prec '$' ';' {
385: $$ = node(AFOUT, $2);
386: }
387: | '|' terminal ';' {
388: $$ = node(AFPIPE, $2);
389: }
390: | ';' {
391: $$ = NULL;
392: }
393: ;
394:
395: altlst : '(' elist ')' {
396: $$ = $2;
397: }
398: | elist {
399: $$ = $1;
400: }
401: ;
402:
403: elist:
404: exp {
405: $$ = $1;
406: }
407: | exp ',' elist {
408: $$ = node(ALIST, $1, $3);
409: }
410: ;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.