dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / fm / eversholt / common / escparse.y
blobfe4b01a232c578e17441a523d67395a3fb7f3ca8
1 %{
2 /*
3 * CDDL HEADER START
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License (the "License").
7 * You may not use this file except in compliance with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * escparse.y -- parser for esc
27 * this is the yacc-based parser for Eversholt. the syntax is simple
28 * and is defined by the LALR(1) grammar described by this file. there
29 * should be no shift/reduce or reduce/reduce messages when building this
30 * file.
32 * as the input is parsed, a parse tree is built by calling the
33 * tree_X() functions defined in tree.c. any syntax errors cause
34 * us to skip to the next semicolon, achieved via the "error" clause
35 * in the stmt rule below. the yacc state machine code will call
36 * yyerror() in esclex.c and that will keep count of the errors and
37 * display the filename, line number, and current input stream of tokens
38 * to help the user figure out the problem. the -Y flag to this program
39 * turns on the yacc debugging output which is quite large. you probably
40 * only need to do that if you're debugging the grammar below.
44 #include <stdio.h>
45 #include <ctype.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <time.h>
50 #include <sys/time.h>
51 #include "out.h"
52 #include "stable.h"
53 #include "literals.h"
54 #include "lut.h"
55 #include "esclex.h"
56 #include "tree.h"
59 %union {
60 struct tokstr tok;
61 struct node *np;
64 %right '='
67 * make sure ':' comes immediately after '?' in precedence declarations
69 %right '?'
70 %nonassoc ':'
72 %left OR
73 %left AND
74 %left '|'
75 %left '^'
76 %left '&'
77 %left EQ NE
78 %left LE GE '<' '>'
79 %left LSHIFT RSHIFT
80 %left '-' '+'
81 %left '*' '%' DIV '/'
82 %right '!' '~'
83 %left '.'
85 %token <tok> PROP MASK ARROW EVENT ENGINE ASRU FRU COUNT CONFIG
86 %token <tok> ID QUOTE NUMBER IF PATHFUNC
87 %type <tok> enameid
88 %type <np> root stmtlist stmt nvpairlist nvpair nvname nvexpr
89 %type <np> exprlist expr iterid ename pname epname eexprlist ipname iname
90 %type <np> numexpr cexpr func pfunc parglist parg
91 %type <np> eventlist event nork norkexpr globid propbody
95 root : stmtlist
96 { (void)tree_root($1); }
99 stmtlist : /*empty*/
100 { $$ = NULL; }
101 | stmtlist stmt
102 { $$ = tree_expr(T_LIST, $1, $2); }
105 stmt : error ';'
106 { $$ = tree_nothing(); }
107 | IF '(' expr ')' stmt
108 { $$ = $5; }
109 | IF '(' expr ')' '{' stmtlist '}'
110 { $$ = $6; }
111 | EVENT event nvpairlist ';'
112 { $$ = tree_decl(T_EVENT, $2, $3, $1.file, $1.line); }
113 | ENGINE event nvpairlist ';'
114 { $$ = tree_decl(T_ENGINE, $2, $3, $1.file, $1.line); }
115 | PROP propbody ';'
117 $$ = tree_stmt(T_PROP, $2, $1.file, $1.line);
119 | MASK propbody ';'
121 $$ = tree_stmt(T_MASK, $2, $1.file, $1.line);
123 | ASRU pname nvpairlist ';'
125 $$ = tree_decl(T_ASRU, $2, $3, $1.file, $1.line);
127 | FRU pname nvpairlist ';'
129 $$ = tree_decl(T_FRU, $2, $3, $1.file, $1.line);
131 | CONFIG ipname nvpairlist ';'
133 $$ = tree_decl(T_CONFIG, $2, $3, $1.file, $1.line);
135 | /*superfluous semicolons are ignored*/ ';'
136 { $$ = tree_nothing(); }
139 propbody: eventlist nork ARROW nork eventlist
141 $$ = tree_arrow($1, $2, $4, $5);
143 | propbody nork ARROW nork eventlist
145 $$ = tree_arrow($1, $2, $4, $5);
149 nork : /* empty */
150 { $$ = NULL; }
151 | '(' norkexpr ')'
152 { $$ = $2; }
155 norkexpr: NUMBER
156 { $$ = tree_num($1.s, $1.file, $1.line); }
157 | ID
158 /* really can only be 'A', enforced by check_arrow() later */
159 { $$ = tree_name($1.s, IT_NONE, $1.file, $1.line); }
160 | '(' norkexpr ')'
161 { $$ = $2; }
162 | norkexpr '-' norkexpr
163 { $$ = tree_expr(T_SUB, $1, $3); }
164 | norkexpr '+' norkexpr
165 { $$ = tree_expr(T_ADD, $1, $3); }
166 | norkexpr '*' norkexpr
167 { $$ = tree_expr(T_MUL, $1, $3); }
168 | norkexpr DIV norkexpr
169 { $$ = tree_expr(T_DIV, $1, $3); }
170 | norkexpr '%' norkexpr
171 { $$ = tree_expr(T_MOD, $1, $3); }
174 nvpairlist: /* empty */
175 { $$ = NULL; }
176 | nvpair
177 | nvpairlist ',' nvpair
178 { $$ = tree_expr(T_LIST, $1, $3); }
181 nvpair : nvname '=' nvexpr
182 { $$ = tree_expr(T_NVPAIR, $1, $3); }
183 | ENGINE '=' nvexpr
184 /* "engine" is a reserved word, but a valid property name */
186 $$ = tree_expr(T_NVPAIR,
187 tree_name($1.s, IT_NONE, $1.file, $1.line), $3);
189 | COUNT '=' nvexpr
190 /* "count" is a reserved word, but a valid property name */
192 $$ = tree_expr(T_NVPAIR,
193 tree_name($1.s, IT_NONE, $1.file, $1.line), $3);
197 nvname : ID
198 { $$ = tree_name($1.s, IT_NONE, $1.file, $1.line); }
199 | nvname '-' ID
201 /* hack to allow dashes in property names */
202 $$ = tree_name_repairdash($1, $3.s);
206 /* the RHS of an nvpair can be a value, or an ename, or an ename@pname */
207 nvexpr : numexpr
208 | ename epname
209 { $$ = tree_event($1, $2, NULL); }
210 | pname
211 | globid
212 | func
213 | NUMBER ID
215 * ID must be timevals only ("ms", "us", etc.).
216 * enforced by tree_timeval().
218 { $$ = tree_timeval($1.s, $2.s, $1.file, $1.line); }
219 | QUOTE
220 { $$ = tree_quote($1.s, $1.file, $1.line); }
223 /* arithmetic operations, no variables or symbols */
224 numexpr : numexpr '-' numexpr
225 { $$ = tree_expr(T_SUB, $1, $3); }
226 | numexpr '+' numexpr
227 { $$ = tree_expr(T_ADD, $1, $3); }
228 | numexpr '*' numexpr
229 { $$ = tree_expr(T_MUL, $1, $3); }
230 | numexpr DIV numexpr
231 { $$ = tree_expr(T_DIV, $1, $3); }
232 | numexpr '/' numexpr
233 { $$ = tree_expr(T_DIV, $1, $3); }
234 | numexpr '%' numexpr
235 { $$ = tree_expr(T_MOD, $1, $3); }
236 | '(' numexpr ')'
237 { $$ = $2; }
238 | NUMBER
239 { $$ = tree_num($1.s, $1.file, $1.line); }
242 eventlist: event
243 | eventlist ',' event
244 { $$ = tree_expr(T_LIST, $1, $3); }
247 event : ename epname eexprlist
248 { $$ = tree_event($1, $2, $3); }
251 epname : /* empty */
252 { $$ = NULL; }
253 | '@' pname
254 { $$ = $2; }
257 eexprlist: /* empty */
258 { $$ = NULL; }
259 | '{' exprlist '}'
260 { $$ = $2; }
263 exprlist: expr
264 | exprlist ',' expr
265 { $$ = tree_expr(T_LIST, $1, $3); }
269 * note that expr does not include pname, to avoid reduce/reduce
270 * conflicts between cexpr and iterid involving the use of ID
272 expr : cexpr
273 | NUMBER ID
275 * ID must be timevals only ("ms", "us", etc.).
276 * enforced by tree_timeval().
278 { $$ = tree_timeval($1.s, $2.s, $1.file, $1.line); }
281 cexpr : cexpr '=' cexpr
282 { $$ = tree_expr(T_ASSIGN, $1, $3); }
283 | cexpr '?' cexpr
284 { $$ = tree_expr(T_CONDIF, $1, $3); }
285 | cexpr ':' cexpr
286 { $$ = tree_expr(T_CONDELSE, $1, $3); }
287 | cexpr OR cexpr
288 { $$ = tree_expr(T_OR, $1, $3); }
289 | cexpr AND cexpr
290 { $$ = tree_expr(T_AND, $1, $3); }
291 | cexpr '|' cexpr
292 { $$ = tree_expr(T_BITOR, $1, $3); }
293 | cexpr '^' cexpr
294 { $$ = tree_expr(T_BITXOR, $1, $3); }
295 | cexpr '&' cexpr
296 { $$ = tree_expr(T_BITAND, $1, $3); }
297 | cexpr EQ cexpr
298 { $$ = tree_expr(T_EQ, $1, $3); }
299 | cexpr NE cexpr
300 { $$ = tree_expr(T_NE, $1, $3); }
301 | cexpr '<' cexpr
302 { $$ = tree_expr(T_LT, $1, $3); }
303 | cexpr LE cexpr
304 { $$ = tree_expr(T_LE, $1, $3); }
305 | cexpr '>' cexpr
306 { $$ = tree_expr(T_GT, $1, $3); }
307 | cexpr GE cexpr
308 { $$ = tree_expr(T_GE, $1, $3); }
309 | cexpr LSHIFT cexpr
310 { $$ = tree_expr(T_LSHIFT, $1, $3); }
311 | cexpr RSHIFT cexpr
312 { $$ = tree_expr(T_RSHIFT, $1, $3); }
313 | cexpr '-' cexpr
314 { $$ = tree_expr(T_SUB, $1, $3); }
315 | cexpr '+' cexpr
316 { $$ = tree_expr(T_ADD, $1, $3); }
317 | cexpr '*' cexpr
318 { $$ = tree_expr(T_MUL, $1, $3); }
319 | cexpr DIV cexpr
320 { $$ = tree_expr(T_DIV, $1, $3); }
321 | cexpr '/' cexpr
322 { $$ = tree_expr(T_DIV, $1, $3); }
323 | cexpr '%' cexpr
324 { $$ = tree_expr(T_MOD, $1, $3); }
325 | '!' cexpr
326 { $$ = tree_expr(T_NOT, $2, NULL); }
327 | '~' cexpr
328 { $$ = tree_expr(T_BITNOT, $2, NULL); }
329 | '(' cexpr ')'
330 { $$ = $2; }
331 | func
332 | NUMBER
333 { $$ = tree_num($1.s, $1.file, $1.line); }
334 | ID
336 /* iteration variable */
337 $$ = tree_name($1.s, IT_NONE, $1.file, $1.line);
339 | globid
340 | QUOTE
341 { $$ = tree_quote($1.s, $1.file, $1.line); }
344 func : ID '(' ')'
345 { $$ = tree_func($1.s, NULL, $1.file, $1.line); }
346 | ID '(' exprlist ')'
347 { $$ = tree_func($1.s, $3, $1.file, $1.line); }
348 | PATHFUNC '(' parglist ')'
349 { $$ = tree_func($1.s, $3, $1.file, $1.line); }
350 | pfunc
353 parglist: parg
354 | parglist ',' parg
355 { $$ = tree_expr(T_LIST, $1, $3); }
358 parg : pfunc
359 | pname
360 { $$ = tree_pname($1); }
361 | QUOTE
362 { $$ = tree_quote($1.s, $1.file, $1.line); }
363 | ID '(' exprlist ')'
364 { $$ = tree_func($1.s, $3, $1.file, $1.line); }
368 * these functions are in the grammar so we can force the arg to be
369 * a path or an event. they show up as functions in the parse tree.
371 pfunc : ASRU '(' pname ')'
372 { $$ = tree_func($1.s, tree_pname($3), $1.file, $1.line); }
373 | FRU '(' pname ')'
374 { $$ = tree_func($1.s, tree_pname($3), $1.file, $1.line); }
375 | COUNT '(' event ')'
376 { $$ = tree_func($1.s, $3, $1.file, $1.line); }
379 globid : '$' ID
380 { $$ = tree_globid($2.s, $2.file, $2.line); }
383 iterid : ID
384 { $$ = tree_name($1.s, IT_VERTICAL, $1.file, $1.line); }
385 | ID '[' ']'
386 { $$ = tree_name($1.s, IT_VERTICAL, $1.file, $1.line); }
387 | ID '[' cexpr ']'
389 $$ = tree_name_iterator(
390 tree_name($1.s, IT_VERTICAL, $1.file, $1.line), $3);
392 | ID '<' '>'
393 { $$ = tree_name($1.s, IT_HORIZONTAL, $1.file, $1.line); }
394 | ID '<' ID '>'
396 $$ = tree_name_iterator(
397 tree_name($1.s, IT_HORIZONTAL, $1.file, $1.line),
398 tree_name($3.s, IT_NONE, $3.file, $3.line));
400 | ID '-' iterid
402 /* hack to allow dashes in path name components */
403 $$ = tree_name_repairdash2($1.s, $3);
407 /* iname is an ID where we can peel numbers off the end */
408 iname : ID
409 { $$ = tree_iname($1.s, $1.file, $1.line); }
412 /* base case of ID.ID instead of just ID requires ename to contain one dot */
413 ename : ID '.' enameid
415 $$ = tree_name_append(
416 tree_name($1.s, IT_ENAME, $1.file, $1.line),
417 tree_name($3.s, IT_NONE, $3.file, $3.line));
419 | ename '.' enameid
421 $$ = tree_name_append($1,
422 tree_name($3.s, IT_NONE, $3.file, $3.line));
424 | ename '-' enameid
427 * hack to allow dashes in class names. when we
428 * detect the dash here, we know we're in a class
429 * name because the left recursion of this rule
430 * means we've already matched at least:
431 * ID '.' ID
432 * so the ename here has an incomplete final
433 * component (because the lexer stopped at the
434 * dash). so we repair that final component here.
436 $$ = tree_name_repairdash($1, $3.s);
440 /* like an ID, but we let reserved words act unreserved in enames */
441 enameid : ID
442 | PROP
443 | MASK
444 | EVENT
445 | ENGINE
446 | ASRU
447 | FRU
448 | CONFIG
449 | IF
452 /* pname is a pathname, like x/y, x<i>/y[0], etc */
453 pname : iterid
454 | pname '/' iterid
455 { $$ = tree_name_append($1, $3); }
458 /* ipname is an "instanced" pathname, like x0/y1 */
459 ipname : iname
460 | ipname '/' iname
461 { $$ = tree_name_append($1, $3); }