]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 "object.h" | |
60 | #include "rules.h" | |
61 | ||
62 | # define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */ | |
63 | ||
64 | # define F0 -1 | |
65 | # define P0 (PARSE *)0 | |
66 | # define S0 (OBJECT *)0 | |
67 | ||
68 | # define pappend( l,r ) parse_make( PARSE_APPEND,l,r,P0,S0,S0,0 ) | |
69 | # define peval( c,l,r ) parse_make( PARSE_EVAL,l,r,P0,S0,S0,c ) | |
70 | # define pfor( s,l,r,x ) parse_make( PARSE_FOREACH,l,r,P0,s,S0,x ) | |
71 | # define pif( l,r,t ) parse_make( PARSE_IF,l,r,t,S0,S0,0 ) | |
72 | # define pincl( l ) parse_make( PARSE_INCLUDE,l,P0,P0,S0,S0,0 ) | |
73 | # define plist( s ) parse_make( PARSE_LIST,P0,P0,P0,s,S0,0 ) | |
74 | # define plocal( l,r,t ) parse_make( PARSE_LOCAL,l,r,t,S0,S0,0 ) | |
75 | # define pmodule( l,r ) parse_make( PARSE_MODULE,l,r,P0,S0,S0,0 ) | |
76 | # define pclass( l,r ) parse_make( PARSE_CLASS,l,r,P0,S0,S0,0 ) | |
77 | # define pnull() parse_make( PARSE_NULL,P0,P0,P0,S0,S0,0 ) | |
78 | # define pon( l,r ) parse_make( PARSE_ON,l,r,P0,S0,S0,0 ) | |
79 | # define prule( s,p ) parse_make( PARSE_RULE,p,P0,P0,s,S0,0 ) | |
80 | # define prules( l,r ) parse_make( PARSE_RULES,l,r,P0,S0,S0,0 ) | |
81 | # define pset( l,r,a ) parse_make( PARSE_SET,l,r,P0,S0,S0,a ) | |
82 | # define pset1( l,r,t,a ) parse_make( PARSE_SETTINGS,l,r,t,S0,S0,a ) | |
83 | # define psetc( s,p,a,l ) parse_make( PARSE_SETCOMP,p,a,P0,s,S0,l ) | |
84 | # define psete( s,l,s1,f ) parse_make( PARSE_SETEXEC,l,P0,P0,s,s1,f ) | |
85 | # define pswitch( l,r ) parse_make( PARSE_SWITCH,l,r,P0,S0,S0,0 ) | |
86 | # define pwhile( l,r ) parse_make( PARSE_WHILE,l,r,P0,S0,S0,0 ) | |
87 | # define preturn( l ) parse_make( PARSE_RETURN,l,P0,P0,S0,S0,0 ) | |
88 | # define pbreak() parse_make( PARSE_BREAK,P0,P0,P0,S0,S0,0 ) | |
89 | # define pcontinue() parse_make( PARSE_CONTINUE,P0,P0,P0,S0,S0,0 ) | |
90 | ||
91 | # define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 ) | |
92 | # define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 ) | |
93 | ||
94 | %} | |
95 | ||
96 | %% | |
97 | ||
98 | run : /* empty */ | |
99 | /* do nothing */ | |
100 | | rules | |
101 | { parse_save( $1.parse ); } | |
102 | ; | |
103 | ||
104 | /* | |
105 | * block - zero or more rules | |
106 | * rules - one or more rules | |
107 | * rule - any one of jam's rules | |
108 | * right-recursive so rules execute in order. | |
109 | */ | |
110 | ||
111 | block : null | |
112 | { $$.parse = $1.parse; } | |
113 | | rules | |
114 | { $$.parse = $1.parse; } | |
115 | ; | |
116 | ||
117 | rules : rule | |
118 | { $$.parse = $1.parse; } | |
119 | | rule rules | |
120 | { $$.parse = prules( $1.parse, $2.parse ); } | |
121 | | `local` list assign_list_opt `;` block | |
122 | { $$.parse = plocal( $2.parse, $3.parse, $5.parse ); } | |
123 | ; | |
124 | ||
125 | null : /* empty */ | |
126 | { $$.parse = pnull(); } | |
127 | ; | |
128 | ||
129 | assign_list_opt : `=` list | |
130 | { $$.parse = $2.parse; $$.number = ASSIGN_SET; } | |
131 | | null | |
132 | { $$.parse = $1.parse; $$.number = ASSIGN_APPEND; } | |
133 | ; | |
134 | ||
135 | arglist_opt : `(` lol `)` | |
136 | { $$.parse = $2.parse; } | |
137 | | | |
138 | { $$.parse = P0; } | |
139 | ; | |
140 | ||
141 | local_opt : `local` | |
142 | { $$.number = 1; } | |
143 | | /* empty */ | |
144 | { $$.number = 0; } | |
145 | ; | |
146 | ||
147 | rule : `{` block `}` | |
148 | { $$.parse = $2.parse; } | |
149 | | `include` list `;` | |
150 | { $$.parse = pincl( $2.parse ); } | |
151 | | ARG lol `;` | |
152 | { $$.parse = prule( $1.string, $2.parse ); } | |
153 | | arg assign list `;` | |
154 | { $$.parse = pset( $1.parse, $3.parse, $2.number ); } | |
155 | | arg `on` list assign list `;` | |
156 | { $$.parse = pset1( $1.parse, $3.parse, $5.parse, $4.number ); } | |
157 | | `return` list `;` | |
158 | { $$.parse = preturn( $2.parse ); } | |
159 | | `break` `;` | |
160 | { $$.parse = pbreak(); } | |
161 | | `continue` `;` | |
162 | { $$.parse = pcontinue(); } | |
163 | | `for` local_opt ARG `in` list `{` block `}` | |
164 | { $$.parse = pfor( $3.string, $5.parse, $7.parse, $2.number ); } | |
165 | | `switch` list `{` cases `}` | |
166 | { $$.parse = pswitch( $2.parse, $4.parse ); } | |
167 | | `if` expr `{` block `}` | |
168 | { $$.parse = pif( $2.parse, $4.parse, pnull() ); } | |
169 | | `module` list `{` block `}` | |
170 | { $$.parse = pmodule( $2.parse, $4.parse ); } | |
171 | | `class` lol `{` block `}` | |
172 | { $$.parse = pclass( $2.parse, $4.parse ); } | |
173 | | `while` expr `{` block `}` | |
174 | { $$.parse = pwhile( $2.parse, $4.parse ); } | |
175 | | `if` expr `{` block `}` `else` rule | |
176 | { $$.parse = pif( $2.parse, $4.parse, $7.parse ); } | |
177 | | local_opt `rule` ARG arglist_opt rule | |
178 | { $$.parse = psetc( $3.string, $5.parse, $4.parse, $1.number ); } | |
179 | | `on` arg rule | |
180 | { $$.parse = pon( $2.parse, $3.parse ); } | |
181 | | `actions` eflags ARG bindlist `{` | |
182 | { yymode( SCAN_STRING ); } | |
183 | STRING | |
184 | { yymode( SCAN_NORMAL ); } | |
185 | `}` | |
186 | { $$.parse = psete( $3.string,$4.parse,$7.string,$2.number ); } | |
187 | ; | |
188 | ||
189 | /* | |
190 | * assign - = or += | |
191 | */ | |
192 | ||
193 | assign : `=` | |
194 | { $$.number = ASSIGN_SET; } | |
195 | | `+=` | |
196 | { $$.number = ASSIGN_APPEND; } | |
197 | | `?=` | |
198 | { $$.number = ASSIGN_DEFAULT; } | |
199 | | `default` `=` | |
200 | { $$.number = ASSIGN_DEFAULT; } | |
201 | ; | |
202 | ||
203 | /* | |
204 | * expr - an expression for if | |
205 | */ | |
206 | expr : arg | |
207 | { $$.parse = peval( EXPR_EXISTS, $1.parse, pnull() ); } | |
208 | | expr `=` expr | |
209 | { $$.parse = peval( EXPR_EQUALS, $1.parse, $3.parse ); } | |
210 | | expr `!=` expr | |
211 | { $$.parse = peval( EXPR_NOTEQ, $1.parse, $3.parse ); } | |
212 | | expr `<` expr | |
213 | { $$.parse = peval( EXPR_LESS, $1.parse, $3.parse ); } | |
214 | | expr `<=` expr | |
215 | { $$.parse = peval( EXPR_LESSEQ, $1.parse, $3.parse ); } | |
216 | | expr `>` expr | |
217 | { $$.parse = peval( EXPR_MORE, $1.parse, $3.parse ); } | |
218 | | expr `>=` expr | |
219 | { $$.parse = peval( EXPR_MOREEQ, $1.parse, $3.parse ); } | |
220 | | expr `&` expr | |
221 | { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); } | |
222 | | expr `&&` expr | |
223 | { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); } | |
224 | | expr `|` expr | |
225 | { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); } | |
226 | | expr `||` expr | |
227 | { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); } | |
228 | | arg `in` list | |
229 | { $$.parse = peval( EXPR_IN, $1.parse, $3.parse ); } | |
230 | | `!` expr | |
231 | { $$.parse = peval( EXPR_NOT, $2.parse, pnull() ); } | |
232 | | `(` expr `)` | |
233 | { $$.parse = $2.parse; } | |
234 | ; | |
235 | ||
236 | ||
237 | /* | |
238 | * cases - action elements inside a 'switch' | |
239 | * case - a single action element inside a 'switch' | |
240 | * right-recursive rule so cases can be examined in order. | |
241 | */ | |
242 | ||
243 | cases : /* empty */ | |
244 | { $$.parse = P0; } | |
245 | | case cases | |
246 | { $$.parse = pnode( $1.parse, $2.parse ); } | |
247 | ; | |
248 | ||
249 | case : `case` ARG `:` block | |
250 | { $$.parse = psnode( $2.string, $4.parse ); } | |
251 | ; | |
252 | ||
253 | /* | |
254 | * lol - list of lists | |
255 | * right-recursive rule so that lists can be added in order. | |
256 | */ | |
257 | ||
258 | lol : list | |
259 | { $$.parse = pnode( P0, $1.parse ); } | |
260 | | list `:` lol | |
261 | { $$.parse = pnode( $3.parse, $1.parse ); } | |
262 | ; | |
263 | ||
264 | /* | |
265 | * list - zero or more args in a LIST | |
266 | * listp - list (in puncutation only mode) | |
267 | * arg - one ARG or function call | |
268 | */ | |
269 | ||
270 | list : listp | |
271 | { $$.parse = $1.parse; yymode( SCAN_NORMAL ); } | |
272 | ; | |
273 | ||
274 | listp : /* empty */ | |
275 | { $$.parse = pnull(); yymode( SCAN_PUNCT ); } | |
276 | | listp arg | |
277 | { $$.parse = pappend( $1.parse, $2.parse ); } | |
278 | ; | |
279 | ||
280 | arg : ARG | |
281 | { $$.parse = plist( $1.string ); } | |
282 | | `[` { yymode( SCAN_NORMAL ); } func `]` | |
283 | { $$.parse = $3.parse; } | |
284 | ; | |
285 | ||
286 | /* | |
287 | * func - a function call (inside []) | |
288 | * This needs to be split cleanly out of 'rule' | |
289 | */ | |
290 | ||
291 | func : ARG lol | |
292 | { $$.parse = prule( $1.string, $2.parse ); } | |
293 | | `on` arg ARG lol | |
294 | { $$.parse = pon( $2.parse, prule( $3.string, $4.parse ) ); } | |
295 | | `on` arg `return` list | |
296 | { $$.parse = pon( $2.parse, $4.parse ); } | |
297 | ; | |
298 | ||
299 | ||
300 | /* | |
301 | * eflags - zero or more modifiers to 'executes' | |
302 | * eflag - a single modifier to 'executes' | |
303 | */ | |
304 | ||
305 | eflags : /* empty */ | |
306 | { $$.number = 0; } | |
307 | | eflags eflag | |
308 | { $$.number = $1.number | $2.number; } | |
309 | ; | |
310 | ||
311 | eflag : `updated` | |
312 | { $$.number = EXEC_UPDATED; } | |
313 | | `together` | |
314 | { $$.number = EXEC_TOGETHER; } | |
315 | | `ignore` | |
316 | { $$.number = EXEC_IGNORE; } | |
317 | | `quietly` | |
318 | { $$.number = EXEC_QUIETLY; } | |
319 | | `piecemeal` | |
320 | { $$.number = EXEC_PIECEMEAL; } | |
321 | | `existing` | |
322 | { $$.number = EXEC_EXISTING; } | |
323 | ; | |
324 | ||
325 | ||
326 | /* | |
327 | * bindlist - list of variable to bind for an action | |
328 | */ | |
329 | ||
330 | bindlist : /* empty */ | |
331 | { $$.parse = pnull(); } | |
332 | | `bind` list | |
333 | { $$.parse = $2.parse; } | |
334 | ; | |
335 | ||
336 |