cosmetix in 'maxline'
[k8jam.git] / src / jamgram.yy
blob7002796f5a3fb06196f4350fe59d87bf76304314
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  *
29  * 2013, Sep 16 (ketmar): modified for lemon
30  */
31 %stack_size 0
33 %token_type {token_t}
35 %syntax_error {
36   yyerror(&yyminor.yy0, "parsing error");
40 %left `|` `||` .
41 %left `&` `&&` .
42 %left `==` `=` `!=` `in` `anyin` `~=` .
43 %left `<` `<=` `>` `>=` .
44 %left `!` .
47 %include{
48 #include "jam.h"
50 #include "lists.h"
51 #include "variable.h"
52 #include "parse.h"
53 #include "scan.h"
54 #include "compile.h"
55 #include "newstr.h"
56 #include "rules.h"
58 /* for OSF and other less endowed yaccs */
59 /*#define YYMAXDEPTH  (10000)*/
61 #define F0  (LIST *(*)(PARSE *, LOL *, int *))0
62 #define P0  (PARSE *)0
63 #define S0  (char *)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 /******************************************************************************/
90 %start_symbol run
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.
102  */
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 - =, +=, ?=, -=
138  */
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
147  */
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.
171  */
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.
181  */
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.
190  */
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
199  */
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'
213  */
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'
222  */
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
241  */
242 bindlist(RR) ::= .                 { RR.parse = pnull(); }
243 bindlist(RR) ::= `bind` list(L) .  { RR.parse = L.parse; }
247  * mode change rules
248  */
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); }