xref: /titanic_41/usr/src/cmd/fm/eversholt/common/escparse.y (revision 6dfee4834394825da35b977ca71cdc965bc7b6a4)
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  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * escparse.y -- parser for esc
27  *
28  * this is the yacc-based parser for Eversholt.  the syntax is simple
29  * and is defined by the LALR(1) grammar described by this file.  there
30  * should be no shift/reduce or reduce/reduce messages when building this
31  * file.
32  *
33  * as the input is parsed, a parse tree is built by calling the
34  * tree_X() functions defined in tree.c.  any syntax errors cause
35  * us to skip to the next semicolon, achieved via the "error" clause
36  * in the stmt rule below.  the yacc state machine code will call
37  * yyerror() in esclex.c and that will keep count of the errors and
38  * display the filename, line number, and current input stream of tokens
39  * to help the user figure out the problem.  the -Y flag to this program
40  * turns on the yacc debugging output which is quite large.  you probably
41  * only need to do that if you're debugging the grammar below.
42  *
43  */
44 
45 #pragma ident	"%Z%%M%	%I%	%E% SMI"
46 
47 #include <stdio.h>
48 #include <ctype.h>
49 #include <string.h>
50 #include <stdlib.h>
51 #include <unistd.h>
52 #include <time.h>
53 #include <sys/time.h>
54 #include "out.h"
55 #include "stable.h"
56 #include "literals.h"
57 #include "lut.h"
58 #include "esclex.h"
59 #include "tree.h"
60 
61 %}
62 %union {
63 	struct tokstr tok;
64 	struct node *np;
65 }
66 
67 %right '='
68 
69 /*
70  * make sure ':' comes immediately after '?' in precedence declarations
71  */
72 %right '?'
73 %nonassoc ':'
74 
75 %left OR
76 %left AND
77 %left '|'
78 %left '^'
79 %left '&'
80 %left EQ NE
81 %left LE GE '<' '>'
82 %left LSHIFT RSHIFT
83 %left '-' '+'
84 %left '*' '%' DIV '/'
85 %right '!' '~'
86 %left '.'
87 
88 %token <tok> PROP MASK ARROW EVENT ENGINE ASRU FRU CONFIG
89 %token <tok> ID QUOTE NUMBER IF PATHFUNC
90 %type <tok> enameid
91 %type <np> root stmtlist stmt nvpairlist nvpair nvname nvexpr
92 %type <np> exprlist expr iterid ename pname epname eexprlist ipname iname
93 %type <np> numexpr cexpr func pfunc parglist, parg
94 %type <np> eventlist event nork norkexpr globid propbody
95 
96 %%
97 
98 root	: stmtlist
99 		{ (void)tree_root($1); }
100 	;
101 
102 stmtlist   : /*empty*/
103 		{ $$ = NULL; }
104         | stmtlist stmt
105 		{ $$ = tree_expr(T_LIST, $1, $2); }
106 	;
107 
108 stmt	: error ';'
109      		{ $$ = tree_nothing(); }
110 	| IF '(' expr ')' stmt
111 		{ $$ = $5; }
112 	| IF '(' expr ')' '{' stmtlist '}'
113 		{ $$ = $6; }
114 	| EVENT event nvpairlist ';'
115 		{ $$ = tree_decl(T_EVENT, $2, $3, $1.file, $1.line); }
116 	| ENGINE event nvpairlist ';'
117 		{ $$ = tree_decl(T_ENGINE, $2, $3, $1.file, $1.line); }
118 	| PROP propbody ';'
119 		{
120 			$$ = tree_stmt(T_PROP, $2, $1.file, $1.line);
121 		}
122 	| MASK propbody ';'
123 		{
124 			$$ = tree_stmt(T_MASK, $2, $1.file, $1.line);
125 		}
126 	| ASRU pname nvpairlist ';'
127 		{
128 			$$ = tree_decl(T_ASRU, $2, $3, $1.file, $1.line);
129 		}
130 	| FRU pname nvpairlist ';'
131 		{
132 			$$ = tree_decl(T_FRU, $2, $3, $1.file, $1.line);
133 		}
134 	| CONFIG ipname nvpairlist ';'
135 		{
136 			$$ = tree_decl(T_CONFIG, $2, $3, $1.file, $1.line);
137 		}
138 	| /*superfluous semicolons are ignored*/ ';'
139      		{ $$ = tree_nothing(); }
140 	;
141 
142 propbody: eventlist nork ARROW nork eventlist
143 		{
144 			$$ = tree_arrow($1, $2, $4, $5);
145 		}
146 	| propbody nork ARROW nork eventlist
147 		{
148 			$$ = tree_arrow($1, $2, $4, $5);
149 		}
150 	;
151 
152 nork	: /* empty */
153 		{ $$ = NULL; }
154 	| '(' norkexpr ')'
155 		{ $$ = $2; }
156 	;
157 
158 norkexpr: NUMBER
159 		{ $$ = tree_num($1.s, $1.file, $1.line); }
160 	| ID
161 		/* really can only be 'A', enforced by check_arrow() later */
162        		{ $$ = tree_name($1.s, IT_NONE, $1.file, $1.line); }
163 	| '(' norkexpr ')'
164 		{ $$ = $2; }
165 	| norkexpr '-' norkexpr
166 		{ $$ = tree_expr(T_SUB, $1, $3); }
167 	| norkexpr '+' norkexpr
168 		{ $$ = tree_expr(T_ADD, $1, $3); }
169 	| norkexpr '*' norkexpr
170 		{ $$ = tree_expr(T_MUL, $1, $3); }
171 	| norkexpr DIV norkexpr
172 		{ $$ = tree_expr(T_DIV, $1, $3); }
173 	| norkexpr '%' norkexpr
174 		{ $$ = tree_expr(T_MOD, $1, $3); }
175 	;
176 
177 nvpairlist: /* empty */
178 		{ $$ = NULL; }
179 	| nvpair
180 	| nvpairlist ',' nvpair
181 		{ $$ = tree_expr(T_LIST, $1, $3); }
182 	;
183 
184 nvpair	: nvname '=' nvexpr
185 		{ $$ = tree_expr(T_NVPAIR, $1, $3); }
186 	| ENGINE '=' nvexpr
187 		/* "engine" is a reserved word, but a valid property name */
188 		{
189 			$$ = tree_expr(T_NVPAIR,
190 				tree_name($1.s, IT_NONE, $1.file, $1.line), $3);
191 		}
192 	;
193 
194 nvname	: ID
195 		{ $$ = tree_name($1.s, IT_NONE, $1.file, $1.line); }
196 	| nvname '-' ID
197 		{
198 			/* hack to allow dashes in property names */
199 			$$ = tree_name_repairdash($1, $3.s);
200 		}
201 	;
202 
203 /* the RHS of an nvpair can be a value, or an ename, or an ename@pname */
204 nvexpr	: numexpr
205 	| ename epname
206 		{ $$ = tree_event($1, $2, NULL); }
207 	| pname
208 	| NUMBER ID
209 		/*
210 		 * ID must be timevals only ("ms", "us", etc.).
211 		 * enforced by tree_timeval().
212 		 */
213 		{ $$ = tree_timeval($1.s, $2.s, $1.file, $1.line); }
214 	| QUOTE
215 		{ $$ = tree_quote($1.s, $1.file, $1.line); }
216 	;
217 
218 /* arithmetic operations, no variables or symbols */
219 numexpr	: numexpr '-' numexpr
220 		{ $$ = tree_expr(T_SUB, $1, $3); }
221 	| numexpr '+' numexpr
222 		{ $$ = tree_expr(T_ADD, $1, $3); }
223 	| numexpr '*' numexpr
224 		{ $$ = tree_expr(T_MUL, $1, $3); }
225 	| numexpr DIV numexpr
226 		{ $$ = tree_expr(T_DIV, $1, $3); }
227 	| numexpr '/' numexpr
228 		{ $$ = tree_expr(T_DIV, $1, $3); }
229 	| numexpr '%' numexpr
230 		{ $$ = tree_expr(T_MOD, $1, $3); }
231  	| '(' numexpr ')'
232 		{ $$ = $2; }
233 	| NUMBER
234 		{ $$ = tree_num($1.s, $1.file, $1.line); }
235 	;
236 
237 eventlist: event
238 	| eventlist ',' event
239 		{ $$ = tree_expr(T_LIST, $1, $3); }
240 	;
241 
242 event	: ename epname eexprlist
243 		{ $$ = tree_event($1, $2, $3); }
244 	;
245 
246 epname	: /* empty */
247 		{ $$ = NULL; }
248 	| '@' pname
249 		{ $$ = $2; }
250 	;
251 
252 eexprlist: /* empty */
253 		{ $$ = NULL; }
254 	| '{' exprlist '}'
255 		{ $$ = $2; }
256 	;
257 
258 exprlist: expr
259 	| exprlist ',' expr
260 		{ $$ = tree_expr(T_LIST, $1, $3); }
261 	;
262 
263 /*
264  * note that expr does not include pname, to avoid reduce/reduce
265  * conflicts between cexpr and iterid involving the use of ID
266  */
267 expr	: cexpr
268 	| NUMBER ID
269 		/*
270 		 * ID must be timevals only ("ms", "us", etc.).
271 		 * enforced by tree_timeval().
272 		 */
273 		{ $$ = tree_timeval($1.s, $2.s, $1.file, $1.line); }
274 	;
275 
276 cexpr	: cexpr '=' cexpr
277 		{ $$ = tree_expr(T_ASSIGN, $1, $3); }
278 	| cexpr '?' cexpr
279 		{ $$ = tree_expr(T_CONDIF, $1, $3); }
280 	| cexpr ':' cexpr
281 		{ $$ = tree_expr(T_CONDELSE, $1, $3); }
282 	| cexpr OR cexpr
283 		{ $$ = tree_expr(T_OR, $1, $3); }
284  	| cexpr AND cexpr
285 		{ $$ = tree_expr(T_AND, $1, $3); }
286 	| cexpr '|' cexpr
287 		{ $$ = tree_expr(T_BITOR, $1, $3); }
288 	| cexpr '^' cexpr
289 		{ $$ = tree_expr(T_BITXOR, $1, $3); }
290 	| cexpr '&' cexpr
291 		{ $$ = tree_expr(T_BITAND, $1, $3); }
292 	| cexpr EQ cexpr
293 		{ $$ = tree_expr(T_EQ, $1, $3); }
294 	| cexpr NE cexpr
295 		{ $$ = tree_expr(T_NE, $1, $3); }
296 	| cexpr '<' cexpr
297 		{ $$ = tree_expr(T_LT, $1, $3); }
298 	| cexpr LE cexpr
299 		{ $$ = tree_expr(T_LE, $1, $3); }
300 	| cexpr '>' cexpr
301 		{ $$ = tree_expr(T_GT, $1, $3); }
302 	| cexpr GE cexpr
303 		{ $$ = tree_expr(T_GE, $1, $3); }
304 	| cexpr LSHIFT cexpr
305 		{ $$ = tree_expr(T_LSHIFT, $1, $3); }
306 	| cexpr RSHIFT cexpr
307 		{ $$ = tree_expr(T_RSHIFT, $1, $3); }
308 	| cexpr '-' cexpr
309 		{ $$ = tree_expr(T_SUB, $1, $3); }
310 	| cexpr '+' cexpr
311 		{ $$ = tree_expr(T_ADD, $1, $3); }
312 	| cexpr '*' cexpr
313 		{ $$ = tree_expr(T_MUL, $1, $3); }
314 	| cexpr DIV cexpr
315 		{ $$ = tree_expr(T_DIV, $1, $3); }
316 	| cexpr '/' cexpr
317 		{ $$ = tree_expr(T_DIV, $1, $3); }
318 	| cexpr '%' cexpr
319 		{ $$ = tree_expr(T_MOD, $1, $3); }
320 	|  '!' cexpr
321 		{ $$ = tree_expr(T_NOT, $2, NULL); }
322 	|  '~' cexpr
323 		{ $$ = tree_expr(T_BITNOT, $2, NULL); }
324 	| '(' cexpr ')'
325 		{ $$ = $2; }
326 	| func
327 	| NUMBER
328 		{ $$ = tree_num($1.s, $1.file, $1.line); }
329 	| ID
330        		{
331 			/* iteration variable */
332 			$$ = tree_name($1.s, IT_NONE, $1.file, $1.line);
333 		}
334 	| globid
335 	| QUOTE
336 		{ $$ = tree_quote($1.s, $1.file, $1.line); }
337 	;
338 
339 func	: ID '(' ')'
340 		{ $$ = tree_func($1.s, NULL, $1.file, $1.line); }
341 	| ID '(' exprlist ')'
342 		{ $$ = tree_func($1.s, $3, $1.file, $1.line); }
343 	| PATHFUNC '(' parglist ')'
344 		{ $$ = tree_func($1.s, $3, $1.file, $1.line); }
345 	| pfunc
346 	;
347 
348 parglist: parg
349 	| parglist ',' parg
350 		{ $$ = tree_expr(T_LIST, $1, $3); }
351 	;
352 
353 parg	: pfunc
354 	| pname
355 		{ $$ = tree_pname($1); }
356 	| QUOTE
357 		{ $$ = tree_quote($1.s, $1.file, $1.line); }
358 	;
359 
360 /* asru() and fru() show up as functions in the parse tree */
361 pfunc	: ASRU '(' pname ')'
362 		{ $$ = tree_func($1.s, tree_pname($3), $1.file, $1.line); }
363 	| FRU '(' pname ')'
364 		{ $$ = tree_func($1.s, tree_pname($3), $1.file, $1.line); }
365 	;
366 
367 globid	: '$' ID
368        		{ $$ = tree_globid($2.s, $2.file, $2.line); }
369 	;
370 
371 iterid	: ID
372        		{ $$ = tree_name($1.s, IT_VERTICAL, $1.file, $1.line); }
373 	| ID '[' ']'
374        		{ $$ = tree_name($1.s, IT_VERTICAL, $1.file, $1.line); }
375 	| ID '[' cexpr ']'
376        		{
377 			$$ = tree_name_iterator(
378 			   tree_name($1.s, IT_VERTICAL, $1.file, $1.line), $3);
379 		}
380 	| ID '<' '>'
381        		{ $$ = tree_name($1.s, IT_HORIZONTAL, $1.file, $1.line); }
382 	| ID '<' ID '>'
383        		{
384 			$$ = tree_name_iterator(
385 			    tree_name($1.s, IT_HORIZONTAL, $1.file, $1.line),
386 			    tree_name($3.s, IT_NONE, $3.file, $3.line));
387 		}
388 	;
389 
390 /* iname is an ID where we can peel numbers off the end */
391 iname	: ID
392        		{ $$ = tree_iname($1.s, $1.file, $1.line); }
393 	;
394 
395 /* base case of ID.ID instead of just ID requires ename to contain one dot */
396 ename	: ID '.' enameid
397        		{
398 			$$ = tree_name_append(
399 			    tree_name($1.s, IT_ENAME, $1.file, $1.line),
400 			    tree_name($3.s, IT_NONE, $3.file, $3.line));
401 		}
402 	| ename '.' enameid
403 		{
404 			$$ = tree_name_append($1,
405 			    tree_name($3.s, IT_NONE, $3.file, $3.line));
406 		}
407 	| ename '-' enameid
408 		{
409 			/*
410 			 * hack to allow dashes in class names.  when we
411 			 * detect the dash here, we know we're in a class
412 			 * name because the left recursion of this rule
413 			 * means we've already matched at least:
414 			 * 	ID '.' ID
415 			 * so the ename here has an incomplete final
416 			 * component (because the lexer stopped at the
417 			 * dash).  so we repair that final component here.
418 			 */
419 			$$ = tree_name_repairdash($1, $3.s);
420 		}
421 	;
422 
423 /* like an ID, but we let reserved words act unreserved in enames */
424 enameid	: ID
425 	| PROP
426 	| MASK
427 	| EVENT
428 	| ENGINE
429 	| ASRU
430 	| FRU
431 	| CONFIG
432 	| IF
433 	;
434 
435 /* pname is a pathname, like x/y, x<i>/y[0], etc */
436 pname	: iterid
437 	| pname '/' iterid
438 		{ $$ = tree_name_append($1, $3); }
439 	;
440 
441 /* ipname is an "instanced" pathname, like x0/y1 */
442 ipname	: iname
443 	| ipname '/' iname
444 		{ $$ = tree_name_append($1, $3); }
445 	;
446 
447 %%
448