2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * This file is part of Jam - see jam.c for Copyright information.
7 * jamgram.yy - jam grammar
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
29 * 2013, Sep 16 (ketmar): modified for lemon
36 yyerror(&yyminor.yy0, "parsing error");
42 %left `==` `=` `!=` `in` `anyin` `~=` .
43 %left `<` `<=` `>` `>=` .
58 /* for OSF and other less endowed yaccs */
59 /*#define YYMAXDEPTH (10000)*/
61 #define F0 (LIST *(*)(PARSE *, LOL *, int *))0
65 #define pappend(l,r) parse_make(compile_append, l, r, P0, S0, S0, 0)
66 #define pbreak(l,f) parse_make(compile_break, l, P0, P0, S0, S0, f)
67 #define peval(c,l,r) parse_make(compile_eval, l, r, P0, S0, S0, c)
68 #define pfor(s,l,r,x) parse_make(compile_foreach, l, r, P0, s, S0, x)
69 #define pif(l,r,t) parse_make(compile_if, l, r, t, S0, S0, 0)
70 #define pincl(l,soft) parse_make(compile_include, l, P0, P0, S0, S0, soft)
71 #define plist(s,sl) parse_make(compile_list, P0, P0, P0, s, S0, sl)
72 #define plocal(l,r,t) parse_make(compile_local, l, r, t, S0, S0, 0)
73 #define pnull() parse_make(compile_null, P0, P0, P0, S0, S0, 0)
74 #define pon(l,r) parse_make(compile_on, l, r, P0, S0, S0, 0)
75 #define prule(a,p) parse_make(compile_rule, a, p, P0, S0, S0, 0)
76 #define prules(l,r) parse_make(compile_rules, l, r, P0, S0, S0, 0)
77 #define pset(l,r,a) parse_make(compile_set, l, r, P0, S0, S0, a)
78 #define pset1(l,r,t,a) parse_make(compile_settings, l, r, t, S0, S0, a)
79 #define psetc(s,l,r) parse_make(compile_setcomp, l, r, P0, s, S0, 0)
80 #define psete(s,l,s1,f) parse_make(compile_setexec, l, P0, P0, s, s1, f)
81 #define pswitch(l,r) parse_make(compile_switch, l, r, P0, S0, S0, 0)
82 #define pwhile(l,r) parse_make(compile_while, l, r, P0, S0, S0, 0)
84 #define pnode(l,r) parse_make(F0, l, r, P0, S0, S0, 0)
85 #define psnode(s,l) parse_make(F0, l, P0, P0, s, S0, 0)
89 /******************************************************************************/
93 run ::= . /* do nothing */
94 run ::= rules(R) . { parse_save(R.parse); }
98 * block - zero or more rules
99 * rules - one or more rules
100 * rule - any one of jam's rules
101 * right-recursive so rules execute in order.
103 block(RR) ::= . { RR.parse = pnull(); }
104 block(RR) ::= rules(R) . { RR.parse = R.parse; }
106 rules(RR) ::= rule(R) . { RR.parse = R.parse; }
107 rules(RR) ::= rule(R1) rules(R2) . { RR.parse = prules(R1.parse, R2.parse); }
108 rules(RR) ::= `local` list(LST) `;` block(B) . { RR.parse = plocal(LST.parse, pnull(), B.parse); }
109 rules(RR) ::= `local` list(LST1) `=` list(LST2) `;` block(B) . { RR.parse = plocal(LST1.parse, LST2.parse, B.parse); }
111 rule(RR) ::= `{` block(B) `}` . { RR.parse = B.parse; }
112 rule(RR) ::= `include` list(LST) `;` . { RR.parse = pincl(LST.parse, 0); }
113 rule(RR) ::= `softinclude` list(LST) `;` . { RR.parse = pincl(LST.parse, 1); }
114 rule(RR) ::= arg(A) lol(LST) `;` . { RR.parse = prule(A.parse, LST.parse); }
115 rule(RR) ::= arg(A) assign(X) list(LST) `;` . { RR.parse = pset(A.parse, LST.parse, X.number); }
116 rule(RR) ::= arg(A) `on` list(LST0) assign(X) list(LST1) `;` . { RR.parse = pset1(A.parse, LST0.parse, LST1.parse, X.number); }
117 rule(RR) ::= `break` list(LST) `;` . { RR.parse = pbreak(LST.parse, JMP_BREAK); }
118 rule(RR) ::= `continue` list(LST) `;` . { RR.parse = pbreak(LST.parse, JMP_CONTINUE); }
119 rule(RR) ::= `return` list(LST) `;` . { RR.parse = pbreak(LST.parse, JMP_RETURN); }
120 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); }
121 rule(RR) ::= `switch` list(LST) `{` cases(CS) `}` . { RR.parse = pswitch(LST.parse, CS.parse); }
122 rule(RR) ::= `if` expr(EXP) `{` block(B) `}` . { RR.parse = pif(EXP.parse, B.parse, pnull()); }
123 rule(RR) ::= `if` expr(EXP) `{` block(B) `}` `else` rule(R) . { RR.parse = pif(EXP.parse, B.parse, R.parse); }
124 rule(RR) ::= `while` expr(EXP) `{` block(B) `}` . { RR.parse = pwhile(EXP.parse, B.parse); }
125 rule(RR) ::= `rule` T_ARG(A) params(PR) `{` block(B) `}` . { RR.parse = psetc(A.string, PR.parse, B.parse); }
126 rule(RR) ::= `on` arg(A) rule(R) . { RR.parse = pon(A.parse, R.parse); }
127 rule(RR) ::= `actions` eflags(EF) T_ARG(A) bindlist(BL) set_string_mode `{` T_STRING(STR) `}` .
128 { RR.parse = psete(A.string, BL.parse, STR.string, EF.number); }
129 /* note that lemon is LALR(1), so we have to move set_string_mode BEFORE opening brace */
132 local_opt(RR) ::= `local` . { RR.number = 1; }
133 local_opt(RR) ::= . { RR.number = 0; }
137 * assign - =, +=, ?=, -=
139 assign(RR) ::= `=` . { RR.number = VAR_SET; }
140 assign(RR) ::= `+=` . { RR.number = VAR_APPEND; }
141 assign(RR) ::= `-=` . { RR.number = VAR_REMOVE; }
142 assign(RR) ::= `?=` . { RR.number = VAR_DEFAULT; }
146 * expr - an expression for if
148 expr(RR) ::= arg(A) . { RR.parse = peval(EXPR_EXISTS, A.parse, pnull()); }
149 expr(RR) ::= expr(EXP0) `=` expr(EXP1) . { RR.parse = peval(EXPR_EQUALS, EXP0.parse, EXP1.parse); }
150 expr(RR) ::= expr(EXP0) `==` expr(EXP1) . { RR.parse = peval(EXPR_EQUALS, EXP0.parse, EXP1.parse); }
151 expr(RR) ::= expr(EXP0) `~=` arg(A) . { RR.parse = peval(EXPR_REXPEQ, EXP0.parse, A.parse); }
152 expr(RR) ::= expr(EXP0) `!=` expr(EXP1) . { RR.parse = peval(EXPR_NOTEQ, EXP0.parse, EXP1.parse); }
153 expr(RR) ::= expr(EXP0) `<` expr(EXP1) . { RR.parse = peval(EXPR_LESS, EXP0.parse, EXP1.parse); }
154 expr(RR) ::= expr(EXP0) `<=` expr(EXP1) . { RR.parse = peval(EXPR_LESSEQ, EXP0.parse, EXP1.parse); }
155 expr(RR) ::= expr(EXP0) `>` expr(EXP1) . { RR.parse = peval(EXPR_MORE, EXP0.parse, EXP1.parse); }
156 expr(RR) ::= expr(EXP0) `>=` expr(EXP1) . { RR.parse = peval(EXPR_MOREEQ, EXP0.parse, EXP1.parse); }
157 expr(RR) ::= expr(EXP0) `&` expr(EXP1) . { RR.parse = peval(EXPR_AND, EXP0.parse, EXP1.parse); }
158 expr(RR) ::= expr(EXP0) `&&` expr(EXP1) . { RR.parse = peval(EXPR_AND, EXP0.parse, EXP1.parse); }
159 expr(RR) ::= expr(EXP0) `|` expr(EXP1) . { RR.parse = peval(EXPR_OR, EXP0.parse, EXP1.parse); }
160 expr(RR) ::= expr(EXP0) `||` expr(EXP1) . { RR.parse = peval(EXPR_OR, EXP0.parse, EXP1.parse); }
161 expr(RR) ::= arg(A) `in` list(L) . { RR.parse = peval(EXPR_IN, A.parse, L.parse); }
162 expr(RR) ::= arg(A) `anyin` list(L) . { RR.parse = peval(EXPR_ANYIN, A.parse, L.parse); }
163 expr(RR) ::= `!` expr(E) . { RR.parse = peval(EXPR_NOT, E.parse, pnull()); }
164 expr(RR) ::= `(` expr(E) `)` . { RR.parse = E.parse; }
168 * cases - action elements inside a 'switch'
169 * case - a single action element inside a 'switch'
170 * right-recursive rule so cases can be examined in order.
172 cases(RR) ::= . { RR.parse = P0; }
173 cases(RR) ::= case(CS) cases(CSX) . { RR.parse = pnode(CS.parse, CSX.parse); }
175 case(RR) ::= `case` T_ARG(A) `:` block(B) . { RR.parse = psnode(A.string, B.parse); }
179 * params - optional parameter names to rule definition
180 * right-recursive rule so that params can be added in order.
182 params(RR) ::= . { RR.parse = P0; }
183 params(RR) ::= T_ARG(A) `:` params(P) . { RR.parse = psnode(A.string, P.parse); }
184 params(RR) ::= T_ARG(A) . { RR.parse = psnode(A.string, P0); }
188 * lol - list of lists
189 * right-recursive rule so that lists can be added in order.
191 lol(RR) ::= list(L) . { RR.parse = pnode(P0, L.parse); }
192 lol(RR) ::= list(L) `:` lol(LOL) . { RR.parse = pnode(LOL.parse, L.parse); }
196 * list - zero or more args in a LIST
197 * listp - list (in puncutation only mode)
198 * arg - one T_ARG or function call
200 list(RR) ::= listp(L) . { RR.parse = L.parse; yymode(SCAN_NORMAL); }
202 listp(RR) ::= . { RR.parse = pnull(); yymode(SCAN_PUNCT); }
203 listp(RR) ::= listp(L) arg(A) . { RR.parse = pappend(L.parse, A.parse); }
205 arg(RR) ::= T_ARG(A) . { RR.parse = plist(A.string, A.strlit); }
206 arg(RR) ::= set_normal_mode `[` func(F) `]` . { RR.parse = F.parse; }
207 /* note that lemon is LALR(1), so we have to move set_normal_mode BEFORE opening bracket */
211 * func - a function call (inside [])
212 * This needs to be split cleanly out of 'rule'
214 func(RR) ::= arg(A) lol(LOL) . { RR.parse = prule(A.parse, LOL.parse); }
215 func(RR) ::= `on` arg(A0) arg(A1) lol(LOL) . { RR.parse = pon(A0.parse, prule(A1.parse, LOL.parse)); }
216 func(RR) ::= `on` arg(A) `return` list(L) . { RR.parse = pon(A.parse, L.parse); }
220 * eflags - zero or more modifiers to 'executes'
221 * eflag - a single modifier to 'executes'
223 eflags(RR) ::= . { RR.number = 0; }
224 eflags(RR) ::= eflags(EFL) eflag(EF) . { RR.number = EFL.number | EF.number; }
226 eflag(RR) ::= `updated` . { RR.number = RULE_UPDATED; }
227 eflag(RR) ::= `together` . { RR.number = RULE_TOGETHER; }
228 eflag(RR) ::= `ignore` . { RR.number = RULE_IGNORE; }
229 eflag(RR) ::= `quietly` . { RR.number = RULE_QUIETLY; }
230 eflag(RR) ::= `piecemeal` . { RR.number = RULE_PIECEMEAL; }
231 eflag(RR) ::= `existing` . { RR.number = RULE_EXISTING; }
232 eflag(RR) ::= `maxline` T_ARG(A) . {
233 RR.number = atoi(A.string);
234 if (RR.number < 1) RR.number = 1; else if (RR.number > 1024) RR.number = 1024;
235 RR.number = (RR.number<<8)|RULE_MAXLINE;
240 * bindlist - list of variable to bind for an action
242 bindlist(RR) ::= . { RR.parse = pnull(); }
243 bindlist(RR) ::= `bind` list(L) . { RR.parse = L.parse; }
249 set_normal_mode ::= . { /*if (DEBUG_SCAN) printf("**set_normal_mode\n");*/ yymode(SCAN_NORMAL); }
250 set_string_mode ::= . { /*if (DEBUG_SCAN) printf("**set_string_mode\n");*/ yymode(SCAN_STRING); }