1 %{
2 /*
3 * CDDL HEADER START
4 *
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License, Version 1.0 only
7 * (the "License"). You may not use this file except in compliance
8 * with the License.
9 *
10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 * or http://www.opensolaris.org/os/licensing.
12 * See the License for the specific language governing permissions
13 * and limitations under the License.
14 *
15 * When distributing Covered Code, include this CDDL HEADER in each
16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 * If applicable, add the following below this CDDL HEADER, with the
18 * fields enclosed by brackets "[]" replaced with your own identifying
19 * information: Portions Copyright [yyyy] [name of copyright owner]
20 *
21 * CDDL HEADER END
22 */
23 /*
24 * awk -- YACC grammar
25 *
26 * Copyright (c) 1995 by Sun Microsystems, Inc.
27 *
28 * Copyright 1986, 1992 by Mortice Kern Systems Inc. All rights reserved.
29 *
30 * This Software is unpublished, valuable, confidential property of
31 * Mortice Kern Systems Inc. Use is authorized only in accordance
32 * with the terms and conditions of the source licence agreement
33 * protecting this Software. Any unauthorized use or disclosure of
34 * this Software is strictly prohibited and will result in the
35 * termination of the licence agreement.
36 *
37 * NOTE: this grammar correctly produces NO shift/reduce conflicts from YACC.
38 *
39 */
40
41 /*
42 * Do not use any character constants as tokens, so the resulting C file
43 * is codeset independent.
44 */
45
46 #ident "%Z%%M% %I% %E% SMI"
47 #include "awk.h"
48 static NODE * fliplist ANSI((NODE *np));
49 %}
50
51 %union {
52 NODE *node;
53 };
54
55 /*
56 * Do not use any character constants as tokens, so the resulting C file
57 * is codeset independent.
58 *
59 * Declare terminal symbols before their operator
60 * precedences to get them in a contiguous block
61 * for giant switches in action() and exprreduce().
62 */
63 /* Tokens from exprreduce() */
64 %token <node> PARM ARRAY UFUNC FIELD IN INDEX CONCAT
65 %token <node> NOT AND OR EXP QUEST
66 %token <node> EQ NE GE LE GT LT
67 %token <node> ADD SUB MUL DIV REM INC DEC PRE_INC PRE_DEC
68 %token <node> GETLINE CALLFUNC RE TILDE NRE
69
70 /* Tokens shared by exprreduce() and action() */
71 %token ASG
72
73 /* Tokens from action() */
74 %token <node> PRINT PRINTF
75 %token <node> EXIT RETURN BREAK CONTINUE NEXT
76 %token <node> DELETE WHILE DO FOR FORIN IF
77
78 /*
79 * Terminal symbols not used in action() and exprrreduce()
80 * switch statements.
81 */
82 %token <node> CONSTANT VAR FUNC
83 %token <node> DEFFUNC BEGIN END CLOSE ELSE PACT
84 %right ELSE
85 %token DOT CALLUFUNC
86
87 /*
88 * Tokens not used in grammar
89 */
90 %token KEYWORD SVAR
91 %token PIPESYM
92
93 /*
94 * Tokens representing character constants
95 * TILDE, '~', taken care of above
96 */
97 %token BAR /* '|' */
98 CARAT /* '^' */
99 LANGLE /* '<' */
100 RANGLE /* '>' */
101 PLUSC /* '+' */
102 HYPHEN /* '-' */
103 STAR /* '*' */
104 SLASH /* '/' */
105 PERCENT /* '%' */
106 EXCLAMATION /* '!' */
107 DOLLAR /* '$' */
108 LSQUARE /* '[' */
109 RSQUARE /* ']' */
110 LPAREN /* '(' */
111 RPAREN /* ')' */
112 SEMI /* ';' */
113 LBRACE /* '{' */
114 RBRACE /* '}' */
115
116 /*
117 * Priorities of operators
118 * Lowest to highest
119 */
120 %left COMMA
121 %right BAR PIPE WRITE APPEND
122 %right ASG AADD ASUB AMUL ADIV AREM AEXP
123 %right QUEST COLON
124 %left OR
125 %left AND
126 %left IN
127 %left CARAT
128 %left TILDE NRE
129 %left EQ NE LANGLE RANGLE GE LE
130 %left CONCAT
131 %left PLUSC HYPHEN
132 %left STAR SLASH PERCENT
133 %right UPLUS UMINUS
134 %right EXCLAMATION
135 %right EXP
136 %right INC DEC URE
137 %left DOLLAR LSQUARE RSQUARE
138 %left LPAREN RPAREN
139
140 %type <node> prog rule pattern expr rvalue lvalue fexpr varlist varlist2
141 %type <node> statement statlist fileout exprlist eexprlist simplepattern
142 %type <node> getline optvar var
143 %type <node> dummy
144
145 %start dummy
146 %%
147
148 dummy:
149 prog = {
150 yytree = fliplist(yytree);
151 }
152 ;
153 prog:
154 rule = {
155 yytree = $1;
156 }
157 | rule SEMI prog = {
158 if ($1 != NNULL) {
159 if (yytree != NNULL)
160 yytree = node(COMMA, $1, yytree); else
161 yytree = $1;
162 }
163 }
164 ;
165
166 rule: pattern LBRACE statlist RBRACE = {
167 $$ = node(PACT, $1, $3);
168 doing_begin = 0;
169 }
170 | LBRACE statlist RBRACE = {
171 npattern++;
172 $$ = node(PACT, NNULL, $2);
173 }
174 | pattern = {
175 $$ = node(PACT, $1, node(PRINT, NNULL, NNULL));
176 doing_begin = 0;
177 }
178 | DEFFUNC VAR
179 { $2->n_type = UFUNC; funparm = 1; }
180 LPAREN varlist RPAREN
181 { funparm = 0; }
182 LBRACE statlist { uexit($5); } RBRACE = {
183 $2->n_ufunc = node(DEFFUNC, $5, fliplist($9));
184 $$ = NNULL;
185 }
186 | DEFFUNC UFUNC = {
187 awkerr((char *) gettext("function \"%S\" redefined"), $2->n_name);
188 /* NOTREACHED */
189 }
190 | = {
191 $$ = NNULL;
192 }
193 ;
194
195 pattern:
196 simplepattern
197 | expr COMMA expr = {
198 ++npattern;
199 $$ = node(COMMA, $1, $3);
200 }
201 ;
202
203 simplepattern:
204 BEGIN = {
205 $$ = node(BEGIN, NNULL, NNULL);
206 doing_begin++;
207 }
208 | END = {
209 ++npattern;
210 $$ = node(END, NNULL, NNULL);
211 }
212 | expr = {
213 ++npattern;
214 $$ = $1;
215 }
216 ;
217
218 eexprlist:
219 exprlist
220 | = {
221 $$ = NNULL;
222 }
223 ;
224
225 exprlist:
226 expr %prec COMMA
227 | exprlist COMMA expr = {
228 $$ = node(COMMA, $1, $3);
229 }
230 ;
231
232 varlist:
233 = {
234 $$ = NNULL;
235 }
236 | varlist2
237 ;
238
239 varlist2:
240 var
241 | var COMMA varlist2 = {
242 $$ = node(COMMA, $1, $3);
243 }
244 ;
245
246 fexpr:
247 expr
248 | = {
249 $$ = NNULL;
250 }
251 ;
252
253 /*
254 * Normal expression (includes regular expression)
255 */
256 expr:
257 expr PLUSC expr = {
258 $$ = node(ADD, $1, $3);
259 }
260 | expr HYPHEN expr = {
261 $$ = node(SUB, $1, $3);
262 }
263 | expr STAR expr = {
264 $$ = node(MUL, $1, $3);
265 }
266 | expr SLASH expr = {
267 $$ = node(DIV, $1, $3);
268 }
269 | expr PERCENT expr = {
270 $$ = node(REM, $1, $3);
271 }
272 | expr EXP expr = {
273 $$ = node(EXP, $1, $3);
274 }
275 | expr AND expr = {
276 $$ = node(AND, $1, $3);
277 }
278 | expr OR expr = {
279 $$ = node(OR, $1, $3);
280 }
281 | expr QUEST expr COLON expr = {
282 $$ = node(QUEST, $1, node(COLON, $3, $5));
283 }
284 | lvalue ASG expr = {
285 $$ = node(ASG, $1, $3);
286 }
287 | lvalue AADD expr = {
288 $$ = node(AADD, $1, $3);
289 }
290 | lvalue ASUB expr = {
291 $$ = node(ASUB, $1, $3);
292 }
293 | lvalue AMUL expr = {
294 $$ = node(AMUL, $1, $3);
295 }
296 | lvalue ADIV expr = {
297 $$ = node(ADIV, $1, $3);
298 }
299 | lvalue AREM expr = {
300 $$ = node(AREM, $1, $3);
301 }
302 | lvalue AEXP expr = {
303 $$ = node(AEXP, $1, $3);
304 }
305 | lvalue INC = {
306 $$ = node(INC, $1, NNULL);
307 }
308 | lvalue DEC = {
309 $$ = node(DEC, $1, NNULL);
310 }
311 | expr EQ expr = {
312 $$ = node(EQ, $1, $3);
313 }
314 | expr NE expr = {
315 $$ = node(NE, $1, $3);
316 }
317 | expr RANGLE expr = {
318 $$ = node(GT, $1, $3);
319 }
320 | expr LANGLE expr = {
321 $$ = node(LT, $1, $3);
322 }
323 | expr GE expr = {
324 $$ = node(GE, $1, $3);
325 }
326 | expr LE expr = {
327 $$ = node(LE, $1, $3);
328 }
329 | expr TILDE expr = {
330 $$ = node(TILDE, $1, $3);
331 }
332 | expr NRE expr = {
333 $$ = node(NRE, $1, $3);
334 }
335 | expr IN var = {
336 $$ = node(IN, $3, $1);
337 }
338 | LPAREN exprlist RPAREN IN var = {
339 $$ = node(IN, $5, $2);
340 }
341 | getline
342 | rvalue
343 | expr CONCAT expr = {
344 $$ = node(CONCAT, $1, $3);
345 }
346 ;
347
348 lvalue:
349 DOLLAR rvalue = {
350 $$ = node(FIELD, $2, NNULL);
351 }
352 /*
353 * Prevents conflict with FOR LPAREN var IN var RPAREN production
354 */
355 | var %prec COMMA
356 | var LSQUARE exprlist RSQUARE = {
357 $$ = node(INDEX, $1, $3);
358 }
359 ;
360
361 var:
362 VAR
363 | PARM
364 ;
365
366 rvalue:
367 lvalue %prec COMMA
368 | CONSTANT
369 | LPAREN expr RPAREN term = {
370 $$ = $2;
371 }
372 | EXCLAMATION expr = {
373 $$ = node(NOT, $2, NNULL);
374 }
375 | HYPHEN expr %prec UMINUS = {
376 $$ = node(SUB, const0, $2);
377 }
378 | PLUSC expr %prec UPLUS = {
379 $$ = $2;
380 }
381 | DEC lvalue = {
382 $$ = node(PRE_DEC, $2, NNULL);
383 }
384 | INC lvalue = {
385 $$ = node(PRE_INC, $2, NNULL);
386 }
387 | FUNC = {
388 $$ = node(CALLFUNC, $1, NNULL);
389 }
390 | FUNC LPAREN eexprlist RPAREN term = {
391 $$ = node(CALLFUNC, $1, $3);
392 }
393 | UFUNC LPAREN eexprlist RPAREN term = {
394 $$ = node(CALLUFUNC, $1, $3);
395 }
396 | VAR LPAREN eexprlist RPAREN term = {
397 $$ = node(CALLUFUNC, $1, $3);
398 }
399 | SLASH {redelim='/';} URE SLASH %prec URE = {
400 $$ = $<node>3;
401 }
402 ;
403
404 statement:
405 FOR LPAREN fexpr SEMI fexpr SEMI fexpr RPAREN statement = {
406 $$ = node(FOR, node(COMMA, $3, node(COMMA, $5, $7)), $9);
407 }
408 | FOR LPAREN var IN var RPAREN statement = {
409 register NODE *np;
410
411 /*
412 * attempt to optimize statements for the form
413 * for (i in x) delete x[i]
414 * to
415 * delete x
416 */
417 np = $7;
418 if (np != NNULL
419 && np->n_type == DELETE
420 && (np = np->n_left)->n_type == INDEX
421 && np->n_left == $5
422 && np->n_right == $3)
423 $$ = node(DELETE, $5, NNULL);
424 else
425 $$ = node(FORIN, node(IN, $3, $5), $7);
426 }
427 | WHILE LPAREN expr RPAREN statement = {
428 $$ = node(WHILE, $3, $5);
429 }
430 | DO statement WHILE LPAREN expr RPAREN = {
431 $$ = node(DO, $5, $2);
432 }
433 | IF LPAREN expr RPAREN statement ELSE statement = {
434 $$ = node(IF, $3, node(ELSE, $5, $7));
435 }
436 | IF LPAREN expr RPAREN statement %prec ELSE = {
437 $$ = node(IF, $3, node(ELSE, $5, NNULL));
438 }
439 | CONTINUE SEMI = {
440 $$ = node(CONTINUE, NNULL, NNULL);
441 }
442 | BREAK SEMI = {
443 $$ = node(BREAK, NNULL, NNULL);
444 }
445 | NEXT SEMI = {
446 $$ = node(NEXT, NNULL, NNULL);
447 }
448 | DELETE lvalue SEMI = {
449 $$ = node(DELETE, $2, NNULL);
450 }
451 | RETURN fexpr SEMI = {
452 $$ = node(RETURN, $2, NNULL);
453 }
454 | EXIT fexpr SEMI = {
455 $$ = node(EXIT, $2, NNULL);
456 }
457 | PRINT eexprlist fileout SEMI = {
458 $$ = node(PRINT, $2, $3);
459 }
460 | PRINT LPAREN exprlist RPAREN fileout SEMI = {
461 $$ = node(PRINT, $3, $5);
462 }
463 | PRINTF exprlist fileout SEMI = {
464 $$ = node(PRINTF, $2, $3);
465 }
466 | PRINTF LPAREN exprlist RPAREN fileout SEMI = {
467 $$ = node(PRINTF, $3, $5);
468 }
469 | expr SEMI = {
470 $$ = $1;
471 }
472 | SEMI = {
473 $$ = NNULL;
474 }
475 | LBRACE statlist RBRACE = {
476 $$ = $2;
477 }
478 ;
479
480
481 statlist:
482 statement
483 | statlist statement = {
484 if ($1 == NNULL)
485 $$ = $2;
486 else if ($2 == NNULL)
487 $$ = $1;
488 else
489 $$ = node(COMMA, $1, $2);
490 }
491 ;
492
493 fileout:
494 WRITE expr = {
495 $$ = node(WRITE, $2, NNULL);
496 }
497 | APPEND expr = {
498 $$ = node(APPEND, $2, NNULL);
499 }
500 | PIPE expr = {
501 $$ = node(PIPE, $2, NNULL);
502 }
503 | = {
504 $$ = NNULL;
505 }
506 ;
507
508 getline:
509 GETLINE optvar %prec WRITE = {
510 $$ = node(GETLINE, $2, NNULL);
511 }
512 | expr BAR GETLINE optvar = {
513 $$ = node(GETLINE, $4, node(PIPESYM, $1, NNULL));
514 }
515 | GETLINE optvar LANGLE expr = {
516 $$ = node(GETLINE, $2, node(LT, $4, NNULL));
517 }
518 ;
519
520 optvar:
521 lvalue
522 | = {
523 $$ = NNULL;
524 }
525 ;
526
527 term:
528 {catterm = 1;}
529 ;
530 %%
531 /*
532 * Flip a left-recursively generated list
533 * so that it can easily be traversed from left
534 * to right without recursion.
535 */
536 static NODE *
fliplist(np)537 fliplist(np)
538 register NODE *np;
539 {
540 int type;
541
542 if (np!=NNULL && !isleaf(np->n_flags)
543 #if 0
544 && (type = np->n_type)!=FUNC && type!=UFUNC
545 #endif
546 ) {
547 np->n_right = fliplist(np->n_right);
548 if ((type=np->n_type)==COMMA) {
549 register NODE *lp;
550
551 while ((lp = np->n_left)!=NNULL && lp->n_type==COMMA) {
552 register NODE* *spp;
553
554 lp->n_right = fliplist(lp->n_right);
555 for (spp = &lp->n_right;
556 *spp != NNULL && (*spp)->n_type==COMMA;
557 spp = &(*spp)->n_right)
558 ;
559 np->n_left = *spp;
560 *spp = np;
561 np = lp;
562 }
563 }
564 if (np->n_left != NULL &&
565 (type = np->n_left->n_type)!= FUNC && type!=UFUNC)
566 np->n_left = fliplist(np->n_left);
567 }
568 return (np);
569 }
570