2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * This file is part of Jam - see jam.c for Copyright information.
7 * jamgram.yy - jam grammar
9 * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
10 * 06/01/94 (seiwald) - new 'actions existing' does existing sources
11 * 08/23/94 (seiwald) - Support for '+=' (append to variable)
12 * 08/31/94 (seiwald) - Allow ?= as alias for "default =".
13 * 09/15/94 (seiwald) - if conditionals take only single arguments, so
14 * that 'if foo == bar' gives syntax error (use =).
15 * 02/11/95 (seiwald) - when scanning arguments to rules, only treat
16 * punctuation keywords as keywords. All arg lists
17 * are terminated with punctuation keywords.
18 * 09/11/00 (seiwald) - Support for function calls; rules return LIST *.
19 * 01/22/01 (seiwald) - replace evaluate_if() with compile_eval()
20 * 01/24/01 (seiwald) - 'while' statement
21 * 03/23/01 (seiwald) - "[ on target rule ]" support
22 * 02/27/02 (seiwald) - un-break "expr : arg in list" syntax
23 * 03/02/02 (seiwald) - rules can be invoked via variable names
24 * 03/12/02 (seiwald) - set YYMAXDEPTH for big, right-recursive rules
25 * 02/28/02 (seiwald) - merge EXEC_xxx flags in with RULE_xxx
26 * 06/21/02 (seiwald) - support for named parameters
27 * 10/22/02 (seiwald) - working return/break/continue statements
35 %left `<` `<=` `>` `>=`
49 /* for OSF and other less endowed yaccs */
50 #define YYMAXDEPTH (10000)
52 #define F0 (LIST *(*)(PARSE *, LOL *, int *))0
56 #define pappend(l,r) parse_make(compile_append, l, r, P0, S0, S0, 0)
57 #define pbreak(l,f) parse_make(compile_break, l, P0, P0, S0, S0, f)
58 #define peval(c,l,r) parse_make(compile_eval, l, r, P0, S0, S0, c)
59 #define pfor(s,l,r) parse_make(compile_foreach, l, r, P0, s, S0, 0)
60 #define pif(l,r,t) parse_make(compile_if, l, r, t, S0, S0, 0)
61 #define pincl(l) parse_make(compile_include, l, P0, P0, S0, S0, 0)
62 #define plist(s) parse_make(compile_list, P0, P0, P0, s, S0, 0)
63 #define plocal(l,r,t) parse_make(compile_local, l, r, t, S0, S0, 0)
64 #define pnull() parse_make(compile_null, P0, P0, P0, S0, S0, 0)
65 #define pon(l,r) parse_make(compile_on, l, r, P0, S0, S0, 0)
66 #define prule(a,p) parse_make(compile_rule, a, p, P0, S0, S0, 0)
67 #define prules(l,r) parse_make(compile_rules, l, r, P0, S0, S0, 0)
68 #define pset(l,r,a) parse_make(compile_set, l, r, P0, S0, S0, a)
69 #define pset1(l,r,t,a) parse_make(compile_settings, l, r, t, S0, S0, a)
70 #define psetc(s,l,r) parse_make(compile_setcomp, l, r, P0, s, S0, 0)
71 #define psete(s,l,s1,f) parse_make(compile_setexec, l, P0, P0, s, s1, f)
72 #define pswitch(l,r) parse_make(compile_switch, l, r, P0, S0, S0, 0)
73 #define pwhile(l,r) parse_make(compile_while, l, r, P0, S0, S0, 0)
75 #define pnode(l,r) parse_make(F0, l, r, P0, S0, S0, 0)
76 #define psnode(s,l) parse_make(F0, l, P0, P0, s, S0, 0)
83 : /* empty */ /* do nothing */
84 | rules { parse_save($1.parse); }
89 * block - zero or more rules
90 * rules - one or more rules
91 * rule - any one of jam's rules
92 * right-recursive so rules execute in order.
95 : /* empty */ { $$.parse = pnull(); }
96 | rules { $$.parse = $1.parse; }
100 : rule { $$.parse = $1.parse; }
101 | rule rules { $$.parse = prules($1.parse, $2.parse); }
102 | `local` list `;` block { $$.parse = plocal($2.parse, pnull(), $4.parse); }
103 | `local` list `=` list `;` block { $$.parse = plocal($2.parse, $4.parse, $6.parse); }
107 : `{` block `}` { $$.parse = $2.parse; }
108 | `include` list `;` { $$.parse = pincl($2.parse); }
109 | arg lol `;` { $$.parse = prule($1.parse, $2.parse); }
110 | arg assign list `;` { $$.parse = pset($1.parse, $3.parse, $2.number); }
111 | arg `on` list assign list `;` { $$.parse = pset1($1.parse, $3.parse, $5.parse, $4.number); }
112 | `break` list `;` { $$.parse = pbreak($2.parse, JMP_BREAK); }
113 | `continue` list `;` { $$.parse = pbreak($2.parse, JMP_CONTINUE); }
114 | `return` list `;` { $$.parse = pbreak($2.parse, JMP_RETURN); }
115 | `for` ARG `in` list `{` block `}` { $$.parse = pfor($2.string, $4.parse, $6.parse); }
116 | `switch` list `{` cases `}` { $$.parse = pswitch($2.parse, $4.parse); }
117 | `if` expr `{` block `}` { $$.parse = pif($2.parse, $4.parse, pnull()); }
118 | `if` expr `{` block `}` `else` rule { $$.parse = pif($2.parse, $4.parse, $7.parse); }
119 | `while` expr `{` block `}` { $$.parse = pwhile($2.parse, $4.parse); }
120 | `rule` ARG params `{` block `}` { $$.parse = psetc($2.string, $3.parse, $5.parse); }
121 | `on` arg rule { $$.parse = pon($2.parse, $3.parse); }
122 | `actions` eflags ARG bindlist `{` { yymode(SCAN_STRING); } STRING { yymode(SCAN_NORMAL); } `}`
123 { $$.parse = psete($3.string, $4.parse, $7.string, $2.number); }
128 * assign - =, +=, ?=, -=
131 : `=` { $$.number = VAR_SET; }
132 | `+=` { $$.number = VAR_APPEND; }
133 | `-=` { $$.number = VAR_REMOVE; }
134 | `?=` { $$.number = VAR_DEFAULT; }
135 | `default` `=` { $$.number = VAR_DEFAULT; }
140 * expr - an expression for if
143 : arg { $$.parse = peval(EXPR_EXISTS, $1.parse, pnull()); }
144 | expr `=` expr { $$.parse = peval(EXPR_EQUALS, $1.parse, $3.parse); }
145 | expr `!=` expr { $$.parse = peval(EXPR_NOTEQ, $1.parse, $3.parse); }
146 | expr `<` expr { $$.parse = peval(EXPR_LESS, $1.parse, $3.parse); }
147 | expr `<=` expr { $$.parse = peval(EXPR_LESSEQ, $1.parse, $3.parse); }
148 | expr `>` expr { $$.parse = peval(EXPR_MORE, $1.parse, $3.parse); }
149 | expr `>=` expr { $$.parse = peval(EXPR_MOREEQ, $1.parse, $3.parse); }
150 | expr `&` expr { $$.parse = peval(EXPR_AND, $1.parse, $3.parse); }
151 | expr `&&` expr { $$.parse = peval(EXPR_AND, $1.parse, $3.parse); }
152 | expr `|` expr { $$.parse = peval(EXPR_OR, $1.parse, $3.parse); }
153 | expr `||` expr { $$.parse = peval(EXPR_OR, $1.parse, $3.parse); }
154 | arg `in` list { $$.parse = peval(EXPR_IN, $1.parse, $3.parse); }
155 | `!` expr { $$.parse = peval(EXPR_NOT, $2.parse, pnull()); }
156 | `(` expr `)` { $$.parse = $2.parse; }
161 * cases - action elements inside a 'switch'
162 * case - a single action element inside a 'switch'
163 * right-recursive rule so cases can be examined in order.
166 : /* empty */ { $$.parse = P0; }
167 | case cases { $$.parse = pnode($1.parse, $2.parse); }
171 : `case` ARG `:` block { $$.parse = psnode($2.string, $4.parse); }
176 * params - optional parameter names to rule definition
177 * right-recursive rule so that params can be added in order.
180 : /* empty */ { $$.parse = P0; }
181 | ARG `:` params { $$.parse = psnode($1.string, $3.parse); }
182 | ARG { $$.parse = psnode($1.string, P0); }
187 * lol - list of lists
188 * right-recursive rule so that lists can be added in order.
191 : list { $$.parse = pnode(P0, $1.parse); }
192 | list `:` lol { $$.parse = pnode($3.parse, $1.parse); }
197 * list - zero or more args in a LIST
198 * listp - list (in puncutation only mode)
199 * arg - one ARG or function call
202 : listp { $$.parse = $1.parse; yymode(SCAN_NORMAL); }
206 : /* empty */ { $$.parse = pnull(); yymode(SCAN_PUNCT); }
207 | listp arg { $$.parse = pappend($1.parse, $2.parse); }
211 : ARG { $$.parse = plist($1.string); }
212 | `[` { yymode(SCAN_NORMAL); } func `]` { $$.parse = $3.parse; }
217 * func - a function call (inside [])
218 * This needs to be split cleanly out of 'rule'
221 : arg lol { $$.parse = prule($1.parse, $2.parse); }
222 | `on` arg arg lol { $$.parse = pon($2.parse, prule($3.parse, $4.parse)); }
223 | `on` arg `return` list { $$.parse = pon($2.parse, $4.parse); }
228 * eflags - zero or more modifiers to 'executes'
229 * eflag - a single modifier to 'executes'
232 : /* empty */ { $$.number = 0; }
233 | eflags eflag { $$.number = $1.number | $2.number; }
237 : `updated` { $$.number = RULE_UPDATED; }
238 | `together` { $$.number = RULE_TOGETHER; }
239 | `ignore` { $$.number = RULE_IGNORE; }
240 | `quietly` { $$.number = RULE_QUIETLY; }
241 | `piecemeal` { $$.number = RULE_PIECEMEAL; }
242 | `existing` { $$.number = RULE_EXISTING; }
243 | `maxline` ARG { $$.number = atoi($2.string)*RULE_MAXLINE; }
248 * bindlist - list of variable to bind for an action
251 : /* empty */ { $$.parse = pnull(); }
252 | `bind` list { $$.parse = $2.parse; }