ah; i'm an idiot; fix for gcc-suggest-attrs
[k8jam.git] / src / jamgram.yy
blobbd045b1097c2ac0389dce32f76ce8c2580825a30
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 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
83   : /* empty */  /* do nothing */
84   | rules        { parse_save($1.parse); }
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  */
94 block
95   : /* empty */  { $$.parse = pnull(); }
96   | rules        { $$.parse = $1.parse; }
99 rules
100   : rule                             { $$.parse = $1.parse; }
101   | rule rules                       { $$.parse = prules($1.parse, $2.parse); }
102   | `local` list `;` block           { $$.parse = plocal($2.parse, pnull(), $4.parse); }
103   | `local` list `=` list `;` block  { $$.parse = plocal($2.parse, $4.parse, $6.parse); }
106 rule
107   : `{` block `}`                        { $$.parse = $2.parse; }
108   | `include` list `;`                   { $$.parse = pincl($2.parse); }
109   | arg lol `;`                          { $$.parse = prule($1.parse, $2.parse); }
110   | arg assign list `;`                  { $$.parse = pset($1.parse, $3.parse, $2.number); }
111   | arg `on` list assign list `;`        { $$.parse = pset1($1.parse, $3.parse, $5.parse, $4.number); }
112   | `break` list `;`                     { $$.parse = pbreak($2.parse, JMP_BREAK); }
113   | `continue` list `;`                  { $$.parse = pbreak($2.parse, JMP_CONTINUE); }
114   | `return` list `;`                    { $$.parse = pbreak($2.parse, JMP_RETURN); }
115   | `for` ARG `in` list `{` block `}`    { $$.parse = pfor($2.string, $4.parse, $6.parse); }
116   | `switch` list `{` cases `}`          { $$.parse = pswitch($2.parse, $4.parse); }
117   | `if` expr `{` block `}`              { $$.parse = pif($2.parse, $4.parse, pnull()); }
118   | `if` expr `{` block `}` `else` rule  { $$.parse = pif($2.parse, $4.parse, $7.parse); }
119   | `while` expr `{` block `}`           { $$.parse = pwhile($2.parse, $4.parse); }
120   | `rule` ARG params `{` block `}`      { $$.parse = psetc($2.string, $3.parse, $5.parse); }
121   | `on` arg rule                        { $$.parse = pon($2.parse, $3.parse); }
122   | `actions` eflags ARG bindlist `{` { yymode(SCAN_STRING); } STRING { yymode(SCAN_NORMAL); } `}`
123     { $$.parse = psete($3.string, $4.parse, $7.string, $2.number); }
128  * assign - =, +=, ?=, -=
129  */
130 assign
131   : `=`            { $$.number = VAR_SET; }
132   | `+=`           { $$.number = VAR_APPEND; }
133   | `-=`           { $$.number = VAR_REMOVE; }
134   | `?=`           { $$.number = VAR_DEFAULT; }
135   | `default` `=`  { $$.number = VAR_DEFAULT; }
140  * expr - an expression for if
141  */
142 expr
143   : arg             { $$.parse = peval(EXPR_EXISTS, $1.parse, pnull()); }
144   | expr `=` expr   { $$.parse = peval(EXPR_EQUALS, $1.parse, $3.parse); }
145   | expr `!=` expr  { $$.parse = peval(EXPR_NOTEQ, $1.parse, $3.parse); }
146   | expr `<` expr   { $$.parse = peval(EXPR_LESS, $1.parse, $3.parse); }
147   | expr `<=` expr  { $$.parse = peval(EXPR_LESSEQ, $1.parse, $3.parse); }
148   | expr `>` expr   { $$.parse = peval(EXPR_MORE, $1.parse, $3.parse); }
149   | expr `>=` expr  { $$.parse = peval(EXPR_MOREEQ, $1.parse, $3.parse); }
150   | expr `&` expr   { $$.parse = peval(EXPR_AND, $1.parse, $3.parse); }
151   | expr `&&` expr  { $$.parse = peval(EXPR_AND, $1.parse, $3.parse); }
152   | expr `|` expr   { $$.parse = peval(EXPR_OR, $1.parse, $3.parse); }
153   | expr `||` expr  { $$.parse = peval(EXPR_OR, $1.parse, $3.parse); }
154   | arg `in` list   { $$.parse = peval(EXPR_IN, $1.parse, $3.parse); }
155   | `!` expr        { $$.parse = peval(EXPR_NOT, $2.parse, pnull()); }
156   | `(` expr `)`    { $$.parse = $2.parse; }
161  * cases - action elements inside a 'switch'
162  * case - a single action element inside a 'switch'
163  * right-recursive rule so cases can be examined in order.
164  */
165 cases
166   : /* empty */  { $$.parse = P0; }
167   | case cases   { $$.parse = pnode($1.parse, $2.parse); }
170 case
171   : `case` ARG `:` block  { $$.parse = psnode($2.string, $4.parse); }
176  * params - optional parameter names to rule definition
177  * right-recursive rule so that params can be added in order.
178  */
179 params
180   : /* empty */     { $$.parse = P0; }
181   | ARG `:` params  { $$.parse = psnode($1.string, $3.parse); }
182   | ARG             { $$.parse = psnode($1.string, P0); }
187  * lol - list of lists
188  * right-recursive rule so that lists can be added in order.
189  */
191   : list          { $$.parse = pnode(P0, $1.parse); }
192   | list `:` lol  { $$.parse = pnode($3.parse, $1.parse); }
197  * list - zero or more args in a LIST
198  * listp - list (in puncutation only mode)
199  * arg - one ARG or function call
200  */
201 list
202   : listp  { $$.parse = $1.parse; yymode(SCAN_NORMAL); }
205 listp
206   : /* empty */  { $$.parse = pnull(); yymode(SCAN_PUNCT); }
207   | listp arg    { $$.parse = pappend($1.parse, $2.parse); }
211   : ARG                                    { $$.parse = plist($1.string); }
212   | `[` { yymode(SCAN_NORMAL); } func `]`  { $$.parse = $3.parse; }
217  * func - a function call (inside [])
218  * This needs to be split cleanly out of 'rule'
219  */
220 func
221   : arg lol                 { $$.parse = prule($1.parse, $2.parse); }
222   | `on` arg arg lol        { $$.parse = pon($2.parse, prule($3.parse, $4.parse)); }
223   | `on` arg `return` list  { $$.parse = pon($2.parse, $4.parse); }
228  * eflags - zero or more modifiers to 'executes'
229  * eflag - a single modifier to 'executes'
230  */
231 eflags
232   : /* empty */   { $$.number = 0; }
233   | eflags eflag  { $$.number = $1.number | $2.number; }
236 eflag
237   : `updated`      { $$.number = RULE_UPDATED; }
238   | `together`     { $$.number = RULE_TOGETHER; }
239   | `ignore`       { $$.number = RULE_IGNORE; }
240   | `quietly`      { $$.number = RULE_QUIETLY; }
241   | `piecemeal`    { $$.number = RULE_PIECEMEAL; }
242   | `existing`     { $$.number = RULE_EXISTING; }
243   | `maxline` ARG  { $$.number = atoi($2.string)*RULE_MAXLINE; }
248  * bindlist - list of variable to bind for an action
249  */
250 bindlist
251   : /* empty */  { $$.parse = pnull(); }
252   | `bind` list  { $$.parse = $2.parse; }