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