added valid install target to Jamfile
[k8jam.git] / jamgram.yy
blob0a9aa1e7dd41fd1af9d0d5253454b16955d3a265
1 /*
2  * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
3  *
4  * This file is part of Jam - see jam.c for Copyright information.
5  */
7 /*
8  * jamgram.yy - jam grammar
9  *
10  * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
11  * 06/01/94 (seiwald) - new 'actions existing' does existing sources
12  * 08/23/94 (seiwald) - Support for '+=' (append to variable)
13  * 08/31/94 (seiwald) - Allow ?= as alias for "default =".
14  * 09/15/94 (seiwald) - if conditionals take only single arguments, so
15  *                      that 'if foo == bar' gives syntax error (use =).
16  * 02/11/95 (seiwald) - when scanning arguments to rules, only treat
17  *                      punctuation keywords as keywords.  All arg lists
18  *                      are terminated with punctuation keywords.
19  * 09/11/00 (seiwald) - Support for function calls; rules return LIST *.
20  * 01/22/01 (seiwald) - replace evaluate_if() with compile_eval()
21  * 01/24/01 (seiwald) - 'while' statement
22  * 03/23/01 (seiwald) - "[ on target rule ]" support 
23  * 02/27/02 (seiwald) - un-break "expr : arg in list" syntax
24  * 03/02/02 (seiwald) - rules can be invoked via variable names
25  * 03/12/02 (seiwald) - set YYMAXDEPTH for big, right-recursive rules
26  * 02/28/02 (seiwald) - merge EXEC_xxx flags in with RULE_xxx 
27  * 06/21/02 (seiwald) - support for named parameters
28  * 10/22/02 (seiwald) - working return/break/continue statements
29  */
31 %token ARG STRING
33 %left `||` `|`
34 %left `&&` `&`
35 %left `=` `!=` `in`
36 %left `<` `<=` `>` `>=`
37 %left `!`
40 #include "jam.h"
42 #include "lists.h"
43 #include "variable.h"
44 #include "parse.h"
45 #include "scan.h"
46 #include "compile.h"
47 #include "newstr.h"
48 #include "rules.h"
50 # define YYMAXDEPTH 10000       /* for OSF and other less endowed yaccs */
52 # define F0 (LIST *(*)(PARSE *, LOL *, int *))0
53 # define P0 (PARSE *)0
54 # define S0 (char *)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 )
82 run     : /* empty */
83                 /* do nothing */
84         | rules
85                 { parse_save( $1.parse ); }
86         ;
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.
93  */
95 block   : /* empty */
96                 { $$.parse = pnull(); }
97         | rules
98                 { $$.parse = $1.parse; }
99         ;
101 rules   : rule
102                 { $$.parse = $1.parse; }
103         | rule rules
104                 { $$.parse = prules( $1.parse, $2.parse ); }
105         | `local` list `;` block
106                 { $$.parse = plocal( $2.parse, pnull(), $4.parse ); }
107         | `local` list `=` list `;` block
108                 { $$.parse = plocal( $2.parse, $4.parse, $6.parse ); }
109         ;
111 rule    : `{` block `}`
112                 { $$.parse = $2.parse; }
113         | `include` list `;`
114                 { $$.parse = pincl( $2.parse ); }
115         | arg lol `;`
116                 { $$.parse = prule( $1.parse, $2.parse ); }
117         | arg assign list `;`
118                 { $$.parse = pset( $1.parse, $3.parse, $2.number ); }
119         | arg `on` list assign list `;`
120                 { $$.parse = pset1( $1.parse, $3.parse, $5.parse, $4.number ); }
121         | `break` list `;`
122                 { $$.parse = pbreak( $2.parse, JMP_BREAK ); }
123         | `continue` list `;`
124                 { $$.parse = pbreak( $2.parse, JMP_CONTINUE ); }
125         | `return` list `;`
126                 { $$.parse = pbreak( $2.parse, JMP_RETURN ); }
127         | `for` ARG `in` list `{` block `}`
128                 { $$.parse = pfor( $2.string, $4.parse, $6.parse ); }
129         | `switch` list `{` cases `}`
130                 { $$.parse = pswitch( $2.parse, $4.parse ); }
131         | `if` expr `{` block `}` 
132                 { $$.parse = pif( $2.parse, $4.parse, pnull() ); }
133         | `if` expr `{` block `}` `else` rule
134                 { $$.parse = pif( $2.parse, $4.parse, $7.parse ); }
135         | `while` expr `{` block `}`
136                 { $$.parse = pwhile( $2.parse, $4.parse ); }
137         | `rule` ARG params `{` block `}`
138                 { $$.parse = psetc( $2.string, $3.parse, $5.parse ); }
139         | `on` arg rule
140                 { $$.parse = pon( $2.parse, $3.parse ); }
141         | `actions` eflags ARG bindlist `{`
142                 { yymode( SCAN_STRING ); }
143           STRING 
144                 { yymode( SCAN_NORMAL ); }
145           `}`
146                 { $$.parse = psete( $3.string,$4.parse,$7.string,$2.number ); }
147         ;
150  * assign - = or +=
151  */
153 assign  : `=`
154                 { $$.number = VAR_SET; }
155         | `+=`
156                 { $$.number = VAR_APPEND; }
157         | `?=`
158                 { $$.number = VAR_DEFAULT; }
159         | `default` `=`
160                 { $$.number = VAR_DEFAULT; }
161         ;
164  * expr - an expression for if
165  */
167 expr    : arg 
168                 { $$.parse = peval( EXPR_EXISTS, $1.parse, pnull() ); }
169         | expr `=` expr 
170                 { $$.parse = peval( EXPR_EQUALS, $1.parse, $3.parse ); }
171         | expr `!=` expr
172                 { $$.parse = peval( EXPR_NOTEQ, $1.parse, $3.parse ); }
173         | expr `<` expr
174                 { $$.parse = peval( EXPR_LESS, $1.parse, $3.parse ); }
175         | expr `<=` expr 
176                 { $$.parse = peval( EXPR_LESSEQ, $1.parse, $3.parse ); }
177         | expr `>` expr 
178                 { $$.parse = peval( EXPR_MORE, $1.parse, $3.parse ); }
179         | expr `>=` expr 
180                 { $$.parse = peval( EXPR_MOREEQ, $1.parse, $3.parse ); }
181         | expr `&` expr 
182                 { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
183         | expr `&&` expr 
184                 { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
185         | expr `|` expr
186                 { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
187         | expr `||` expr
188                 { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
189         | arg `in` list
190                 { $$.parse = peval( EXPR_IN, $1.parse, $3.parse ); }
191         | `!` expr
192                 { $$.parse = peval( EXPR_NOT, $2.parse, pnull() ); }
193         | `(` expr `)`
194                 { $$.parse = $2.parse; }
195         ;
198  * cases - action elements inside a 'switch'
199  * case - a single action element inside a 'switch'
200  * right-recursive rule so cases can be examined in order.
201  */
203 cases   : /* empty */
204                 { $$.parse = P0; }
205         | case cases
206                 { $$.parse = pnode( $1.parse, $2.parse ); }
207         ;
209 case    : `case` ARG `:` block
210                 { $$.parse = psnode( $2.string, $4.parse ); }
211         ;
214  * params - optional parameter names to rule definition
215  * right-recursive rule so that params can be added in order.
216  */
218 params  : /* empty */
219                 { $$.parse = P0; }
220         | ARG `:` params
221                 { $$.parse = psnode( $1.string, $3.parse ); }
222         | ARG
223                 { $$.parse = psnode( $1.string, P0 ); }
224         ;
227  * lol - list of lists
228  * right-recursive rule so that lists can be added in order.
229  */
231 lol     : list
232                 { $$.parse = pnode( P0, $1.parse ); }
233         | list `:` lol
234                 { $$.parse = pnode( $3.parse, $1.parse ); }
235         ;
238  * list - zero or more args in a LIST
239  * listp - list (in puncutation only mode)
240  * arg - one ARG or function call
241  */
243 list    : listp
244                 { $$.parse = $1.parse; yymode( SCAN_NORMAL ); }
245         ;
247 listp   : /* empty */
248                 { $$.parse = pnull(); yymode( SCAN_PUNCT ); }
249         | listp arg
250                 { $$.parse = pappend( $1.parse, $2.parse ); }
251         ;
253 arg     : ARG 
254                 { $$.parse = plist( $1.string ); }
255         | `[` { yymode( SCAN_NORMAL ); } func `]`
256                 { $$.parse = $3.parse; }
257         ;
260  * func - a function call (inside [])
261  * This needs to be split cleanly out of 'rule'
262  */
264 func    : arg lol
265                 { $$.parse = prule( $1.parse, $2.parse ); }
266         | `on` arg arg lol
267                 { $$.parse = pon( $2.parse, prule( $3.parse, $4.parse ) ); }
268         | `on` arg `return` list 
269                 { $$.parse = pon( $2.parse, $4.parse ); }
270         ;
273  * eflags - zero or more modifiers to 'executes'
274  * eflag - a single modifier to 'executes'
275  */
277 eflags  : /* empty */
278                 { $$.number = 0; }
279         | eflags eflag
280                 { $$.number = $1.number | $2.number; }
281         ;
283 eflag   : `updated`
284                 { $$.number = RULE_UPDATED; }
285         | `together`
286                 { $$.number = RULE_TOGETHER; }
287         | `ignore`
288                 { $$.number = RULE_IGNORE; }
289         | `quietly`
290                 { $$.number = RULE_QUIETLY; }
291         | `piecemeal`
292                 { $$.number = RULE_PIECEMEAL; }
293         | `existing`
294                 { $$.number = RULE_EXISTING; }
295         | `maxline` ARG
296                 { $$.number = atoi( $2.string ) * RULE_MAXLINE; }
297         ;
301  * bindlist - list of variable to bind for an action
302  */
304 bindlist : /* empty */
305                 { $$.parse = pnull(); }
306         | `bind` list
307                 { $$.parse = $2.parse; }
308         ;