1 %token _BANG_t
2 %token _BANG_EQUALS_t
3 %token _AMPER_t
4 %token _AMPERAMPER_t
5 %token _LPAREN_t
6 %token _RPAREN_t
7 %token _PLUS_EQUALS_t
8 %token _COLON_t
9 %token _SEMIC_t
10 %token _LANGLE_t
11 %token _LANGLE_EQUALS_t
12 %token _EQUALS_t
13 %token _RANGLE_t
14 %token _RANGLE_EQUALS_t
15 %token _QUESTION_EQUALS_t
16 %token _LBRACKET_t
17 %token _RBRACKET_t
18 %token ACTIONS_t
19 %token BIND_t
20 %token BREAK_t
21 %token CASE_t
22 %token CLASS_t
23 %token CONTINUE_t
24 %token DEFAULT_t
25 %token ELSE_t
26 %token EXISTING_t
27 %token FOR_t
28 %token IF_t
29 %token IGNORE_t
30 %token IN_t
31 %token INCLUDE_t
32 %token LOCAL_t
33 %token MODULE_t
34 %token ON_t
35 %token PIECEMEAL_t
36 %token QUIETLY_t
37 %token RETURN_t
38 %token RULE_t
39 %token SWITCH_t
40 %token TOGETHER_t
41 %token UPDATED_t
42 %token WHILE_t
43 %token _LBRACE_t
44 %token _BAR_t
45 %token _BARBAR_t
46 %token _RBRACE_t
47 /*
48  * Copyright 1993, 2000 Christopher Seiwald.
49  *
50  * This file is part of Jam - see jam.c for Copyright information.
51  */
52 
53 /*  This file is ALSO:
54  *  Copyright 2001-2004 David Abrahams.
55  *  Distributed under the Boost Software License, Version 1.0.
56  *  (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
57  */
58 
59 /*
60  * jamgram.yy - jam grammar
61  *
62  * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
63  * 06/01/94 (seiwald) - new 'actions existing' does existing sources
64  * 08/23/94 (seiwald) - Support for '+=' (append to variable)
65  * 08/31/94 (seiwald) - Allow ?= as alias for "default =".
66  * 09/15/94 (seiwald) - if conditionals take only single arguments, so
67  *			that 'if foo == bar' gives syntax error (use =).
68  * 02/11/95 (seiwald) - when scanning arguments to rules, only treat
69  *			punctuation keywords as keywords.  All arg lists
70  *			are terminated with punctuation keywords.
71  *
72  * 09/11/00 (seiwald) - Support for function calls:
73  *
74  *		Rules now return lists (LIST *), rather than void.
75  *
76  *		New "[ rule ]" syntax evals rule into a LIST.
77  *
78  *		Lists are now generated by compile_list() and
79  *		compile_append(), and any other rule that indirectly
80  *		makes a list, rather than being built directly here,
81  *		so that lists values can contain rule evaluations.
82  *
83  *		New 'return' rule sets the return value, though
84  *		other statements also may have return values.
85  *
86  *		'run' production split from 'block' production so
87  *		that empty blocks can be handled separately.
88  */
89 
90 %token ARG STRING
91 
92 %left _BARBAR_t _BAR_t
93 %left _AMPERAMPER_t _AMPER_t
94 %left _EQUALS_t _BANG_EQUALS_t IN_t
95 %left _LANGLE_t _LANGLE_EQUALS_t _RANGLE_t _RANGLE_EQUALS_t
96 %left _BANG_t
97 
98 %{
99 #include "jam.h"
100 
101 #include "lists.h"
102 #include "parse.h"
103 #include "scan.h"
104 #include "compile.h"
105 #include "object.h"
106 #include "rules.h"
107 
108 # define YYMAXDEPTH 10000	/* for OSF and other less endowed yaccs */
109 
110 # define F0 -1
111 # define P0 (PARSE *)0
112 # define S0 (OBJECT *)0
113 
114 # define pappend( l,r )    	parse_make( PARSE_APPEND,l,r,P0,S0,S0,0 )
115 # define peval( c,l,r )	parse_make( PARSE_EVAL,l,r,P0,S0,S0,c )
116 # define pfor( s,l,r,x )    	parse_make( PARSE_FOREACH,l,r,P0,s,S0,x )
117 # define pif( l,r,t )	  	parse_make( PARSE_IF,l,r,t,S0,S0,0 )
118 # define pincl( l )       	parse_make( PARSE_INCLUDE,l,P0,P0,S0,S0,0 )
119 # define plist( s )	  	parse_make( PARSE_LIST,P0,P0,P0,s,S0,0 )
120 # define plocal( l,r,t )  	parse_make( PARSE_LOCAL,l,r,t,S0,S0,0 )
121 # define pmodule( l,r )	  	parse_make( PARSE_MODULE,l,r,P0,S0,S0,0 )
122 # define pclass( l,r )	  	parse_make( PARSE_CLASS,l,r,P0,S0,S0,0 )
123 # define pnull()	  	parse_make( PARSE_NULL,P0,P0,P0,S0,S0,0 )
124 # define pon( l,r )	  	parse_make( PARSE_ON,l,r,P0,S0,S0,0 )
125 # define prule( s,p )     	parse_make( PARSE_RULE,p,P0,P0,s,S0,0 )
126 # define prules( l,r )	  	parse_make( PARSE_RULES,l,r,P0,S0,S0,0 )
127 # define pset( l,r,a )          parse_make( PARSE_SET,l,r,P0,S0,S0,a )
128 # define pset1( l,r,t,a )	parse_make( PARSE_SETTINGS,l,r,t,S0,S0,a )
129 # define psetc( s,p,a,l )     	parse_make( PARSE_SETCOMP,p,a,P0,s,S0,l )
130 # define psete( s,l,s1,f ) 	parse_make( PARSE_SETEXEC,l,P0,P0,s,s1,f )
131 # define pswitch( l,r )   	parse_make( PARSE_SWITCH,l,r,P0,S0,S0,0 )
132 # define pwhile( l,r )   	parse_make( PARSE_WHILE,l,r,P0,S0,S0,0 )
133 # define preturn( l )       parse_make( PARSE_RETURN,l,P0,P0,S0,S0,0 )
134 # define pbreak()           parse_make( PARSE_BREAK,P0,P0,P0,S0,S0,0 )
135 # define pcontinue()        parse_make( PARSE_CONTINUE,P0,P0,P0,S0,S0,0 )
136 
137 # define pnode( l,r )    	parse_make( F0,l,r,P0,S0,S0,0 )
138 # define psnode( s,l )     	parse_make( F0,l,P0,P0,s,S0,0 )
139 
140 %}
141 
142 %%
143 
144 run	: /* empty */
145 		/* do nothing */
146 	| rules
147 		{ parse_save( $1.parse ); }
148 	;
149 
150 /*
151  * block - zero or more rules
152  * rules - one or more rules
153  * rule - any one of jam's rules
154  * right-recursive so rules execute in order.
155  */
156 
157 block	: null
158                 { $$.parse = $1.parse; }
159 	| rules
160 		{ $$.parse = $1.parse; }
161 	;
162 
163 rules	: rule
164 		{ $$.parse = $1.parse; }
165 	| rule rules
166 		{ $$.parse = prules( $1.parse, $2.parse ); }
167 	| LOCAL_t list assign_list_opt _SEMIC_t block
168 		{ $$.parse = plocal( $2.parse, $3.parse, $5.parse ); }
169 	;
170 
171 null    : /* empty */
172         { $$.parse = pnull(); }
173         ;
174 
175 assign_list_opt : _EQUALS_t list
176                 { $$.parse = $2.parse; $$.number = ASSIGN_SET; }
177         | null
178 		{ $$.parse = $1.parse; $$.number = ASSIGN_APPEND; }
179         ;
180 
181 arglist_opt : _LPAREN_t lol _RPAREN_t
182                 { $$.parse = $2.parse; }
183         |
184                 { $$.parse = P0; }
185         ;
186 
187 local_opt : LOCAL_t
188                 { $$.number = 1; }
189           | /* empty */
190                 { $$.number = 0; }
191           ;
192 
193 rule	: _LBRACE_t block _RBRACE_t
194 		{ $$.parse = $2.parse; }
195 	| INCLUDE_t list _SEMIC_t
196 		{ $$.parse = pincl( $2.parse ); }
197 	| ARG lol _SEMIC_t
198 		{ $$.parse = prule( $1.string, $2.parse ); }
199 	| arg assign list _SEMIC_t
200 		{ $$.parse = pset( $1.parse, $3.parse, $2.number ); }
201 	| arg ON_t list assign list _SEMIC_t
202 		{ $$.parse = pset1( $1.parse, $3.parse, $5.parse, $4.number ); }
203 	| RETURN_t list _SEMIC_t
204 		{ $$.parse = preturn( $2.parse ); }
205     | BREAK_t _SEMIC_t
206         { $$.parse = pbreak(); }
207     | CONTINUE_t _SEMIC_t
208         { $$.parse = pcontinue(); }
209 	| FOR_t local_opt ARG IN_t list _LBRACE_t block _RBRACE_t
210 		{ $$.parse = pfor( $3.string, $5.parse, $7.parse, $2.number ); }
211 	| SWITCH_t list _LBRACE_t cases _RBRACE_t
212 		{ $$.parse = pswitch( $2.parse, $4.parse ); }
213 	| IF_t expr _LBRACE_t block _RBRACE_t
214 		{ $$.parse = pif( $2.parse, $4.parse, pnull() ); }
215 	| MODULE_t list _LBRACE_t block _RBRACE_t
216 		{ $$.parse = pmodule( $2.parse, $4.parse ); }
217 	| CLASS_t lol _LBRACE_t block _RBRACE_t
218 		{ $$.parse = pclass( $2.parse, $4.parse ); }
219 	| WHILE_t expr _LBRACE_t block _RBRACE_t
220 		{ $$.parse = pwhile( $2.parse, $4.parse ); }
221 	| IF_t expr _LBRACE_t block _RBRACE_t ELSE_t rule
222 		{ $$.parse = pif( $2.parse, $4.parse, $7.parse ); }
223      | local_opt RULE_t ARG arglist_opt rule
224 		{ $$.parse = psetc( $3.string, $5.parse, $4.parse, $1.number ); }
225 	| ON_t arg rule
226 		{ $$.parse = pon( $2.parse, $3.parse ); }
227 	| ACTIONS_t eflags ARG bindlist _LBRACE_t
228 		{ yymode( SCAN_STRING ); }
229 	  STRING
230 		{ yymode( SCAN_NORMAL ); }
231 	  _RBRACE_t
232 		{ $$.parse = psete( $3.string,$4.parse,$7.string,$2.number ); }
233 	;
234 
235 /*
236  * assign - = or +=
237  */
238 
239 assign	: _EQUALS_t
240 		{ $$.number = ASSIGN_SET; }
241 	| _PLUS_EQUALS_t
242 		{ $$.number = ASSIGN_APPEND; }
243 	| _QUESTION_EQUALS_t
244 		{ $$.number = ASSIGN_DEFAULT; }
245 	| DEFAULT_t _EQUALS_t
246 		{ $$.number = ASSIGN_DEFAULT; }
247 	;
248 
249 /*
250  * expr - an expression for if
251  */
252 expr	: arg
253 		{ $$.parse = peval( EXPR_EXISTS, $1.parse, pnull() ); }
254 	| expr _EQUALS_t expr
255 		{ $$.parse = peval( EXPR_EQUALS, $1.parse, $3.parse ); }
256 	| expr _BANG_EQUALS_t expr
257 		{ $$.parse = peval( EXPR_NOTEQ, $1.parse, $3.parse ); }
258 	| expr _LANGLE_t expr
259 		{ $$.parse = peval( EXPR_LESS, $1.parse, $3.parse ); }
260 	| expr _LANGLE_EQUALS_t expr
261 		{ $$.parse = peval( EXPR_LESSEQ, $1.parse, $3.parse ); }
262 	| expr _RANGLE_t expr
263 		{ $$.parse = peval( EXPR_MORE, $1.parse, $3.parse ); }
264 	| expr _RANGLE_EQUALS_t expr
265 		{ $$.parse = peval( EXPR_MOREEQ, $1.parse, $3.parse ); }
266 	| expr _AMPER_t expr
267 		{ $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
268 	| expr _AMPERAMPER_t expr
269 		{ $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
270 	| expr _BAR_t expr
271 		{ $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
272 	| expr _BARBAR_t expr
273 		{ $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
274 	| arg IN_t list
275 		{ $$.parse = peval( EXPR_IN, $1.parse, $3.parse ); }
276 	| _BANG_t expr
277 		{ $$.parse = peval( EXPR_NOT, $2.parse, pnull() ); }
278 	| _LPAREN_t expr _RPAREN_t
279 		{ $$.parse = $2.parse; }
280 	;
281 
282 
283 /*
284  * cases - action elements inside a 'switch'
285  * case - a single action element inside a 'switch'
286  * right-recursive rule so cases can be examined in order.
287  */
288 
289 cases	: /* empty */
290 		{ $$.parse = P0; }
291 	| case cases
292 		{ $$.parse = pnode( $1.parse, $2.parse ); }
293 	;
294 
295 case	: CASE_t ARG _COLON_t block
296 		{ $$.parse = psnode( $2.string, $4.parse ); }
297 	;
298 
299 /*
300  * lol - list of lists
301  * right-recursive rule so that lists can be added in order.
302  */
303 
304 lol	: list
305 		{ $$.parse = pnode( P0, $1.parse ); }
306 	| list _COLON_t lol
307 		{ $$.parse = pnode( $3.parse, $1.parse ); }
308 	;
309 
310 /*
311  * list - zero or more args in a LIST
312  * listp - list (in puncutation only mode)
313  * arg - one ARG or function call
314  */
315 
316 list	: listp
317 		{ $$.parse = $1.parse; yymode( SCAN_NORMAL ); }
318 	;
319 
320 listp	: /* empty */
321 		{ $$.parse = pnull(); yymode( SCAN_PUNCT ); }
322 	| listp arg
323         	{ $$.parse = pappend( $1.parse, $2.parse ); }
324 	;
325 
326 arg	: ARG
327 		{ $$.parse = plist( $1.string ); }
328 	| _LBRACKET_t { yymode( SCAN_NORMAL ); } func _RBRACKET_t
329 		{ $$.parse = $3.parse; }
330 	;
331 
332 /*
333  * func - a function call (inside [])
334  * This needs to be split cleanly out of 'rule'
335  */
336 
337 func	: ARG lol
338 		{ $$.parse = prule( $1.string, $2.parse ); }
339 	| ON_t arg ARG lol
340 		{ $$.parse = pon( $2.parse, prule( $3.string, $4.parse ) ); }
341 	| ON_t arg RETURN_t list
342 		{ $$.parse = pon( $2.parse, $4.parse ); }
343 	;
344 
345 
346 /*
347  * eflags - zero or more modifiers to 'executes'
348  * eflag - a single modifier to 'executes'
349  */
350 
351 eflags	: /* empty */
352 		{ $$.number = 0; }
353 	| eflags eflag
354 		{ $$.number = $1.number | $2.number; }
355 	;
356 
357 eflag	: UPDATED_t
358 		{ $$.number = EXEC_UPDATED; }
359 	| TOGETHER_t
360 		{ $$.number = EXEC_TOGETHER; }
361 	| IGNORE_t
362 		{ $$.number = EXEC_IGNORE; }
363 	| QUIETLY_t
364 		{ $$.number = EXEC_QUIETLY; }
365 	| PIECEMEAL_t
366 		{ $$.number = EXEC_PIECEMEAL; }
367 	| EXISTING_t
368 		{ $$.number = EXEC_EXISTING; }
369 	;
370 
371 
372 /*
373  * bindlist - list of variable to bind for an action
374  */
375 
376 bindlist : /* empty */
377 		{ $$.parse = pnull(); }
378 	| BIND_t list
379 		{ $$.parse = $2.parse; }
380 	;
381 
382 
383