2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
3 * This file is part of Jam - see jam.c for Copyright information.
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.
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.
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/>.
19 * jamgram.yy - jam grammar
26 yyerror(&yyminor.yy0, "parsing error");
32 %left `==` `=` `!=` `in` `anyin` `~=` .
33 %left `<` `<=` `>` `>=` .
48 /* for OSF and other less endowed yaccs */
49 /*#define YYMAXDEPTH (10000)*/
51 #define F0 (LIST *(*)(PARSE *, LOL *, int *))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 /******************************************************************************/
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.
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 - =, +=, ?=, -=
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
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.
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.
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.
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
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'
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'
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
232 bindlist(RR) ::= . { RR.parse = pnull(); }
233 bindlist(RR) ::= `bind` list(L) . { RR.parse = L.parse; }
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); }