Blame


1 47d4646e 2020-05-05 rsc #include "rc.h"
2 47d4646e 2020-05-05 rsc #include "io.h"
3 47d4646e 2020-05-05 rsc #include "fns.h"
4 47d4646e 2020-05-05 rsc
5 47d4646e 2020-05-05 rsc static tree* body(int tok, int *ptok);
6 47d4646e 2020-05-05 rsc static tree* brace(int tok);
7 47d4646e 2020-05-05 rsc static tree* cmd(int tok, int *ptok);
8 47d4646e 2020-05-05 rsc static tree* cmd2(int tok, int *ptok);
9 47d4646e 2020-05-05 rsc static tree* cmd3(int tok, int *ptok);
10 47d4646e 2020-05-05 rsc static tree* cmds(int tok, int *ptok, int nlok);
11 47d4646e 2020-05-05 rsc static tree* epilog(int tok, int *ptok);
12 47d4646e 2020-05-05 rsc static int iswordtok(int tok);
13 47d4646e 2020-05-05 rsc static tree* line(int tok, int *ptok);
14 47d4646e 2020-05-05 rsc static tree* paren(int tok);
15 47d4646e 2020-05-05 rsc static tree* yyredir(int tok, int *ptok);
16 ff74f7cd 2020-05-05 rsc static tree* yyword(int tok, int *ptok, int eqok);
17 47d4646e 2020-05-05 rsc static tree* word1(int tok, int *ptok);
18 47d4646e 2020-05-05 rsc static tree* words(int tok, int *ptok);
19 47d4646e 2020-05-05 rsc
20 47d4646e 2020-05-05 rsc static jmp_buf yyjmp;
21 47d4646e 2020-05-05 rsc
22 3caf5c23 2020-05-05 rsc static int
23 3caf5c23 2020-05-05 rsc dropnl(int tok)
24 3caf5c23 2020-05-05 rsc {
25 7d6a248f 2020-05-05 rsc while(tok == ' ' || tok == '\n')
26 3caf5c23 2020-05-05 rsc tok = yylex();
27 3caf5c23 2020-05-05 rsc return tok;
28 3caf5c23 2020-05-05 rsc }
29 3caf5c23 2020-05-05 rsc
30 7d6a248f 2020-05-05 rsc static int
31 7d6a248f 2020-05-05 rsc dropsp(int tok)
32 7d6a248f 2020-05-05 rsc {
33 7d6a248f 2020-05-05 rsc while(tok == ' ')
34 7d6a248f 2020-05-05 rsc tok = yylex();
35 7d6a248f 2020-05-05 rsc return tok;
36 7d6a248f 2020-05-05 rsc }
37 7d6a248f 2020-05-05 rsc
38 47d4646e 2020-05-05 rsc static void
39 47d4646e 2020-05-05 rsc syntax(int tok)
40 47d4646e 2020-05-05 rsc {
41 601e07b6 2020-05-05 rsc USED(tok);
42 601e07b6 2020-05-05 rsc yyerror("syntax error");
43 47d4646e 2020-05-05 rsc longjmp(yyjmp, 1);
44 47d4646e 2020-05-05 rsc }
45 47d4646e 2020-05-05 rsc
46 47d4646e 2020-05-05 rsc int
47 47d4646e 2020-05-05 rsc parse(void)
48 47d4646e 2020-05-05 rsc {
49 47d4646e 2020-05-05 rsc tree *t;
50 47d4646e 2020-05-05 rsc int tok;
51 47d4646e 2020-05-05 rsc
52 47d4646e 2020-05-05 rsc if(setjmp(yyjmp))
53 47d4646e 2020-05-05 rsc return 1;
54 47d4646e 2020-05-05 rsc
55 47d4646e 2020-05-05 rsc // rc: { return 1;}
56 47d4646e 2020-05-05 rsc // | line '\n' {return !compile($1);}
57 47d4646e 2020-05-05 rsc
58 7d6a248f 2020-05-05 rsc tok = dropsp(yylex());
59 47d4646e 2020-05-05 rsc if(tok == EOF)
60 47d4646e 2020-05-05 rsc return 1;
61 47d4646e 2020-05-05 rsc t = line(tok, &tok);
62 47d4646e 2020-05-05 rsc if(tok != '\n')
63 47d4646e 2020-05-05 rsc yyerror("missing newline at end of line");
64 47d4646e 2020-05-05 rsc yylval.tree = t;
65 47d4646e 2020-05-05 rsc return !compile(t);
66 47d4646e 2020-05-05 rsc }
67 47d4646e 2020-05-05 rsc
68 47d4646e 2020-05-05 rsc static tree*
69 47d4646e 2020-05-05 rsc line(int tok, int *ptok)
70 47d4646e 2020-05-05 rsc {
71 47d4646e 2020-05-05 rsc return cmds(tok, ptok, 0);
72 47d4646e 2020-05-05 rsc }
73 47d4646e 2020-05-05 rsc
74 47d4646e 2020-05-05 rsc static tree*
75 47d4646e 2020-05-05 rsc body(int tok, int *ptok)
76 47d4646e 2020-05-05 rsc {
77 47d4646e 2020-05-05 rsc return cmds(tok, ptok, 1);
78 47d4646e 2020-05-05 rsc }
79 47d4646e 2020-05-05 rsc
80 47d4646e 2020-05-05 rsc static tree*
81 47d4646e 2020-05-05 rsc cmds(int tok, int *ptok, int nlok)
82 47d4646e 2020-05-05 rsc {
83 47d4646e 2020-05-05 rsc tree *t, **last, *t2;
84 47d4646e 2020-05-05 rsc
85 47d4646e 2020-05-05 rsc // line: cmd
86 47d4646e 2020-05-05 rsc // | cmdsa line {$$=tree2(';', $1, $2);}
87 47d4646e 2020-05-05 rsc // cmdsa: cmd ';'
88 47d4646e 2020-05-05 rsc // | cmd '&' {$$=tree1('&', $1);}
89 47d4646e 2020-05-05 rsc
90 47d4646e 2020-05-05 rsc // body: cmd
91 47d4646e 2020-05-05 rsc // | cmdsan body {$$=tree2(';', $1, $2);}
92 47d4646e 2020-05-05 rsc // cmdsan: cmdsa
93 47d4646e 2020-05-05 rsc // | cmd '\n'
94 47d4646e 2020-05-05 rsc
95 47d4646e 2020-05-05 rsc t = nil;
96 47d4646e 2020-05-05 rsc last = nil;
97 47d4646e 2020-05-05 rsc for(;;) {
98 47d4646e 2020-05-05 rsc t2 = cmd(tok, &tok);
99 47d4646e 2020-05-05 rsc if(tok == '&')
100 47d4646e 2020-05-05 rsc t2 = tree1('&', t2);
101 47d4646e 2020-05-05 rsc if(t2 != nil) {
102 47d4646e 2020-05-05 rsc // slot into list t
103 47d4646e 2020-05-05 rsc if(last == nil) {
104 47d4646e 2020-05-05 rsc t = t2;
105 47d4646e 2020-05-05 rsc last = &t;
106 47d4646e 2020-05-05 rsc } else {
107 47d4646e 2020-05-05 rsc *last = tree2(';', *last, t2);
108 47d4646e 2020-05-05 rsc last = &(*last)->child[1];
109 47d4646e 2020-05-05 rsc }
110 47d4646e 2020-05-05 rsc }
111 47d4646e 2020-05-05 rsc if(tok != ';' && tok != '&' && (!nlok || tok != '\n'))
112 47d4646e 2020-05-05 rsc break;
113 47d4646e 2020-05-05 rsc tok = yylex();
114 47d4646e 2020-05-05 rsc }
115 47d4646e 2020-05-05 rsc *ptok = tok;
116 47d4646e 2020-05-05 rsc return t;
117 47d4646e 2020-05-05 rsc }
118 47d4646e 2020-05-05 rsc
119 47d4646e 2020-05-05 rsc static tree*
120 47d4646e 2020-05-05 rsc brace(int tok)
121 47d4646e 2020-05-05 rsc {
122 47d4646e 2020-05-05 rsc tree *t;
123 47d4646e 2020-05-05 rsc
124 47d4646e 2020-05-05 rsc // brace: '{' body '}' {$$=tree1(BRACE, $2);}
125 47d4646e 2020-05-05 rsc
126 7d6a248f 2020-05-05 rsc tok = dropsp(tok);
127 47d4646e 2020-05-05 rsc if(tok != '{')
128 47d4646e 2020-05-05 rsc syntax(tok);
129 47d4646e 2020-05-05 rsc t = body(yylex(), &tok);
130 47d4646e 2020-05-05 rsc if(tok != '}')
131 47d4646e 2020-05-05 rsc syntax(tok);
132 47d4646e 2020-05-05 rsc return tree1(BRACE, t);
133 47d4646e 2020-05-05 rsc }
134 47d4646e 2020-05-05 rsc
135 47d4646e 2020-05-05 rsc static tree*
136 47d4646e 2020-05-05 rsc paren(int tok)
137 47d4646e 2020-05-05 rsc {
138 47d4646e 2020-05-05 rsc tree *t;
139 47d4646e 2020-05-05 rsc
140 47d4646e 2020-05-05 rsc // paren: '(' body ')' {$$=tree1(PCMD, $2);}
141 47d4646e 2020-05-05 rsc
142 7d6a248f 2020-05-05 rsc tok = dropsp(tok);
143 47d4646e 2020-05-05 rsc if(tok != '(')
144 47d4646e 2020-05-05 rsc syntax(tok);
145 47d4646e 2020-05-05 rsc t = body(yylex(), &tok);
146 47d4646e 2020-05-05 rsc if(tok != ')')
147 47d4646e 2020-05-05 rsc syntax(tok);
148 47d4646e 2020-05-05 rsc return tree1(PCMD, t);
149 47d4646e 2020-05-05 rsc }
150 47d4646e 2020-05-05 rsc
151 47d4646e 2020-05-05 rsc static tree*
152 47d4646e 2020-05-05 rsc epilog(int tok, int *ptok)
153 47d4646e 2020-05-05 rsc {
154 47d4646e 2020-05-05 rsc tree *t, *r;
155 47d4646e 2020-05-05 rsc
156 47d4646e 2020-05-05 rsc // epilog: {$$=0;}
157 47d4646e 2020-05-05 rsc // | redir epilog {$$=mung2($1, $1->child[0], $2);}
158 47d4646e 2020-05-05 rsc
159 47d4646e 2020-05-05 rsc if(tok != REDIR && tok != DUP) {
160 47d4646e 2020-05-05 rsc *ptok = tok;
161 47d4646e 2020-05-05 rsc return nil;
162 47d4646e 2020-05-05 rsc }
163 47d4646e 2020-05-05 rsc
164 47d4646e 2020-05-05 rsc r = yyredir(tok, &tok);
165 47d4646e 2020-05-05 rsc t = epilog(tok, &tok);
166 47d4646e 2020-05-05 rsc *ptok = tok;
167 47d4646e 2020-05-05 rsc return mung2(r, r->child[0], t);
168 47d4646e 2020-05-05 rsc }
169 47d4646e 2020-05-05 rsc
170 47d4646e 2020-05-05 rsc static tree*
171 47d4646e 2020-05-05 rsc yyredir(int tok, int *ptok)
172 47d4646e 2020-05-05 rsc {
173 47d4646e 2020-05-05 rsc tree *r, *w;
174 47d4646e 2020-05-05 rsc
175 47d4646e 2020-05-05 rsc // redir: REDIR word {$$=mung1($1, $1->rtype==HERE?heredoc($2):$2);}
176 47d4646e 2020-05-05 rsc // | DUP
177 47d4646e 2020-05-05 rsc
178 47d4646e 2020-05-05 rsc switch(tok) {
179 47d4646e 2020-05-05 rsc default:
180 47d4646e 2020-05-05 rsc syntax(tok);
181 47d4646e 2020-05-05 rsc case DUP:
182 47d4646e 2020-05-05 rsc r = yylval.tree;
183 7d6a248f 2020-05-05 rsc *ptok = dropsp(yylex());
184 47d4646e 2020-05-05 rsc break;
185 47d4646e 2020-05-05 rsc case REDIR:
186 47d4646e 2020-05-05 rsc r = yylval.tree;
187 ff74f7cd 2020-05-05 rsc w = yyword(yylex(), &tok, 1);
188 7d6a248f 2020-05-05 rsc *ptok = dropsp(tok);
189 47d4646e 2020-05-05 rsc r = mung1(r, r->rtype==HERE?heredoc(w):w);
190 47d4646e 2020-05-05 rsc break;
191 47d4646e 2020-05-05 rsc }
192 47d4646e 2020-05-05 rsc return r;
193 47d4646e 2020-05-05 rsc }
194 47d4646e 2020-05-05 rsc
195 47d4646e 2020-05-05 rsc static tree*
196 47d4646e 2020-05-05 rsc cmd(int tok, int *ptok)
197 47d4646e 2020-05-05 rsc {
198 7d6a248f 2020-05-05 rsc int op;
199 7d6a248f 2020-05-05 rsc tree *t1, *t2;
200 7d6a248f 2020-05-05 rsc
201 7d6a248f 2020-05-05 rsc // | cmd ANDAND cmd {$$=tree2(ANDAND, $1, $3);}
202 7d6a248f 2020-05-05 rsc // | cmd OROR cmd {$$=tree2(OROR, $1, $3);}
203 7d6a248f 2020-05-05 rsc
204 601e07b6 2020-05-05 rsc tok = dropsp(tok);
205 601e07b6 2020-05-05 rsc t1 = cmd2(tok, &tok);
206 7d6a248f 2020-05-05 rsc while(tok == ANDAND || tok == OROR) {
207 7d6a248f 2020-05-05 rsc op = tok;
208 601e07b6 2020-05-05 rsc t2 = cmd2(dropnl(yylex()), &tok);
209 7d6a248f 2020-05-05 rsc t1 = tree2(op, t1, t2);
210 7d6a248f 2020-05-05 rsc }
211 7d6a248f 2020-05-05 rsc *ptok = tok;
212 7d6a248f 2020-05-05 rsc return t1;
213 7d6a248f 2020-05-05 rsc }
214 7d6a248f 2020-05-05 rsc
215 7d6a248f 2020-05-05 rsc static tree*
216 601e07b6 2020-05-05 rsc cmd2(int tok, int *ptok)
217 7d6a248f 2020-05-05 rsc {
218 7d6a248f 2020-05-05 rsc tree *t1, *t2, *t3;
219 7d6a248f 2020-05-05 rsc
220 7d6a248f 2020-05-05 rsc // | cmd PIPE cmd {$$=mung2($2, $1, $3);}
221 601e07b6 2020-05-05 rsc t1 = cmd3(tok, &tok);
222 7d6a248f 2020-05-05 rsc while(tok == PIPE) {
223 7d6a248f 2020-05-05 rsc t2 = yylval.tree;
224 601e07b6 2020-05-05 rsc t3 = cmd3(dropnl(yylex()), &tok);
225 7d6a248f 2020-05-05 rsc t1 = mung2(t2, t1, t3);
226 7d6a248f 2020-05-05 rsc }
227 7d6a248f 2020-05-05 rsc *ptok = tok;
228 7d6a248f 2020-05-05 rsc return t1;
229 7d6a248f 2020-05-05 rsc }
230 7d6a248f 2020-05-05 rsc
231 7d6a248f 2020-05-05 rsc static tree*
232 601e07b6 2020-05-05 rsc cmd3(int tok, int *ptok)
233 7d6a248f 2020-05-05 rsc {
234 7d6a248f 2020-05-05 rsc tree *t1, *t2, *t3, *t4;
235 7d6a248f 2020-05-05 rsc
236 7d6a248f 2020-05-05 rsc tok = dropsp(tok);
237 7d6a248f 2020-05-05 rsc switch(tok) {
238 7d6a248f 2020-05-05 rsc case ';':
239 7d6a248f 2020-05-05 rsc case '&':
240 7d6a248f 2020-05-05 rsc case '\n':
241 7d6a248f 2020-05-05 rsc *ptok = tok;
242 7d6a248f 2020-05-05 rsc return nil;
243 7d6a248f 2020-05-05 rsc
244 47d4646e 2020-05-05 rsc case IF:
245 47d4646e 2020-05-05 rsc // | IF paren {skipnl();} cmd {$$=mung2($1, $2, $4);}
246 47d4646e 2020-05-05 rsc // | IF NOT {skipnl();} cmd {$$=mung1($2, $4);}
247 47d4646e 2020-05-05 rsc t1 = yylval.tree;
248 7d6a248f 2020-05-05 rsc tok = dropsp(yylex());
249 47d4646e 2020-05-05 rsc if(tok == NOT) {
250 47d4646e 2020-05-05 rsc t1 = yylval.tree;
251 3caf5c23 2020-05-05 rsc t2 = cmd(dropnl(yylex()), ptok);
252 47d4646e 2020-05-05 rsc return mung1(t1, t2);
253 47d4646e 2020-05-05 rsc }
254 47d4646e 2020-05-05 rsc t2 = paren(tok);
255 3caf5c23 2020-05-05 rsc t3 = cmd(dropnl(yylex()), ptok);
256 47d4646e 2020-05-05 rsc return mung2(t1, t2, t3);
257 47d4646e 2020-05-05 rsc
258 47d4646e 2020-05-05 rsc case FOR:
259 47d4646e 2020-05-05 rsc // | FOR '(' word IN words ')' {skipnl();} cmd
260 47d4646e 2020-05-05 rsc // {$$=mung3($1, $3, $5 ? $5 : tree1(PAREN, $5), $8);}
261 47d4646e 2020-05-05 rsc // | FOR '(' word ')' {skipnl();} cmd
262 47d4646e 2020-05-05 rsc // {$$=mung3($1, $3, (tree *)0, $6);}
263 47d4646e 2020-05-05 rsc t1 = yylval.tree;
264 7d6a248f 2020-05-05 rsc tok = dropsp(yylex());
265 47d4646e 2020-05-05 rsc if(tok != '(')
266 47d4646e 2020-05-05 rsc syntax(tok);
267 ff74f7cd 2020-05-05 rsc t2 = yyword(yylex(), &tok, 1);
268 47d4646e 2020-05-05 rsc switch(tok) {
269 47d4646e 2020-05-05 rsc default:
270 47d4646e 2020-05-05 rsc syntax(tok);
271 47d4646e 2020-05-05 rsc case ')':
272 47d4646e 2020-05-05 rsc t3 = nil;
273 47d4646e 2020-05-05 rsc break;
274 47d4646e 2020-05-05 rsc case IN:
275 47d4646e 2020-05-05 rsc t3 = words(yylex(), &tok);
276 47d4646e 2020-05-05 rsc if(t3 == nil)
277 47d4646e 2020-05-05 rsc t3 = tree1(PAREN, nil);
278 47d4646e 2020-05-05 rsc if(tok != ')')
279 47d4646e 2020-05-05 rsc syntax(tok);
280 47d4646e 2020-05-05 rsc break;
281 47d4646e 2020-05-05 rsc }
282 3caf5c23 2020-05-05 rsc t4 = cmd(dropnl(yylex()), ptok);
283 47d4646e 2020-05-05 rsc return mung3(t1, t2, t3, t4);
284 47d4646e 2020-05-05 rsc
285 47d4646e 2020-05-05 rsc case WHILE:
286 47d4646e 2020-05-05 rsc // | WHILE paren {skipnl();} cmd
287 47d4646e 2020-05-05 rsc // {$$=mung2($1, $2, $4);}
288 47d4646e 2020-05-05 rsc t1 = yylval.tree;
289 47d4646e 2020-05-05 rsc t2 = paren(yylex());
290 3caf5c23 2020-05-05 rsc t3 = cmd(dropnl(yylex()), ptok);
291 47d4646e 2020-05-05 rsc return mung2(t1, t2, t3);
292 47d4646e 2020-05-05 rsc
293 47d4646e 2020-05-05 rsc case SWITCH:
294 47d4646e 2020-05-05 rsc // | SWITCH word {skipnl();} brace
295 47d4646e 2020-05-05 rsc // {$$=tree2(SWITCH, $2, $4);}
296 ff74f7cd 2020-05-05 rsc t1 = yyword(yylex(), &tok, 1);
297 3caf5c23 2020-05-05 rsc tok = dropnl(tok); // doesn't work in yacc grammar but works here!
298 47d4646e 2020-05-05 rsc t2 = brace(tok);
299 7d6a248f 2020-05-05 rsc *ptok = dropsp(yylex());
300 47d4646e 2020-05-05 rsc return tree2(SWITCH, t1, t2);
301 47d4646e 2020-05-05 rsc // Note: cmd: a && for(x) y && b is a && {for (x) {y && b}}.
302 47d4646e 2020-05-05 rsc return cmd(tok, ptok);
303 47d4646e 2020-05-05 rsc
304 47d4646e 2020-05-05 rsc case FN:
305 47d4646e 2020-05-05 rsc // | FN words brace {$$=tree2(FN, $2, $3);}
306 47d4646e 2020-05-05 rsc // | FN words {$$=tree1(FN, $2);}
307 47d4646e 2020-05-05 rsc t1 = words(yylex(), &tok);
308 47d4646e 2020-05-05 rsc if(tok != '{') {
309 47d4646e 2020-05-05 rsc *ptok = tok;
310 47d4646e 2020-05-05 rsc return tree1(FN, t1);
311 47d4646e 2020-05-05 rsc }
312 47d4646e 2020-05-05 rsc t2 = brace(tok);
313 7d6a248f 2020-05-05 rsc *ptok = dropsp(yylex());
314 47d4646e 2020-05-05 rsc return tree2(FN, t1, t2);
315 47d4646e 2020-05-05 rsc
316 47d4646e 2020-05-05 rsc case TWIDDLE:
317 47d4646e 2020-05-05 rsc // | TWIDDLE word words {$$=mung2($1, $2, $3);}
318 47d4646e 2020-05-05 rsc t1 = yylval.tree;
319 ff74f7cd 2020-05-05 rsc t2 = yyword(yylex(), &tok, 1);
320 47d4646e 2020-05-05 rsc t3 = words(tok, ptok);
321 47d4646e 2020-05-05 rsc return mung2(t1, t2, t3);
322 47d4646e 2020-05-05 rsc
323 47d4646e 2020-05-05 rsc case BANG:
324 47d4646e 2020-05-05 rsc case SUBSHELL:
325 47d4646e 2020-05-05 rsc // | BANG cmd {$$=mung1($1, $2);}
326 47d4646e 2020-05-05 rsc // | SUBSHELL cmd {$$=mung1($1, $2);}
327 601e07b6 2020-05-05 rsc // Note: cmd2: ! x | y is !{x | y} not {!x} | y.
328 47d4646e 2020-05-05 rsc t1 = yylval.tree;
329 601e07b6 2020-05-05 rsc return mung1(t1, cmd2(yylex(), ptok));
330 47d4646e 2020-05-05 rsc
331 47d4646e 2020-05-05 rsc case REDIR:
332 47d4646e 2020-05-05 rsc case DUP:
333 47d4646e 2020-05-05 rsc // | redir cmd %prec BANG {$$=mung2($1, $1->child[0], $2);}
334 601e07b6 2020-05-05 rsc // Note: cmd2: {>x echo a | tr a-z A-Z} writes A to x.
335 47d4646e 2020-05-05 rsc t1 = yyredir(tok, &tok);
336 601e07b6 2020-05-05 rsc t2 = cmd2(tok, ptok);
337 47d4646e 2020-05-05 rsc return mung2(t1, t1->child[0], t2);
338 47d4646e 2020-05-05 rsc
339 47d4646e 2020-05-05 rsc case '{':
340 47d4646e 2020-05-05 rsc // | brace epilog {$$=epimung($1, $2);}
341 47d4646e 2020-05-05 rsc t1 = brace(tok);
342 7d6a248f 2020-05-05 rsc tok = dropsp(yylex());
343 47d4646e 2020-05-05 rsc t2 = epilog(tok, ptok);
344 47d4646e 2020-05-05 rsc return epimung(t1, t2);
345 47d4646e 2020-05-05 rsc }
346 47d4646e 2020-05-05 rsc
347 47d4646e 2020-05-05 rsc if(!iswordtok(tok)) {
348 47d4646e 2020-05-05 rsc *ptok = tok;
349 47d4646e 2020-05-05 rsc return nil;
350 47d4646e 2020-05-05 rsc }
351 47d4646e 2020-05-05 rsc
352 47d4646e 2020-05-05 rsc // cmd: ...
353 47d4646e 2020-05-05 rsc // | simple {$$=simplemung($1);}
354 47d4646e 2020-05-05 rsc // | assign cmd %prec BANG {$$=mung3($1, $1->child[0], $1->child[1], $2);}
355 47d4646e 2020-05-05 rsc // assign: first '=' word {$$=tree2('=', $1, $3);}
356 47d4646e 2020-05-05 rsc // Note: first is same as word except for disallowing all the leading keywords,
357 47d4646e 2020-05-05 rsc // but all those keywords have been picked off in the switch above.
358 47d4646e 2020-05-05 rsc // Except NOT, but disallowing that in yacc was likely a mistake anyway:
359 47d4646e 2020-05-05 rsc // there's no ambiguity in not=1 or not x y z.
360 ff74f7cd 2020-05-05 rsc t1 = yyword(tok, &tok, 0);
361 47d4646e 2020-05-05 rsc if(tok == '=') {
362 47d4646e 2020-05-05 rsc // assignment
363 601e07b6 2020-05-05 rsc // Note: cmd2: {x=1 true | echo $x} echoes 1.
364 ff74f7cd 2020-05-05 rsc t1 = tree2('=', t1, yyword(yylex(), &tok, 1));
365 601e07b6 2020-05-05 rsc t2 = cmd2(tok, ptok);
366 47d4646e 2020-05-05 rsc return mung3(t1, t1->child[0], t1->child[1], t2);
367 47d4646e 2020-05-05 rsc }
368 47d4646e 2020-05-05 rsc
369 47d4646e 2020-05-05 rsc // simple: first
370 47d4646e 2020-05-05 rsc // | simple word {$$=tree2(ARGLIST, $1, $2);}
371 47d4646e 2020-05-05 rsc // | simple redir {$$=tree2(ARGLIST, $1, $2);}
372 47d4646e 2020-05-05 rsc for(;;) {
373 47d4646e 2020-05-05 rsc if(tok == REDIR || tok == DUP) {
374 47d4646e 2020-05-05 rsc t1 = tree2(ARGLIST, t1, yyredir(tok, &tok));
375 47d4646e 2020-05-05 rsc } else if(iswordtok(tok)) {
376 ff74f7cd 2020-05-05 rsc t1 = tree2(ARGLIST, t1, yyword(tok, &tok, 1));
377 47d4646e 2020-05-05 rsc } else {
378 47d4646e 2020-05-05 rsc break;
379 47d4646e 2020-05-05 rsc }
380 47d4646e 2020-05-05 rsc }
381 47d4646e 2020-05-05 rsc *ptok = tok;
382 47d4646e 2020-05-05 rsc return simplemung(t1);
383 47d4646e 2020-05-05 rsc }
384 47d4646e 2020-05-05 rsc
385 47d4646e 2020-05-05 rsc static tree*
386 47d4646e 2020-05-05 rsc words(int tok, int *ptok)
387 47d4646e 2020-05-05 rsc {
388 47d4646e 2020-05-05 rsc tree *t;
389 47d4646e 2020-05-05 rsc
390 47d4646e 2020-05-05 rsc // words: {$$=(tree*)0;}
391 47d4646e 2020-05-05 rsc // | words word {$$=tree2(WORDS, $1, $2);}
392 47d4646e 2020-05-05 rsc
393 47d4646e 2020-05-05 rsc t = nil;
394 7d6a248f 2020-05-05 rsc tok = dropsp(tok);
395 47d4646e 2020-05-05 rsc while(iswordtok(tok))
396 ff74f7cd 2020-05-05 rsc t = tree2(WORDS, t, yyword(tok, &tok, 1));
397 47d4646e 2020-05-05 rsc *ptok = tok;
398 47d4646e 2020-05-05 rsc return t;
399 47d4646e 2020-05-05 rsc }
400 47d4646e 2020-05-05 rsc
401 47d4646e 2020-05-05 rsc static tree*
402 ff74f7cd 2020-05-05 rsc yyword(int tok, int *ptok, int eqok)
403 47d4646e 2020-05-05 rsc {
404 47d4646e 2020-05-05 rsc tree *t;
405 47d4646e 2020-05-05 rsc
406 47d4646e 2020-05-05 rsc // word: keyword {lastword=1; $1->type=WORD;}
407 47d4646e 2020-05-05 rsc // | comword
408 47d4646e 2020-05-05 rsc // | word '^' word {$$=tree2('^', $1, $3);}
409 47d4646e 2020-05-05 rsc // comword: '$' word {$$=tree1('$', $2);}
410 47d4646e 2020-05-05 rsc // | '$' word SUB words ')' {$$=tree2(SUB, $2, $4);}
411 47d4646e 2020-05-05 rsc // | '"' word {$$=tree1('"', $2);}
412 47d4646e 2020-05-05 rsc // | COUNT word {$$=tree1(COUNT, $2);}
413 47d4646e 2020-05-05 rsc // | WORD
414 47d4646e 2020-05-05 rsc // | '`' brace {$$=tree1('`', $2);}
415 47d4646e 2020-05-05 rsc // | '(' words ')' {$$=tree1(PAREN, $2);}
416 47d4646e 2020-05-05 rsc // | REDIR brace {$$=mung1($1, $2); $$->type=PIPEFD;}
417 47d4646e 2020-05-05 rsc // keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN
418 47d4646e 2020-05-05 rsc //
419 47d4646e 2020-05-05 rsc // factored into:
420 47d4646e 2020-05-05 rsc //
421 47d4646e 2020-05-05 rsc // word: word1
422 47d4646e 2020-05-05 rsc // | word '^' word1
423 47d4646e 2020-05-05 rsc //
424 47d4646e 2020-05-05 rsc // word1: keyword | comword
425 47d4646e 2020-05-05 rsc
426 47d4646e 2020-05-05 rsc t = word1(tok, &tok);
427 ff74f7cd 2020-05-05 rsc if(tok == '=' && !eqok)
428 ff74f7cd 2020-05-05 rsc goto out;
429 7d6a248f 2020-05-05 rsc for(;;) {
430 7d6a248f 2020-05-05 rsc if(iswordtok(tok)) {
431 601e07b6 2020-05-05 rsc // No free carats around parens.
432 601e07b6 2020-05-05 rsc if(t->type == PAREN || tok == '(')
433 601e07b6 2020-05-05 rsc syntax(tok);
434 7d6a248f 2020-05-05 rsc t = tree2('^', t, word1(tok, &tok));
435 7d6a248f 2020-05-05 rsc continue;
436 7d6a248f 2020-05-05 rsc }
437 7d6a248f 2020-05-05 rsc tok = dropsp(tok);
438 7d6a248f 2020-05-05 rsc if(tok == '^') {
439 7d6a248f 2020-05-05 rsc t = tree2('^', t, word1(yylex(), &tok));
440 7d6a248f 2020-05-05 rsc continue;
441 7d6a248f 2020-05-05 rsc }
442 7d6a248f 2020-05-05 rsc break;
443 7d6a248f 2020-05-05 rsc }
444 ff74f7cd 2020-05-05 rsc out:
445 7d6a248f 2020-05-05 rsc *ptok = dropsp(tok);
446 47d4646e 2020-05-05 rsc return t;
447 47d4646e 2020-05-05 rsc }
448 47d4646e 2020-05-05 rsc
449 47d4646e 2020-05-05 rsc static tree*
450 47d4646e 2020-05-05 rsc word1(int tok, int *ptok)
451 47d4646e 2020-05-05 rsc {
452 47d4646e 2020-05-05 rsc tree *w, *sub, *t;
453 47d4646e 2020-05-05 rsc
454 7d6a248f 2020-05-05 rsc tok = dropsp(tok);
455 47d4646e 2020-05-05 rsc switch(tok) {
456 47d4646e 2020-05-05 rsc default:
457 47d4646e 2020-05-05 rsc syntax(tok);
458 47d4646e 2020-05-05 rsc
459 47d4646e 2020-05-05 rsc case WORD:
460 47d4646e 2020-05-05 rsc case FOR:
461 47d4646e 2020-05-05 rsc case IN:
462 47d4646e 2020-05-05 rsc case WHILE:
463 47d4646e 2020-05-05 rsc case IF:
464 47d4646e 2020-05-05 rsc case NOT:
465 47d4646e 2020-05-05 rsc case TWIDDLE:
466 47d4646e 2020-05-05 rsc case BANG:
467 47d4646e 2020-05-05 rsc case SUBSHELL:
468 47d4646e 2020-05-05 rsc case SWITCH:
469 47d4646e 2020-05-05 rsc case FN:
470 47d4646e 2020-05-05 rsc // | WORD
471 47d4646e 2020-05-05 rsc // keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN
472 47d4646e 2020-05-05 rsc t = yylval.tree;
473 47d4646e 2020-05-05 rsc t->type = WORD;
474 47d4646e 2020-05-05 rsc *ptok = yylex();
475 47d4646e 2020-05-05 rsc return t;
476 47d4646e 2020-05-05 rsc
477 ff74f7cd 2020-05-05 rsc case '=':
478 ff74f7cd 2020-05-05 rsc *ptok = yylex();
479 ff74f7cd 2020-05-05 rsc return token("=", WORD);
480 ff74f7cd 2020-05-05 rsc
481 47d4646e 2020-05-05 rsc case '$':
482 47d4646e 2020-05-05 rsc // comword: '$' word1 {$$=tree1('$', $2);}
483 47d4646e 2020-05-05 rsc // | '$' word1 SUB words ')' {$$=tree2(SUB, $2, $4);}
484 47d4646e 2020-05-05 rsc w = word1(yylex(), &tok);
485 7d6a248f 2020-05-05 rsc if(tok == '(') {
486 47d4646e 2020-05-05 rsc sub = words(yylex(), &tok);
487 47d4646e 2020-05-05 rsc if(tok != ')')
488 47d4646e 2020-05-05 rsc syntax(tok);
489 47d4646e 2020-05-05 rsc *ptok = yylex();
490 47d4646e 2020-05-05 rsc return tree2(SUB, w, sub);
491 47d4646e 2020-05-05 rsc }
492 47d4646e 2020-05-05 rsc *ptok = tok;
493 47d4646e 2020-05-05 rsc return tree1('$', w);
494 47d4646e 2020-05-05 rsc
495 47d4646e 2020-05-05 rsc case '"':
496 47d4646e 2020-05-05 rsc // | '"' word1 {$$=tree1('"', $2);}
497 47d4646e 2020-05-05 rsc return tree1('"', word1(yylex(), ptok));
498 47d4646e 2020-05-05 rsc
499 47d4646e 2020-05-05 rsc case COUNT:
500 47d4646e 2020-05-05 rsc // | COUNT word1 {$$=tree1(COUNT, $2);}
501 47d4646e 2020-05-05 rsc return tree1(COUNT, word1(yylex(), ptok));
502 47d4646e 2020-05-05 rsc
503 47d4646e 2020-05-05 rsc case '`':
504 47d4646e 2020-05-05 rsc // | '`' brace {$$=tree1('`', $2);}
505 47d4646e 2020-05-05 rsc t = tree1('`', brace(yylex()));
506 47d4646e 2020-05-05 rsc *ptok = yylex();
507 47d4646e 2020-05-05 rsc return t;
508 47d4646e 2020-05-05 rsc
509 47d4646e 2020-05-05 rsc case '(':
510 47d4646e 2020-05-05 rsc // | '(' words ')' {$$=tree1(PAREN, $2);}
511 47d4646e 2020-05-05 rsc t = tree1(PAREN, words(yylex(), &tok));
512 47d4646e 2020-05-05 rsc if(tok != ')')
513 47d4646e 2020-05-05 rsc syntax(tok);
514 47d4646e 2020-05-05 rsc *ptok = yylex();
515 47d4646e 2020-05-05 rsc return t;
516 47d4646e 2020-05-05 rsc
517 47d4646e 2020-05-05 rsc case REDIRW:
518 47d4646e 2020-05-05 rsc // | REDIRW brace {$$=mung1($1, $2); $$->type=PIPEFD;}
519 47d4646e 2020-05-05 rsc t = yylval.tree;
520 47d4646e 2020-05-05 rsc t = mung1(t, brace(yylex()));
521 47d4646e 2020-05-05 rsc t->type = PIPEFD;
522 47d4646e 2020-05-05 rsc *ptok = yylex();
523 47d4646e 2020-05-05 rsc return t;
524 47d4646e 2020-05-05 rsc }
525 47d4646e 2020-05-05 rsc }
526 47d4646e 2020-05-05 rsc
527 47d4646e 2020-05-05 rsc static int
528 47d4646e 2020-05-05 rsc iswordtok(int tok)
529 47d4646e 2020-05-05 rsc {
530 47d4646e 2020-05-05 rsc switch(tok) {
531 47d4646e 2020-05-05 rsc case FOR:
532 47d4646e 2020-05-05 rsc case IN:
533 47d4646e 2020-05-05 rsc case WHILE:
534 47d4646e 2020-05-05 rsc case IF:
535 47d4646e 2020-05-05 rsc case NOT:
536 47d4646e 2020-05-05 rsc case TWIDDLE:
537 47d4646e 2020-05-05 rsc case BANG:
538 47d4646e 2020-05-05 rsc case SUBSHELL:
539 47d4646e 2020-05-05 rsc case SWITCH:
540 47d4646e 2020-05-05 rsc case FN:
541 47d4646e 2020-05-05 rsc case '$':
542 47d4646e 2020-05-05 rsc case '"':
543 47d4646e 2020-05-05 rsc case COUNT:
544 47d4646e 2020-05-05 rsc case WORD:
545 47d4646e 2020-05-05 rsc case '`':
546 47d4646e 2020-05-05 rsc case '(':
547 47d4646e 2020-05-05 rsc case REDIRW:
548 ff74f7cd 2020-05-05 rsc case '=':
549 47d4646e 2020-05-05 rsc return 1;
550 47d4646e 2020-05-05 rsc }
551 47d4646e 2020-05-05 rsc return 0;
552 47d4646e 2020-05-05 rsc }