import parse-define.patch
[nedit-bw.git] / parseEnhance2.diff
bloba35968073a1b22bfba6447d2c928307a0cdbd564
1 ---
3 source/parse.y | 442 ++++++++++++++++++++-------------------------------------
4 1 file changed, 161 insertions(+), 281 deletions(-)
6 diff --quilt old/source/parse.y new/source/parse.y
7 --- old/source/parse.y
8 +++ new/source/parse.y
9 @@ -85,19 +85,23 @@ static int nextSymIsField = 0;
11 %union {
12 Symbol *sym;
13 Inst *inst;
14 int nArgs;
15 + enum operations oper;
16 AccumulatorData *acc;
18 %token <sym> NUMBER STRING SYMBOL FIELD
19 %token DELETE ARG_LOOKUP
20 -%token IF WHILE ELSE FOR BREAK CONTINUE RETURN
21 +%token IF WHILE DO ELSE FOR BREAK CONTINUE RETURN
22 %token <acc> DEFINE
23 -%type <nArgs> arglist catlist
24 -%type <inst> cond comastmts for while else and or arrayexpr
25 +%type <nArgs> arglistopt arglist catlist
26 +%type <inst> cond comastmts comastmtlst for while do else and or arrayexpr mark
27 %type <sym> evalsym
28 +%type <oper> operassign incrdecr
29 +%token <oper> '=' ADDEQ SUBEQ MULEQ DIVEQ MODEQ ANDEQ OREQ
30 +%token <oper> INCR DECR
32 %nonassoc IF_NO_ELSE
33 %nonassoc ELSE
35 %nonassoc ';'
36 @@ -178,36 +182,42 @@ define: DEFINE {
37 $4->value.val.prog = prog;
40 stmtend: '\n' | ';'
42 +mark: /* nothing */ { $$ = GetPC(); } /* record instruction address */
43 + ;
44 stmt: ';' blank
45 | simpstmt stmtend blank
46 - | IF '(' cond ')' blank block %prec IF_NO_ELSE {
47 - SET_BR_OFF($3, GetPC());
48 + | IF blank '(' cond ')' blank block %prec IF_NO_ELSE {
49 + SET_BR_OFF($4, GetPC());
51 - | IF '(' cond ')' blank block else blank block %prec ELSE {
52 - SET_BR_OFF($3, ($7+1)); SET_BR_OFF($7, GetPC());
53 + | IF blank '(' cond ')' blank block else block %prec ELSE {
54 + SET_BR_OFF($4, ($8+1)); SET_BR_OFF($8, GetPC());
56 | while '(' cond ')' blank block {
57 ADD_OP(OP_BRANCH); ADD_BR_OFF($1);
58 SET_BR_OFF($3, GetPC()); FillLoopAddrs(GetPC(), $1);
60 + | do block WHILE blank '(' mark cond ')' stmtend blank {
61 + ADD_OP(OP_BRANCH); ADD_BR_OFF($1);
62 + SET_BR_OFF($7, GetPC()); FillLoopAddrs(GetPC(), $6);
63 + }
64 | for '(' comastmts ';' cond ';' comastmts ')' blank block {
65 FillLoopAddrs(GetPC()+2+($7-($5+1)), GetPC());
66 SwapCode($5+1, $7, GetPC());
67 ADD_OP(OP_BRANCH); ADD_BR_OFF($3); SET_BR_OFF($5, GetPC());
69 - | for '(' SYMBOL IN arrayexpr ')' {
70 + | for '(' blank SYMBOL IN blank arrayexpr blank ')' {
71 Symbol *iterSym = InstallIteratorSymbol();
72 ADD_OP(OP_BEGIN_ARRAY_ITER); ADD_SYM(iterSym);
73 - ADD_OP(OP_ARRAY_ITER); ADD_SYM($3); ADD_SYM(iterSym); ADD_BR_OFF(0);
74 + ADD_OP(OP_ARRAY_ITER); ADD_SYM($4); ADD_SYM(iterSym); ADD_BR_OFF(0);
76 blank block {
77 - ADD_OP(OP_BRANCH); ADD_BR_OFF($5+2);
78 - SET_BR_OFF($5+5, GetPC());
79 - FillLoopAddrs(GetPC(), $5+2);
80 + ADD_OP(OP_BRANCH); ADD_BR_OFF($7+2);
81 + SET_BR_OFF($7+5, GetPC());
82 + FillLoopAddrs(GetPC(), $7+2);
84 | BREAK stmtend blank {
85 ADD_OP(OP_BRANCH); ADD_BR_OFF(0);
86 if (AddBreakAddr(GetPC()-1)) {
87 yyerror("break outside loop"); YYERROR;
88 @@ -224,229 +234,130 @@ stmt: ';' blank
90 | RETURN stmtend blank {
91 ADD_OP(OP_RETURN_NO_VAL);
94 -simpstmt: SYMBOL '=' expr {
96 +operassign: ADDEQ { $$ = OP_ADD; }
97 + | SUBEQ { $$ = OP_SUB; }
98 + | MULEQ { $$ = OP_MUL; }
99 + | DIVEQ { $$ = OP_DIV; }
100 + | MODEQ { $$ = OP_MOD; }
101 + | ANDEQ { $$ = OP_BIT_AND; }
102 + | OREQ { $$ = OP_BIT_OR; }
104 +incrdecr: INCR { $$ = OP_INCR; }
105 + | DECR { $$ = OP_DECR; }
108 +simpstmt: /* simple variable assignment, op-assignment, incr/decrement */
109 + SYMBOL '=' blank expr {
110 ADD_OP(OP_ASSIGN); ADD_SYM($1);
112 - | evalsym ADDEQ expr {
113 - ADD_OP(OP_ADD); ADD_OP(OP_ASSIGN); ADD_SYM($1);
115 - | evalsym SUBEQ expr {
116 - ADD_OP(OP_SUB); ADD_OP(OP_ASSIGN); ADD_SYM($1);
118 - | evalsym MULEQ expr {
119 - ADD_OP(OP_MUL); ADD_OP(OP_ASSIGN); ADD_SYM($1);
120 + | evalsym operassign blank expr {
121 + ADD_OP($2); ADD_OP(OP_ASSIGN); ADD_SYM($1);
123 - | evalsym DIVEQ expr {
124 - ADD_OP(OP_DIV); ADD_OP(OP_ASSIGN); ADD_SYM($1);
125 + | incrdecr blank SYMBOL {
126 + ADD_OP(OP_PUSH_SYM); ADD_SYM($3); ADD_OP($1);
127 + ADD_OP(OP_ASSIGN); ADD_SYM($3);
129 - | evalsym MODEQ expr {
130 - ADD_OP(OP_MOD); ADD_OP(OP_ASSIGN); ADD_SYM($1);
132 - | evalsym ANDEQ expr {
133 - ADD_OP(OP_BIT_AND); ADD_OP(OP_ASSIGN); ADD_SYM($1);
135 - | evalsym OREQ expr {
136 - ADD_OP(OP_BIT_OR); ADD_OP(OP_ASSIGN); ADD_SYM($1);
137 + | SYMBOL incrdecr {
138 + ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP($2);
139 + ADD_OP(OP_ASSIGN); ADD_SYM($1);
141 - | DELETE arraylv '[' arglist ']' {
142 + /* delete array entry simple statement */
143 + | DELETE arraylv '[' arglistopt ']' {
144 ADD_OP(OP_ARRAY_DELETE); ADD_IMMED($4);
146 | DELETE arraylv dot field {
147 ADD_OP(OP_ARRAY_DELETE); ADD_IMMED(1);
149 -/* array[index] assignment */
150 - | initarraylv '[' arglist ']' '=' expr {
151 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
153 - | initarraylv '[' arglist ']' ADDEQ expr {
154 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
155 - ADD_OP(OP_ADD);
156 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
158 - | initarraylv '[' arglist ']' SUBEQ expr {
159 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
160 - ADD_OP(OP_SUB);
161 + /* array[index] assignment, op-assignment, incr/decrement */
162 + | initarraylv '[' arglistopt ']' '=' blank expr {
163 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
165 - | initarraylv '[' arglist ']' MULEQ expr {
166 + | initarraylv '[' arglistopt ']' operassign blank expr {
167 ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
168 - ADD_OP(OP_MUL);
169 + ADD_OP($5);
170 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
172 - | initarraylv '[' arglist ']' DIVEQ expr {
173 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
174 - ADD_OP(OP_DIV);
175 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
177 - | initarraylv '[' arglist ']' MODEQ expr {
178 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
179 - ADD_OP(OP_MOD);
180 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
182 - | initarraylv '[' arglist ']' ANDEQ expr {
183 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
184 - ADD_OP(OP_BIT_AND);
185 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
187 - | initarraylv '[' arglist ']' OREQ expr {
188 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
189 - ADD_OP(OP_BIT_OR);
190 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
192 - | initarraylv '[' arglist ']' INCR {
193 + | initarraylv '[' arglistopt ']' incrdecr {
194 ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED($3);
195 - ADD_OP(OP_INCR);
196 + ADD_OP($5);
197 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
199 - | initarraylv '[' arglist ']' DECR {
200 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED($3);
201 - ADD_OP(OP_DECR);
202 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
203 + | incrdecr blank initarraylv '[' arglistopt ']' {
204 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED($5);
205 + ADD_OP($1);
206 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($5);
208 - | INCR initarraylv '[' arglist ']' {
209 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED($4);
210 - ADD_OP(OP_INCR);
211 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($4);
213 - | DECR initarraylv '[' arglist ']' {
214 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED($4);
215 - ADD_OP(OP_DECR);
216 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($4);
218 -/* array.field assignment */
219 - | initarraylv dot field '=' expr {
220 + /* array.field assignment, op-assignment, incr/decrement */
221 + | initarraylv dot field '=' blank expr {
222 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
224 - | initarraylv dot field ADDEQ expr {
225 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
226 - ADD_OP(OP_ADD);
227 + | initarraylv dot field operassign blank expr {
228 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1);ADD_IMMED(1);
229 + ADD_OP($4);
230 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
232 - | initarraylv dot field SUBEQ expr {
233 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
234 - ADD_OP(OP_SUB);
235 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
237 - | initarraylv dot field MULEQ expr {
238 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
239 - ADD_OP(OP_MUL);
240 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
242 - | initarraylv dot field DIVEQ expr {
243 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
244 - ADD_OP(OP_DIV);
245 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
247 - | initarraylv dot field MODEQ expr {
248 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
249 - ADD_OP(OP_MOD);
250 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
252 - | initarraylv dot field ANDEQ expr {
253 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
254 - ADD_OP(OP_BIT_AND);
255 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
257 - | initarraylv dot field OREQ expr {
258 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
259 - ADD_OP(OP_BIT_OR);
260 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
262 - | initarraylv dot field INCR {
263 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
264 - ADD_OP(OP_INCR);
265 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
267 - | initarraylv dot field DECR {
268 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
269 - ADD_OP(OP_DECR);
270 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
272 - | INCR initarraylv dot field {
273 + | initarraylv dot field incrdecr {
274 ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
275 - ADD_OP(OP_INCR);
276 + ADD_OP($4);
277 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
279 - | DECR initarraylv dot field {
280 + | incrdecr blank initarraylv dot field {
281 ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
282 - ADD_OP(OP_DECR);
283 + ADD_OP($1);
284 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
286 - | SYMBOL '(' arglist ')' {
287 + /* function call */
288 + | SYMBOL '(' arglistopt ')' {
289 ADD_OP(OP_SUBR_CALL);
290 ADD_SYM(PromoteToGlobal($1)); ADD_IMMED($3);
292 - | INCR SYMBOL {
293 - ADD_OP(OP_PUSH_SYM); ADD_SYM($2); ADD_OP(OP_INCR);
294 - ADD_OP(OP_ASSIGN); ADD_SYM($2);
296 - | SYMBOL INCR {
297 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP(OP_INCR);
298 - ADD_OP(OP_ASSIGN); ADD_SYM($1);
300 - | DECR SYMBOL {
301 - ADD_OP(OP_PUSH_SYM); ADD_SYM($2); ADD_OP(OP_DECR);
302 - ADD_OP(OP_ASSIGN); ADD_SYM($2);
304 - | SYMBOL DECR {
305 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP(OP_DECR);
306 - ADD_OP(OP_ASSIGN); ADD_SYM($1);
310 evalsym: SYMBOL {
311 $$ = $1; ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
314 -comastmts: /* nothing */ {
315 - $$ = GetPC();
317 - | simpstmt {
318 - $$ = GetPC();
320 - | comastmts ',' simpstmt {
321 - $$ = GetPC();
323 +comastmts: blank { $$ = GetPC(); }
324 + | blank comastmtlst { $$ = $2; }
326 -arglist: /* nothing */ {
327 - $$ = 0;
329 - | expr {
330 - $$ = 1;
332 - | arglist ',' expr {
333 - $$ = $1 + 1;
335 +comastmtlst: simpstmt blank { $$ = GetPC(); }
336 + | comastmtlst ',' blank simpstmt blank { $$ = GetPC(); }
339 +arglistopt: blank { $$ = 0; }
340 + | arglist { $$ = $1; }
342 +arglist: blank expr blank { $$ = 1; }
343 + | arglist ',' blank expr blank { $$ = $1 + 1; }
345 +catlist: numexpr %prec CONCAT { $$ = 1; }
346 + | catlist numexpr %prec CONCAT { $$ = $1 + 1; }
348 -catlist: numexpr %prec CONCAT {
349 - $$ = 1;
351 - | catlist numexpr %prec CONCAT {
352 - $$ = $1 + 1;
354 expr: catlist {
355 if ($1 > 1) {
356 ADD_OP(OP_CONCAT); ADD_IMMED($1);
360 initarraylv: SYMBOL {
361 ADD_OP(OP_PUSH_ARRAY_SYM); ADD_SYM($1); ADD_IMMED(1);
363 - | initarraylv '[' arglist ']' {
364 + | initarraylv '[' arglistopt ']' {
365 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
367 | initarraylv dot field {
368 ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
371 arraylv: SYMBOL {
372 ADD_OP(OP_PUSH_ARRAY_SYM); ADD_SYM($1); ADD_IMMED(0);
374 - | arraylv '[' arglist ']' {
375 + | arraylv '[' arglistopt ']' {
376 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
378 | arraylv dot field {
379 ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
381 @@ -462,134 +373,86 @@ field: FIELD {
383 arrayexpr: numexpr {
384 $$ = GetPC();
387 -numexpr: NUMBER {
388 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
390 - | STRING {
391 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
393 - | SYMBOL {
394 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
396 - | SYMBOL '(' arglist ')' {
397 +numexpr: '(' blank expr blank ')'
398 + | NUMBER { ADD_OP(OP_PUSH_SYM); ADD_SYM($1); }
399 + | STRING { ADD_OP(OP_PUSH_SYM); ADD_SYM($1); }
400 + | SYMBOL { ADD_OP(OP_PUSH_SYM); ADD_SYM($1); }
401 + | SYMBOL '(' arglistopt ')' {
402 ADD_OP(OP_SUBR_CALL);
403 ADD_SYM(PromoteToGlobal($1)); ADD_IMMED($3);
404 ADD_OP(OP_FETCH_RET_VAL);
406 - | '(' expr ')'
407 - | ARG_LOOKUP '[' numexpr ']' {
408 - ADD_OP(OP_PUSH_ARG);
410 - | ARG_LOOKUP '[' ']' {
411 - ADD_OP(OP_PUSH_ARG_COUNT);
413 - | ARG_LOOKUP {
414 - ADD_OP(OP_PUSH_ARG_ARRAY);
416 - | numexpr '[' arglist ']' {
417 + | ARG_LOOKUP '[' blank numexpr blank ']' { ADD_OP(OP_PUSH_ARG); }
418 + | ARG_LOOKUP '[' blank ']' { ADD_OP(OP_PUSH_ARG_COUNT); }
419 + | ARG_LOOKUP { ADD_OP(OP_PUSH_ARG_ARRAY); }
420 + | numexpr '[' arglistopt ']' {
421 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
423 | numexpr dot field {
424 ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
426 - | numexpr '+' numexpr {
427 - ADD_OP(OP_ADD);
429 - | numexpr '-' numexpr {
430 - ADD_OP(OP_SUB);
432 - | numexpr '*' numexpr {
433 - ADD_OP(OP_MUL);
435 - | numexpr '/' numexpr {
436 - ADD_OP(OP_DIV);
438 - | numexpr '%' numexpr {
439 - ADD_OP(OP_MOD);
441 - | numexpr POW numexpr {
442 - ADD_OP(OP_POWER);
444 - | '-' numexpr %prec UNARY_MINUS {
445 - ADD_OP(OP_NEGATE);
447 - | numexpr GT numexpr {
448 - ADD_OP(OP_GT);
450 - | numexpr GE numexpr {
451 - ADD_OP(OP_GE);
453 - | numexpr LT numexpr {
454 - ADD_OP(OP_LT);
456 - | numexpr LE numexpr {
457 - ADD_OP(OP_LE);
459 - | numexpr EQ numexpr {
460 - ADD_OP(OP_EQ);
462 - | numexpr NE numexpr {
463 - ADD_OP(OP_NE);
465 - | numexpr '&' numexpr {
466 - ADD_OP(OP_BIT_AND);
468 - | numexpr '|' numexpr {
469 - ADD_OP(OP_BIT_OR);
471 - | numexpr and numexpr %prec AND {
472 + | '-' blank numexpr %prec UNARY_MINUS { ADD_OP(OP_NEGATE); }
473 + | NOT blank numexpr { ADD_OP(OP_NOT); }
474 + | numexpr '+' blank numexpr { ADD_OP(OP_ADD); }
475 + | numexpr '-' blank numexpr { ADD_OP(OP_SUB); }
476 + | numexpr '*' blank numexpr { ADD_OP(OP_MUL); }
477 + | numexpr '/' blank numexpr { ADD_OP(OP_DIV); }
478 + | numexpr '%' blank numexpr { ADD_OP(OP_MOD); }
479 + | numexpr POW blank numexpr { ADD_OP(OP_POWER); }
480 + | numexpr GT blank numexpr { ADD_OP(OP_GT); }
481 + | numexpr GE blank numexpr { ADD_OP(OP_GE); }
482 + | numexpr LT blank numexpr { ADD_OP(OP_LT); }
483 + | numexpr LE blank numexpr { ADD_OP(OP_LE); }
484 + | numexpr EQ blank numexpr { ADD_OP(OP_EQ); }
485 + | numexpr NE blank numexpr { ADD_OP(OP_NE); }
486 + | numexpr '&' blank numexpr { ADD_OP(OP_BIT_AND); }
487 + | numexpr '|' blank numexpr { ADD_OP(OP_BIT_OR); }
488 + | numexpr and blank numexpr %prec AND {
489 ADD_OP(OP_AND); SET_BR_OFF($2, GetPC());
491 - | numexpr or numexpr %prec OR {
492 + | numexpr or blank numexpr %prec OR {
493 ADD_OP(OP_OR); SET_BR_OFF($2, GetPC());
495 - | NOT numexpr {
496 - ADD_OP(OP_NOT);
498 - | INCR SYMBOL {
499 - ADD_OP(OP_PUSH_SYM); ADD_SYM($2); ADD_OP(OP_INCR);
500 - ADD_OP(OP_DUP); ADD_OP(OP_ASSIGN); ADD_SYM($2);
502 - | SYMBOL INCR {
503 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP(OP_DUP);
504 - ADD_OP(OP_INCR); ADD_OP(OP_ASSIGN); ADD_SYM($1);
506 - | DECR SYMBOL {
507 - ADD_OP(OP_PUSH_SYM); ADD_SYM($2); ADD_OP(OP_DECR);
508 - ADD_OP(OP_DUP); ADD_OP(OP_ASSIGN); ADD_SYM($2);
509 + | incrdecr blank SYMBOL %prec INCR {
510 + ADD_OP(OP_PUSH_SYM); ADD_SYM($3); ADD_OP($1);
511 + ADD_OP(OP_DUP); ADD_OP(OP_ASSIGN); ADD_SYM($3);
513 - | SYMBOL DECR {
514 + | SYMBOL incrdecr %prec INCR {
515 ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP(OP_DUP);
516 - ADD_OP(OP_DECR); ADD_OP(OP_ASSIGN); ADD_SYM($1);
517 + ADD_OP($2); ADD_OP(OP_ASSIGN); ADD_SYM($1);
519 - | numexpr IN numexpr {
520 + | numexpr IN blank numexpr {
521 ADD_OP(OP_IN_ARRAY);
523 - | numexpr NOT IN numexpr {
524 + | numexpr NOT IN blank numexpr %prec IN {
525 ADD_OP(OP_IN_ARRAY);
526 ADD_OP(OP_NOT);
529 -while: WHILE {
530 +while: WHILE blank {
531 + $$ = GetPC(); StartLoopAddrList();
534 +do: DO blank {
535 $$ = GetPC(); StartLoopAddrList();
538 -for: FOR {
539 +for: FOR blank {
540 StartLoopAddrList(); $$ = GetPC();
543 -else: ELSE {
544 +else: ELSE blank {
545 ADD_OP(OP_BRANCH); $$ = GetPC(); ADD_BR_OFF(0);
548 -cond: /* nothing */ {
549 +cond: blank {
550 ADD_OP(OP_BRANCH_NEVER); $$ = GetPC(); ADD_BR_OFF(0);
552 - | numexpr {
553 + | blank numexpr blank {
554 ADD_OP(OP_BRANCH_FALSE); $$ = GetPC(); ADD_BR_OFF(0);
557 and: AND {
558 ADD_OP(OP_DUP); ADD_OP(OP_BRANCH_FALSE); $$ = GetPC();
559 @@ -609,11 +472,10 @@ blank: /* nothing */
560 | blank '\n'
563 %% /* User Subroutines Section */
567 ** Parse a null terminated string and create a program from it (this is the
568 ** parser entry point). The program created by this routine can be
569 ** executed using ExecuteProgram. Returns program on success, or NULL
570 ** on failure. If the command failed, the error message is returned
571 @@ -658,42 +520,50 @@ Program *ParseMacro(char *expr, char **m
572 *msg = "";
573 *stoppedAt = InPtr;
574 return prog;
578 -static int yylex(void)
579 +static char skipWhitespace(void)
581 - int i, len;
582 - Symbol *s;
583 - static DataValue value = {NO_TAG, {0}};
584 - static char escape[] = "\\\"ntbrfave";
585 -#ifdef EBCDIC_CHARSET
586 - static char replace[] = "\\\"\n\t\b\r\f\a\v\x27"; /* EBCDIC escape */
587 -#else
588 - static char replace[] = "\\\"\n\t\b\r\f\a\v\x1B"; /* ASCII escape */
589 -#endif
591 /* skip whitespace, backslash-newline combinations, and comments, which are
592 all considered whitespace */
593 for (;;) {
594 if (*InPtr == '\\' && *(InPtr + 1) == '\n')
595 InPtr += 2;
596 else if (*InPtr == ' ' || *InPtr == '\t')
597 InPtr++;
598 - else if (*InPtr == '#')
599 + else if (*InPtr == '#') {
600 + InPtr++;
601 while (*InPtr != '\n' && *InPtr != '\0') {
602 /* Comments stop at escaped newlines */
603 if (*InPtr == '\\' && *(InPtr + 1) == '\n') {
604 InPtr += 2;
605 break;
607 InPtr++;
608 - } else
611 + else
612 break;
614 + return *InPtr;
617 +static int yylex(void)
619 + int len;
620 + Symbol *s;
621 + static DataValue value = {NO_TAG, {0}};
622 + static char escape[] = "\\\"ntbrfave";
623 +#ifdef EBCDIC_CHARSET
624 + static char replace[] = "\\\"\n\t\b\r\f\a\v\x27"; /* EBCDIC escape */
625 +#else
626 + static char replace[] = "\\\"\n\t\b\r\f\a\v\x1B"; /* ASCII escape */
627 +#endif
628 + int result;
630 + skipWhitespace();
632 /* return end of input at the end of the string */
633 if (*InPtr == '\0') {
634 return 0;
636 @@ -723,10 +593,11 @@ static int yylex(void)
637 else
638 *p++ = *InPtr++;
640 *p = '\0';
641 if (!strcmp(symName, "while")) return WHILE;
642 + if (!strcmp(symName, "do")) return DO;
643 if (!strcmp(symName, "if")) return IF;
644 if (!strcmp(symName, "else")) return ELSE;
645 if (!strcmp(symName, "for")) return FOR;
646 if (!strcmp(symName, "break")) return BREAK;
647 if (!strcmp(symName, "continue")) return CONTINUE;
648 @@ -861,11 +732,12 @@ static int yylex(void)
649 yylval.sym = InstallStringConstSymbol(string);
650 return STRING;
653 /* process remaining two character tokens or return single char as token */
654 - switch(*InPtr++) {
655 + result = *InPtr++;
656 + switch (result) {
657 case '>': return follow('=', GE, GT);
658 case '<': return follow('=', LE, LT);
659 case '=': return follow('=', EQ, '=');
660 case '!': return follow('=', NE, NOT);
661 case '+': return follow2('+', INCR, '=', ADDEQ, '+');
662 @@ -874,10 +746,18 @@ static int yylex(void)
663 case '&': return follow2('&', AND, '=', ANDEQ, '&');
664 case '*': return follow2('*', POW, '=', MULEQ, '*');
665 case '/': return follow('=', DIVEQ, '/');
666 case '%': return follow('=', MODEQ, '%');
667 case '^': return POW;
668 + case '\n':
669 + case '(':
670 + case '[': {
671 + /* skip newline ( whitespace* newline )* */
672 + while (skipWhitespace() == '\n')
673 + ++InPtr;
674 + return result; /* but return what we started with */
676 default: return *(InPtr-1);