doc: documented DBG=1
[k8jam.git] / src / jamgram.yy
bloba6fc86bf72fbfa016cfba56ee343f7265d99d1cf
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  */
6 /*
7  * jamgram.yy - jam grammar
8  *
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
28  */
30 %token ARG STRING
32 %left `||` `|`
33 %left `&&` `&`
34 %left `=` `==` `!=` `in`
35 %left `<` `<=` `>` `>=`
36 %left `!`
39 #include "jam.h"
41 #include "lists.h"
42 #include "variable.h"
43 #include "parse.h"
44 #include "scan.h"
45 #include "compile.h"
46 #include "newstr.h"
47 #include "rules.h"
49 /* for OSF and other less endowed yaccs */
50 #define YYMAXDEPTH  (10000)
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 psincl(l)        parse_make(compile_softinclude, l, P0, P0, S0, S0, 0)
63 #define plist(s)         parse_make(compile_list, P0, P0, P0, s, S0, 0)
64 #define plocal(l,r,t)    parse_make(compile_local, l, r, t, S0, S0, 0)
65 #define pnull()          parse_make(compile_null, P0, P0, P0, S0, S0, 0)
66 #define pon(l,r)         parse_make(compile_on, l, r, P0, S0, S0, 0)
67 #define prule(a,p)       parse_make(compile_rule, a, p, P0, S0, S0, 0)
68 #define prules(l,r)      parse_make(compile_rules, l, r, P0, S0, S0, 0)
69 #define pset(l,r,a)      parse_make(compile_set, l, r, P0, S0, S0, a)
70 #define pset1(l,r,t,a)   parse_make(compile_settings, l, r, t, S0, S0, a)
71 #define psetc(s,l,r)     parse_make(compile_setcomp, l, r, P0, s, S0, 0)
72 #define psete(s,l,s1,f)  parse_make(compile_setexec, l, P0, P0, s, s1, f)
73 #define pswitch(l,r)     parse_make(compile_switch, l, r, P0, S0, S0, 0)
74 #define pwhile(l,r)      parse_make(compile_while, l, r, P0, S0, S0, 0)
76 #define pnode(l,r)       parse_make(F0, l, r, P0, S0, S0, 0)
77 #define psnode(s,l)      parse_make(F0, l, P0, P0, s, S0, 0)
83 run
84   : /* empty */  /* do nothing */
85   | rules        { parse_save($1.parse); }
90  * block - zero or more rules
91  * rules - one or more rules
92  * rule - any one of jam's rules
93  * right-recursive so rules execute in order.
94  */
95 block
96   : /* empty */  { $$.parse = pnull(); }
97   | rules        { $$.parse = $1.parse; }
100 rules
101   : rule                             { $$.parse = $1.parse; }
102   | rule rules                       { $$.parse = prules($1.parse, $2.parse); }
103   | `local` list `;` block           { $$.parse = plocal($2.parse, pnull(), $4.parse); }
104   | `local` list `=` list `;` block  { $$.parse = plocal($2.parse, $4.parse, $6.parse); }
107 rule
108   : `{` block `}`                        { $$.parse = $2.parse; }
109   | `include` list `;`                   { $$.parse = pincl($2.parse); }
110   | `softinclude` list `;`               { $$.parse = psincl($2.parse); }
111   | arg lol `;`                          { $$.parse = prule($1.parse, $2.parse); }
112   | arg assign list `;`                  { $$.parse = pset($1.parse, $3.parse, $2.number); }
113   | arg `on` list assign list `;`        { $$.parse = pset1($1.parse, $3.parse, $5.parse, $4.number); }
114   | `break` list `;`                     { $$.parse = pbreak($2.parse, JMP_BREAK); }
115   | `continue` list `;`                  { $$.parse = pbreak($2.parse, JMP_CONTINUE); }
116   | `return` list `;`                    { $$.parse = pbreak($2.parse, JMP_RETURN); }
117   | `for` ARG `in` list `{` block `}`    { $$.parse = pfor($2.string, $4.parse, $6.parse); }
118   | `switch` list `{` cases `}`          { $$.parse = pswitch($2.parse, $4.parse); }
119   | `if` expr `{` block `}`              { $$.parse = pif($2.parse, $4.parse, pnull()); }
120   | `if` expr `{` block `}` `else` rule  { $$.parse = pif($2.parse, $4.parse, $7.parse); }
121   | `while` expr `{` block `}`           { $$.parse = pwhile($2.parse, $4.parse); }
122   | `rule` ARG params `{` block `}`      { $$.parse = psetc($2.string, $3.parse, $5.parse); }
123   | `on` arg rule                        { $$.parse = pon($2.parse, $3.parse); }
124   | `actions` eflags ARG bindlist `{` { yymode(SCAN_STRING); } STRING { yymode(SCAN_NORMAL); } `}`
125     { $$.parse = psete($3.string, $4.parse, $7.string, $2.number); }
130  * assign - =, +=, ?=, -=
131  */
132 assign
133   : `=`            { $$.number = VAR_SET; }
134   | `+=`           { $$.number = VAR_APPEND; }
135   | `-=`           { $$.number = VAR_REMOVE; }
136   | `?=`           { $$.number = VAR_DEFAULT; }
141  * expr - an expression for if
142  */
143 expr
144   : arg             { $$.parse = peval(EXPR_EXISTS, $1.parse, pnull()); }
145   | expr `=` expr   { $$.parse = peval(EXPR_EQUALS, $1.parse, $3.parse); }
146   | expr `==` expr  { $$.parse = peval(EXPR_EQUALS, $1.parse, $3.parse); }
147   | expr `!=` expr  { $$.parse = peval(EXPR_NOTEQ, $1.parse, $3.parse); }
148   | expr `<` expr   { $$.parse = peval(EXPR_LESS, $1.parse, $3.parse); }
149   | expr `<=` expr  { $$.parse = peval(EXPR_LESSEQ, $1.parse, $3.parse); }
150   | expr `>` expr   { $$.parse = peval(EXPR_MORE, $1.parse, $3.parse); }
151   | expr `>=` expr  { $$.parse = peval(EXPR_MOREEQ, $1.parse, $3.parse); }
152   | expr `&` expr   { $$.parse = peval(EXPR_AND, $1.parse, $3.parse); }
153   | expr `&&` expr  { $$.parse = peval(EXPR_AND, $1.parse, $3.parse); }
154   | expr `|` expr   { $$.parse = peval(EXPR_OR, $1.parse, $3.parse); }
155   | expr `||` expr  { $$.parse = peval(EXPR_OR, $1.parse, $3.parse); }
156   | arg `in` list   { $$.parse = peval(EXPR_IN, $1.parse, $3.parse); }
157   | `!` expr        { $$.parse = peval(EXPR_NOT, $2.parse, pnull()); }
158   | `(` expr `)`    { $$.parse = $2.parse; }
163  * cases - action elements inside a 'switch'
164  * case - a single action element inside a 'switch'
165  * right-recursive rule so cases can be examined in order.
166  */
167 cases
168   : /* empty */  { $$.parse = P0; }
169   | case cases   { $$.parse = pnode($1.parse, $2.parse); }
172 case
173   : `case` ARG `:` block  { $$.parse = psnode($2.string, $4.parse); }
178  * params - optional parameter names to rule definition
179  * right-recursive rule so that params can be added in order.
180  */
181 params
182   : /* empty */     { $$.parse = P0; }
183   | ARG `:` params  { $$.parse = psnode($1.string, $3.parse); }
184   | ARG             { $$.parse = psnode($1.string, P0); }
189  * lol - list of lists
190  * right-recursive rule so that lists can be added in order.
191  */
193   : list          { $$.parse = pnode(P0, $1.parse); }
194   | list `:` lol  { $$.parse = pnode($3.parse, $1.parse); }
199  * list - zero or more args in a LIST
200  * listp - list (in puncutation only mode)
201  * arg - one ARG or function call
202  */
203 list
204   : listp  { $$.parse = $1.parse; yymode(SCAN_NORMAL); }
207 listp
208   : /* empty */  { $$.parse = pnull(); yymode(SCAN_PUNCT); }
209   | listp arg    { $$.parse = pappend($1.parse, $2.parse); }
213   : ARG                                    { $$.parse = plist($1.string); }
214   | `[` { yymode(SCAN_NORMAL); } func `]`  { $$.parse = $3.parse; }
219  * func - a function call (inside [])
220  * This needs to be split cleanly out of 'rule'
221  */
222 func
223   : arg lol                 { $$.parse = prule($1.parse, $2.parse); }
224   | `on` arg arg lol        { $$.parse = pon($2.parse, prule($3.parse, $4.parse)); }
225   | `on` arg `return` list  { $$.parse = pon($2.parse, $4.parse); }
230  * eflags - zero or more modifiers to 'executes'
231  * eflag - a single modifier to 'executes'
232  */
233 eflags
234   : /* empty */   { $$.number = 0; }
235   | eflags eflag  { $$.number = $1.number | $2.number; }
238 eflag
239   : `updated`      { $$.number = RULE_UPDATED; }
240   | `together`     { $$.number = RULE_TOGETHER; }
241   | `ignore`       { $$.number = RULE_IGNORE; }
242   | `quietly`      { $$.number = RULE_QUIETLY; }
243   | `piecemeal`    { $$.number = RULE_PIECEMEAL; }
244   | `existing`     { $$.number = RULE_EXISTING; }
245   | `maxline` ARG  { $$.number = atoi($2.string)*RULE_MAXLINE; }
250  * bindlist - list of variable to bind for an action
251  */
252 bindlist
253   : /* empty */  { $$.parse = pnull(); }
254   | `bind` list  { $$.parse = $2.parse; }