jam0 use passed cflags
[platform/upstream/boost-jam.git] / jamgram.yy
1 /*
2  * Copyright 1993, 2000 Christopher Seiwald.
3  *
4  * This file is part of Jam - see jam.c for Copyright information.
5  */
6
7 /*  This file is ALSO:
8  *  Copyright 2001-2004 David Abrahams.
9  *  Distributed under the Boost Software License, Version 1.0.
10  *  (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
11  */
12
13 /*
14  * jamgram.yy - jam grammar
15  *
16  * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
17  * 06/01/94 (seiwald) - new 'actions existing' does existing sources
18  * 08/23/94 (seiwald) - Support for '+=' (append to variable)
19  * 08/31/94 (seiwald) - Allow ?= as alias for "default =".
20  * 09/15/94 (seiwald) - if conditionals take only single arguments, so
21  *                      that 'if foo == bar' gives syntax error (use =).
22  * 02/11/95 (seiwald) - when scanning arguments to rules, only treat
23  *                      punctuation keywords as keywords.  All arg lists
24  *                      are terminated with punctuation keywords.
25  *
26  * 09/11/00 (seiwald) - Support for function calls:
27  *
28  *              Rules now return lists (LIST *), rather than void.
29  *
30  *              New "[ rule ]" syntax evals rule into a LIST.
31  *
32  *              Lists are now generated by compile_list() and
33  *              compile_append(), and any other rule that indirectly
34  *              makes a list, rather than being built directly here,
35  *              so that lists values can contain rule evaluations.
36  *
37  *              New 'return' rule sets the return value, though
38  *              other statements also may have return values.
39  *
40  *              'run' production split from 'block' production so
41  *              that empty blocks can be handled separately.
42  */
43
44 %token ARG STRING
45
46 %left `||` `|`
47 %left `&&` `&`
48 %left `=` `!=` `in`
49 %left `<` `<=` `>` `>=`
50 %left `!`
51
52 %{
53 #include "jam.h"
54
55 #include "lists.h"
56 #include "parse.h"
57 #include "scan.h"
58 #include "compile.h"
59 #include "newstr.h"
60 #include "rules.h"
61
62 # define YYMAXDEPTH 10000       /* for OSF and other less endowed yaccs */
63
64 # define F0 (LIST *(*)(PARSE *, FRAME *))0
65 # define P0 (PARSE *)0
66 # define S0 (char *)0
67
68 # define pappend( l,r )         parse_make( compile_append,l,r,P0,S0,S0,0 )
69 # define peval( c,l,r ) parse_make( compile_eval,l,r,P0,S0,S0,c )
70 # define pfor( s,l,r,x )        parse_make( compile_foreach,l,r,P0,s,S0,x )
71 # define pif( l,r,t )           parse_make( compile_if,l,r,t,S0,S0,0 )
72 # define pincl( l )             parse_make( compile_include,l,P0,P0,S0,S0,0 )
73 # define plist( s )             parse_make( compile_list,P0,P0,P0,s,S0,0 )
74 # define plocal( l,r,t )        parse_make( compile_local,l,r,t,S0,S0,0 )
75 # define pmodule( l,r )         parse_make( compile_module,l,r,P0,S0,S0,0 )
76 # define pclass( l,r )          parse_make( compile_class,l,r,P0,S0,S0,0 )
77 # define pnull()                parse_make( compile_null,P0,P0,P0,S0,S0,0 )
78 # define pon( l,r )             parse_make( compile_on,l,r,P0,S0,S0,0 )
79 # define prule( s,p )           parse_make( compile_rule,p,P0,P0,s,S0,0 )
80 # define prules( l,r )          parse_make( compile_rules,l,r,P0,S0,S0,0 )
81 # define pset( l,r,a )          parse_make( compile_set,l,r,P0,S0,S0,a )
82 # define pset1( l,r,t,a )       parse_make( compile_settings,l,r,t,S0,S0,a )
83 # define psetc( s,p,a,l )       parse_make( compile_setcomp,p,a,P0,s,S0,l )
84 # define psete( s,l,s1,f )      parse_make( compile_setexec,l,P0,P0,s,s1,f )
85 # define pswitch( l,r )         parse_make( compile_switch,l,r,P0,S0,S0,0 )
86 # define pwhile( l,r )          parse_make( compile_while,l,r,P0,S0,S0,0 )
87
88 # define pnode( l,r )           parse_make( F0,l,r,P0,S0,S0,0 )
89 # define psnode( s,l )          parse_make( F0,l,P0,P0,s,S0,0 )
90
91 %}
92
93 %%
94
95 run     : /* empty */
96                 /* do nothing */
97         | rules
98                 { parse_save( $1.parse ); }
99         ;
100
101 /*
102  * block - zero or more rules
103  * rules - one or more rules
104  * rule - any one of jam's rules
105  * right-recursive so rules execute in order.
106  */
107
108 block   : null
109                 { $$.parse = $1.parse; }
110         | rules
111                 { $$.parse = $1.parse; }
112         ;
113
114 rules   : rule
115                 { $$.parse = $1.parse; }
116         | rule rules
117                 { $$.parse = prules( $1.parse, $2.parse ); }
118         | `local` list assign_list_opt `;` block
119                 { $$.parse = plocal( $2.parse, $3.parse, $5.parse ); }
120         ;
121
122 null    : /* empty */
123         { $$.parse = pnull(); }
124         ;
125
126 assign_list_opt : `=` list
127                 { $$.parse = $2.parse; $$.number = ASSIGN_SET; }
128         | null
129                 { $$.parse = $1.parse; $$.number = ASSIGN_APPEND; }
130         ;
131
132 arglist_opt : `(` lol `)`
133                 { $$.parse = $2.parse; }
134         |
135                 { $$.parse = P0; }
136         ;
137
138 local_opt : `local`
139                 { $$.number = 1; }
140           | /* empty */
141                 { $$.number = 0; }
142           ;
143
144 rule    : `{` block `}`
145                 { $$.parse = $2.parse; }
146         | `include` list `;`
147                 { $$.parse = pincl( $2.parse ); }
148         | ARG lol `;`
149                 { $$.parse = prule( $1.string, $2.parse ); }
150         | arg assign list `;`
151                 { $$.parse = pset( $1.parse, $3.parse, $2.number ); }
152         | arg `on` list assign list `;`
153                 { $$.parse = pset1( $1.parse, $3.parse, $5.parse, $4.number ); }
154         | `return` list `;`
155                 { $$.parse = $2.parse; }
156         | `for` local_opt ARG `in` list `{` block `}`
157                 { $$.parse = pfor( $3.string, $5.parse, $7.parse, $2.number ); }
158         | `switch` list `{` cases `}`
159                 { $$.parse = pswitch( $2.parse, $4.parse ); }
160         | `if` expr `{` block `}`
161                 { $$.parse = pif( $2.parse, $4.parse, pnull() ); }
162         | `module` list `{` block `}`
163                 { $$.parse = pmodule( $2.parse, $4.parse ); }
164         | `class` lol `{` block `}`
165                 { $$.parse = pclass( $2.parse, $4.parse ); }
166         | `while` expr `{` block `}`
167                 { $$.parse = pwhile( $2.parse, $4.parse ); }
168         | `if` expr `{` block `}` `else` rule
169                 { $$.parse = pif( $2.parse, $4.parse, $7.parse ); }
170      | local_opt `rule` ARG arglist_opt rule
171                 { $$.parse = psetc( $3.string, $5.parse, $4.parse, $1.number ); }
172         | `on` arg rule
173                 { $$.parse = pon( $2.parse, $3.parse ); }
174         | `actions` eflags ARG bindlist `{`
175                 { yymode( SCAN_STRING ); }
176           STRING
177                 { yymode( SCAN_NORMAL ); }
178           `}`
179                 { $$.parse = psete( $3.string,$4.parse,$7.string,$2.number ); }
180         ;
181
182 /*
183  * assign - = or +=
184  */
185
186 assign  : `=`
187                 { $$.number = ASSIGN_SET; }
188         | `+=`
189                 { $$.number = ASSIGN_APPEND; }
190         | `?=`
191                 { $$.number = ASSIGN_DEFAULT; }
192         | `default` `=`
193                 { $$.number = ASSIGN_DEFAULT; }
194         ;
195
196 /*
197  * expr - an expression for if
198  */
199 expr    : arg
200                 { $$.parse = peval( EXPR_EXISTS, $1.parse, pnull() ); }
201         | expr `=` expr
202                 { $$.parse = peval( EXPR_EQUALS, $1.parse, $3.parse ); }
203         | expr `!=` expr
204                 { $$.parse = peval( EXPR_NOTEQ, $1.parse, $3.parse ); }
205         | expr `<` expr
206                 { $$.parse = peval( EXPR_LESS, $1.parse, $3.parse ); }
207         | expr `<=` expr
208                 { $$.parse = peval( EXPR_LESSEQ, $1.parse, $3.parse ); }
209         | expr `>` expr
210                 { $$.parse = peval( EXPR_MORE, $1.parse, $3.parse ); }
211         | expr `>=` expr
212                 { $$.parse = peval( EXPR_MOREEQ, $1.parse, $3.parse ); }
213         | expr `&` expr
214                 { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
215         | expr `&&` expr
216                 { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
217         | expr `|` expr
218                 { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
219         | expr `||` expr
220                 { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
221         | arg `in` list
222                 { $$.parse = peval( EXPR_IN, $1.parse, $3.parse ); }
223         | `!` expr
224                 { $$.parse = peval( EXPR_NOT, $2.parse, pnull() ); }
225         | `(` expr `)`
226                 { $$.parse = $2.parse; }
227         ;
228
229
230 /*
231  * cases - action elements inside a 'switch'
232  * case - a single action element inside a 'switch'
233  * right-recursive rule so cases can be examined in order.
234  */
235
236 cases   : /* empty */
237                 { $$.parse = P0; }
238         | case cases
239                 { $$.parse = pnode( $1.parse, $2.parse ); }
240         ;
241
242 case    : `case` ARG `:` block
243                 { $$.parse = psnode( $2.string, $4.parse ); }
244         ;
245
246 /*
247  * lol - list of lists
248  * right-recursive rule so that lists can be added in order.
249  */
250
251 lol     : list
252                 { $$.parse = pnode( P0, $1.parse ); }
253         | list `:` lol
254                 { $$.parse = pnode( $3.parse, $1.parse ); }
255         ;
256
257 /*
258  * list - zero or more args in a LIST
259  * listp - list (in puncutation only mode)
260  * arg - one ARG or function call
261  */
262
263 list    : listp
264                 { $$.parse = $1.parse; yymode( SCAN_NORMAL ); }
265         ;
266
267 listp   : /* empty */
268                 { $$.parse = pnull(); yymode( SCAN_PUNCT ); }
269         | listp arg
270                 { $$.parse = pappend( $1.parse, $2.parse ); }
271         ;
272
273 arg     : ARG
274                 { $$.parse = plist( $1.string ); }
275         | `[` { yymode( SCAN_NORMAL ); } func `]`
276                 { $$.parse = $3.parse; }
277         ;
278
279 /*
280  * func - a function call (inside [])
281  * This needs to be split cleanly out of 'rule'
282  */
283
284 func    : arg lol
285                 { $$.parse = prule( $1.string, $2.parse ); }
286         | `on` arg arg lol
287                 { $$.parse = pon( $2.parse, prule( $3.string, $4.parse ) ); }
288         | `on` arg `return` list
289                 { $$.parse = pon( $2.parse, $4.parse ); }
290         ;
291
292
293 /*
294  * eflags - zero or more modifiers to 'executes'
295  * eflag - a single modifier to 'executes'
296  */
297
298 eflags  : /* empty */
299                 { $$.number = 0; }
300         | eflags eflag
301                 { $$.number = $1.number | $2.number; }
302         ;
303
304 eflag   : `updated`
305                 { $$.number = EXEC_UPDATED; }
306         | `together`
307                 { $$.number = EXEC_TOGETHER; }
308         | `ignore`
309                 { $$.number = EXEC_IGNORE; }
310         | `quietly`
311                 { $$.number = EXEC_QUIETLY; }
312         | `piecemeal`
313                 { $$.number = EXEC_PIECEMEAL; }
314         | `existing`
315                 { $$.number = EXEC_EXISTING; }
316         ;
317
318
319 /*
320  * bindlist - list of variable to bind for an action
321  */
322
323 bindlist : /* empty */
324                 { $$.parse = pnull(); }
325         | `bind` list
326                 { $$.parse = $2.parse; }
327         ;
328
329