option.c: fixed warnings
[k8jam.git] / src / jamgram.yy
blobecc400e4037eed30b0d1b3226029b92d304c8cd4
1 /*
2  * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
3  * This file is part of Jam - see jam.c for Copyright information.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3 of the License ONLY.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
18  * jamgram.yy - jam grammar
19  */
20 %stack_size 0
22 %token_type {token_t}
24 %syntax_error {
25   yyerror(&yyminor.yy0, "parsing error");
29 %left `|` `||` .
30 %left `&` `&&` .
31 %left `==` `=` `!=` `in` `anyin` `~=` .
32 %left `<` `<=` `>` `>=` .
33 %left `!` .
36 %include{
37 #include "jam.h"
39 #include "lists.h"
40 #include "variable.h"
41 #include "parse.h"
42 #include "scan.h"
43 #include "compile.h"
44 #include "newstr.h"
45 #include "rules.h"
47 /* for OSF and other less endowed yaccs */
48 /*#define YYMAXDEPTH  (10000)*/
50 #define F0  (LIST *(*)(PARSE *, LOL *, int *))0
51 #define P0  (PARSE *)0
52 #define S0  (char *)0
54 #define pappend(l,r)     parse_make(compile_append, l, r, P0, S0, S0, 0)
55 #define pbreak(l,f)      parse_make(compile_break, l, P0, P0, S0, S0, f)
56 #define peval(c,l,r)     parse_make(compile_eval, l, r, P0, S0, S0, c)
57 #define pfor(s,l,r,x)    parse_make(compile_foreach, l, r, P0, s, S0, x)
58 #define pif(l,r,t)       parse_make(compile_if, l, r, t, S0, S0, 0)
59 #define pincl(l,soft)    parse_make(compile_include, l, P0, P0, S0, S0, soft)
60 #define plist(s,sl)      parse_make(compile_list, P0, P0, P0, s, S0, sl)
61 #define plocal(l,r,t)    parse_make(compile_local, l, r, t, S0, S0, 0)
62 #define pnull()          parse_make(compile_null, P0, P0, P0, S0, S0, 0)
63 #define pon(l,r)         parse_make(compile_on, l, r, P0, S0, S0, 0)
64 #define prule(a,p)       parse_make(compile_rule, a, p, P0, S0, S0, 0)
65 #define prules(l,r)      parse_make(compile_rules, l, r, P0, S0, S0, 0)
66 #define pset(l,r,a)      parse_make(compile_set, l, r, P0, S0, S0, a)
67 #define pset1(l,r,t,a)   parse_make(compile_settings, l, r, t, S0, S0, a)
68 #define psetc(s,l,r)     parse_make(compile_setcomp, l, r, P0, s, S0, 0)
69 #define psete(s,l,s1,f)  parse_make(compile_setexec, l, P0, P0, s, s1, f)
70 #define pswitch(l,r)     parse_make(compile_switch, l, r, P0, S0, S0, 0)
71 #define pwhile(l,r)      parse_make(compile_while, l, r, P0, S0, S0, 0)
73 #define pnode(l,r)       parse_make(F0, l, r, P0, S0, S0, 0)
74 #define psnode(s,l)      parse_make(F0, l, P0, P0, s, S0, 0)
78 /******************************************************************************/
79 %start_symbol run
82 run ::= .           /* do nothing */
83 run ::= rules(R) .  { parse_save(R.parse); }
87  * block - zero or more rules
88  * rules - one or more rules
89  * rule - any one of jam's rules
90  * right-recursive so rules execute in order.
91  */
92 block(RR) ::= .           { RR.parse = pnull(); }
93 block(RR) ::= rules(R) .  { RR.parse = R.parse; }
95 rules(RR) ::= rule(R) .                                         { RR.parse = R.parse; }
96 rules(RR) ::= rule(R1) rules(R2) .                              { RR.parse = prules(R1.parse, R2.parse); }
97 rules(RR) ::= `local` list(LST) `;` block(B) .                  { RR.parse = plocal(LST.parse, pnull(), B.parse); }
98 rules(RR) ::= `local` list(LST1) `=` list(LST2) `;` block(B) .  { RR.parse = plocal(LST1.parse, LST2.parse, B.parse); }
100 rule(RR) ::= `{` block(B) `}` .                                 { RR.parse = B.parse; }
101 rule(RR) ::= `include` list(LST) `;` .                          { RR.parse = pincl(LST.parse, 0); }
102 rule(RR) ::= `softinclude` list(LST) `;` .                      { RR.parse = pincl(LST.parse, 1); }
103 rule(RR) ::= arg(A) lol(LST) `;` .                              { RR.parse = prule(A.parse, LST.parse); }
104 rule(RR) ::= arg(A) assign(X) list(LST) `;` .                   { RR.parse = pset(A.parse, LST.parse, X.number); }
105 rule(RR) ::= arg(A) `on` list(LST0) assign(X) list(LST1) `;` .  { RR.parse = pset1(A.parse, LST0.parse, LST1.parse, X.number); }
106 rule(RR) ::= `break` list(LST) `;` .                            { RR.parse = pbreak(LST.parse, JMP_BREAK); }
107 rule(RR) ::= `continue` list(LST) `;` .                         { RR.parse = pbreak(LST.parse, JMP_CONTINUE); }
108 rule(RR) ::= `return` list(LST) `;` .                           { RR.parse = pbreak(LST.parse, JMP_RETURN); }
109 rule(RR) ::= `for` local_opt(LO) T_ARG(A) `in` list(LST) `{` block(B) `}` .  { RR.parse = pfor(A.string, LST.parse, B.parse, LO.number); }
110 rule(RR) ::= `switch` list(LST) `{` cases(CS) `}` .             { RR.parse = pswitch(LST.parse, CS.parse); }
111 rule(RR) ::= `if` expr(EXP) `{` block(B) `}` .                  { RR.parse = pif(EXP.parse, B.parse, pnull()); }
112 rule(RR) ::= `if` expr(EXP) `{` block(B) `}` `else` rule(R) .   { RR.parse = pif(EXP.parse, B.parse, R.parse); }
113 rule(RR) ::= `while` expr(EXP) `{` block(B) `}` .               { RR.parse = pwhile(EXP.parse, B.parse); }
114 rule(RR) ::= `rule` T_ARG(A) params(PR) `{` block(B) `}` .      { RR.parse = psetc(A.string, PR.parse, B.parse); }
115 rule(RR) ::= `on` arg(A) rule(R) .                              { RR.parse = pon(A.parse, R.parse); }
116 rule(RR) ::= `actions` eflags(EF) T_ARG(A) bindlist(BL) set_string_mode `{` T_STRING(STR) `}` .
117   { RR.parse = psete(A.string, BL.parse, STR.string, EF.number); }
118 /* note that lemon is LALR(1), so we have to move set_string_mode BEFORE opening brace */
121 local_opt(RR) ::= `local` .  { RR.number = 1; }
122 local_opt(RR) ::= .          { RR.number = 0; }
126  * assign - =, +=, ?=, -=
127  */
128 assign(RR) ::= `=` .   { RR.number = VAR_SET; }
129 assign(RR) ::= `+=` .  { RR.number = VAR_APPEND; }
130 assign(RR) ::= `-=` .  { RR.number = VAR_REMOVE; }
131 assign(RR) ::= `?=` .  { RR.number = VAR_DEFAULT; }
135  * expr - an expression for if
136  */
137 expr(RR) ::= arg(A) .                      { RR.parse = peval(EXPR_EXISTS, A.parse, pnull()); }
138 expr(RR) ::= expr(EXP0) `=` expr(EXP1) .   { RR.parse = peval(EXPR_EQUALS, EXP0.parse, EXP1.parse); }
139 expr(RR) ::= expr(EXP0) `==` expr(EXP1) .  { RR.parse = peval(EXPR_EQUALS, EXP0.parse, EXP1.parse); }
140 expr(RR) ::= expr(EXP0) `~=` arg(A) .      { RR.parse = peval(EXPR_REXPEQ, EXP0.parse, A.parse); }
141 expr(RR) ::= expr(EXP0) `!=` expr(EXP1) .  { RR.parse = peval(EXPR_NOTEQ, EXP0.parse, EXP1.parse); }
142 expr(RR) ::= expr(EXP0) `<` expr(EXP1) .   { RR.parse = peval(EXPR_LESS, EXP0.parse, EXP1.parse); }
143 expr(RR) ::= expr(EXP0) `<=` expr(EXP1) .  { RR.parse = peval(EXPR_LESSEQ, EXP0.parse, EXP1.parse); }
144 expr(RR) ::= expr(EXP0) `>` expr(EXP1) .   { RR.parse = peval(EXPR_MORE, EXP0.parse, EXP1.parse); }
145 expr(RR) ::= expr(EXP0) `>=` expr(EXP1) .  { RR.parse = peval(EXPR_MOREEQ, EXP0.parse, EXP1.parse); }
146 expr(RR) ::= expr(EXP0) `&` expr(EXP1) .   { RR.parse = peval(EXPR_AND, EXP0.parse, EXP1.parse); }
147 expr(RR) ::= expr(EXP0) `&&` expr(EXP1) .  { RR.parse = peval(EXPR_AND, EXP0.parse, EXP1.parse); }
148 expr(RR) ::= expr(EXP0) `|` expr(EXP1) .   { RR.parse = peval(EXPR_OR, EXP0.parse, EXP1.parse); }
149 expr(RR) ::= expr(EXP0) `||` expr(EXP1) .  { RR.parse = peval(EXPR_OR, EXP0.parse, EXP1.parse); }
150 expr(RR) ::= arg(A) `in` list(L) .         { RR.parse = peval(EXPR_IN, A.parse, L.parse); }
151 expr(RR) ::= arg(A) `anyin` list(L) .      { RR.parse = peval(EXPR_ANYIN, A.parse, L.parse); }
152 expr(RR) ::= `!` expr(E) .                 { RR.parse = peval(EXPR_NOT, E.parse, pnull()); }
153 expr(RR) ::= `(` expr(E) `)` .             { RR.parse = E.parse; }
157  * cases - action elements inside a 'switch'
158  * case - a single action element inside a 'switch'
159  * right-recursive rule so cases can be examined in order.
160  */
161 cases(RR) ::= .                      { RR.parse = P0; }
162 cases(RR) ::= case(CS) cases(CSX) .  { RR.parse = pnode(CS.parse, CSX.parse); }
164 case(RR) ::= `case` T_ARG(A) `:` block(B) .  { RR.parse = psnode(A.string, B.parse); }
168  * params - optional parameter names to rule definition
169  * right-recursive rule so that params can be added in order.
170  */
171 params(RR) ::= .                         { RR.parse = P0; }
172 params(RR) ::= T_ARG(A) `:` params(P) .  { RR.parse = psnode(A.string, P.parse); }
173 params(RR) ::= T_ARG(A) .                { RR.parse = psnode(A.string, P0); }
177  * lol - list of lists
178  * right-recursive rule so that lists can be added in order.
179  */
180 lol(RR) ::= list(L) .               { RR.parse = pnode(P0, L.parse); }
181 lol(RR) ::= list(L) `:` lol(LOL) .  { RR.parse = pnode(LOL.parse, L.parse); }
185  * list - zero or more args in a LIST
186  * listp - list (in puncutation only mode)
187  * arg - one T_ARG or function call
188  */
189 list(RR) ::= listp(L) .  { RR.parse = L.parse; yymode(SCAN_NORMAL); }
191 listp(RR) ::= .                  { RR.parse = pnull(); yymode(SCAN_PUNCT); }
192 listp(RR) ::= listp(L) arg(A) .  { RR.parse = pappend(L.parse, A.parse); }
194 arg(RR) ::= T_ARG(A) .                         { RR.parse = plist(A.string, A.strlit); }
195 arg(RR) ::= set_normal_mode `[` func(F) `]` .  { RR.parse = F.parse; }
196 /* note that lemon is LALR(1), so we have to move set_normal_mode BEFORE opening bracket */
200  * func - a function call (inside [])
201  * This needs to be split cleanly out of 'rule'
202  */
203 func(RR) ::= arg(A) lol(LOL) .                { RR.parse = prule(A.parse, LOL.parse); }
204 func(RR) ::= `on` arg(A0) arg(A1) lol(LOL) .  { RR.parse = pon(A0.parse, prule(A1.parse, LOL.parse)); }
205 func(RR) ::= `on` arg(A) `return` list(L) .   { RR.parse = pon(A.parse, L.parse); }
209  * eflags - zero or more modifiers to 'executes'
210  * eflag - a single modifier to 'executes'
211  */
212 eflags(RR) ::= .                        { RR.number = 0; }
213 eflags(RR) ::= eflags(EFL) eflag(EF) .  { RR.number = EFL.number|EF.number; }
215 eflag(RR) ::= `updated` .         { RR.number = RULE_UPDATED; }
216 eflag(RR) ::= `together` .        { RR.number = RULE_TOGETHER; }
217 eflag(RR) ::= `ignore` .          { RR.number = RULE_IGNORE; }
218 eflag(RR) ::= `quietly` .         { RR.number = RULE_QUIETLY; }
219 eflag(RR) ::= `piecemeal` .       { RR.number = RULE_PIECEMEAL; }
220 eflag(RR) ::= `existing` .        { RR.number = RULE_EXISTING; }
221 eflag(RR) ::= `maxline` T_ARG(A) .  {
222   RR.number = atoi(A.string);
223   if (RR.number < 1) RR.number = 1; else if (RR.number > 1024) RR.number = 1024;
224   RR.number = (RR.number<<8)|RULE_MAXLINE;
229  * bindlist - list of variable to bind for an action
230  */
231 bindlist(RR) ::= .                 { RR.parse = pnull(); }
232 bindlist(RR) ::= `bind` list(L) .  { RR.parse = L.parse; }
236  * mode change rules
237  */
238 set_normal_mode ::= .  { /*if (DEBUG_SCAN) printf("**set_normal_mode\n");*/ yymode(SCAN_NORMAL); }
239 set_string_mode ::= .  { /*if (DEBUG_SCAN) printf("**set_string_mode\n");*/ yymode(SCAN_STRING); }