temporaly disable LoadDotNM
[nedit-bw.git] / parseEnhance2.diff
blob23e60804167bc5c043e614d06466bd7fe6e0c690
1 ---
3 source/parse.y | 444 ++++++++++++++++++++-------------------------------------
4 1 files changed, 162 insertions(+), 282 deletions(-)
6 diff --quilt old/source/parse.y new/source/parse.y
7 --- old/source/parse.y
8 +++ new/source/parse.y
9 @@ -60,17 +60,21 @@ static int nextSymIsField = 0;
11 %union {
12 Symbol *sym;
13 Inst *inst;
14 int nArgs;
15 + enum operations oper;
17 %token <sym> NUMBER STRING SYMBOL FIELD
18 %token DELETE ARG_LOOKUP
19 -%token IF WHILE ELSE FOR BREAK CONTINUE RETURN
20 -%type <nArgs> arglist catlist
21 -%type <inst> cond comastmts for while else and or arrayexpr
22 +%token IF WHILE DO ELSE FOR BREAK CONTINUE RETURN
23 +%type <nArgs> arglistopt arglist catlist
24 +%type <inst> cond comastmts comastmtlst for while do else and or arrayexpr mark
25 %type <sym> evalsym
26 +%type <oper> operassign incrdecr
27 +%token <oper> '=' ADDEQ SUBEQ MULEQ DIVEQ MODEQ ANDEQ OREQ
28 +%token <oper> INCR DECR
30 %nonassoc IF_NO_ELSE
31 %nonassoc ELSE
33 %nonassoc ';'
34 @@ -114,36 +118,42 @@ block: '{' blank stmts '}' blank
35 stmts: stmt
36 | stmts stmt
38 stmtend: '\n' | ';'
40 +mark: /* nothing */ { $$ = GetPC(); } /* record instruction address */
41 + ;
42 stmt: ';' blank
43 | simpstmt stmtend blank
44 - | IF '(' cond ')' blank block %prec IF_NO_ELSE {
45 - SET_BR_OFF($3, GetPC());
46 + | IF blank '(' cond ')' blank block %prec IF_NO_ELSE {
47 + SET_BR_OFF($4, GetPC());
49 - | IF '(' cond ')' blank block else blank block %prec ELSE {
50 - SET_BR_OFF($3, ($7+1)); SET_BR_OFF($7, GetPC());
51 + | IF blank '(' cond ')' blank block else block %prec ELSE {
52 + SET_BR_OFF($4, ($8+1)); SET_BR_OFF($8, GetPC());
54 | while '(' cond ')' blank block {
55 ADD_OP(OP_BRANCH); ADD_BR_OFF($1);
56 SET_BR_OFF($3, GetPC()); FillLoopAddrs(GetPC(), $1);
58 + | do block WHILE blank '(' mark cond ')' stmtend blank {
59 + ADD_OP(OP_BRANCH); ADD_BR_OFF($1);
60 + SET_BR_OFF($7, GetPC()); FillLoopAddrs(GetPC(), $6);
61 + }
62 | for '(' comastmts ';' cond ';' comastmts ')' blank block {
63 FillLoopAddrs(GetPC()+2+($7-($5+1)), GetPC());
64 SwapCode($5+1, $7, GetPC());
65 ADD_OP(OP_BRANCH); ADD_BR_OFF($3); SET_BR_OFF($5, GetPC());
67 - | for '(' SYMBOL IN arrayexpr ')' {
68 + | for '(' blank SYMBOL IN blank arrayexpr blank ')' {
69 Symbol *iterSym = InstallIteratorSymbol();
70 ADD_OP(OP_BEGIN_ARRAY_ITER); ADD_SYM(iterSym);
71 - ADD_OP(OP_ARRAY_ITER); ADD_SYM($3); ADD_SYM(iterSym); ADD_BR_OFF(0);
72 + ADD_OP(OP_ARRAY_ITER); ADD_SYM($4); ADD_SYM(iterSym); ADD_BR_OFF(0);
74 blank block {
75 - ADD_OP(OP_BRANCH); ADD_BR_OFF($5+2);
76 - SET_BR_OFF($5+5, GetPC());
77 - FillLoopAddrs(GetPC(), $5+2);
78 + ADD_OP(OP_BRANCH); ADD_BR_OFF($7+2);
79 + SET_BR_OFF($7+5, GetPC());
80 + FillLoopAddrs(GetPC(), $7+2);
82 | BREAK stmtend blank {
83 ADD_OP(OP_BRANCH); ADD_BR_OFF(0);
84 if (AddBreakAddr(GetPC()-1)) {
85 yyerror("break outside loop"); YYERROR;
86 @@ -160,229 +170,130 @@ stmt: ';' blank
88 | RETURN stmtend blank {
89 ADD_OP(OP_RETURN_NO_VAL);
92 -simpstmt: SYMBOL '=' expr {
94 +operassign: ADDEQ { $$ = OP_ADD; }
95 + | SUBEQ { $$ = OP_SUB; }
96 + | MULEQ { $$ = OP_MUL; }
97 + | DIVEQ { $$ = OP_DIV; }
98 + | MODEQ { $$ = OP_MOD; }
99 + | ANDEQ { $$ = OP_BIT_AND; }
100 + | OREQ { $$ = OP_BIT_OR; }
102 +incrdecr: INCR { $$ = OP_INCR; }
103 + | DECR { $$ = OP_DECR; }
106 +simpstmt: /* simple variable assignment, op-assignment, incr/decrement */
107 + SYMBOL '=' blank expr {
108 ADD_OP(OP_ASSIGN); ADD_SYM($1);
110 - | evalsym ADDEQ expr {
111 - ADD_OP(OP_ADD); ADD_OP(OP_ASSIGN); ADD_SYM($1);
113 - | evalsym SUBEQ expr {
114 - ADD_OP(OP_SUB); ADD_OP(OP_ASSIGN); ADD_SYM($1);
116 - | evalsym MULEQ expr {
117 - ADD_OP(OP_MUL); ADD_OP(OP_ASSIGN); ADD_SYM($1);
118 + | evalsym operassign blank expr {
119 + ADD_OP($2); ADD_OP(OP_ASSIGN); ADD_SYM($1);
121 - | evalsym DIVEQ expr {
122 - ADD_OP(OP_DIV); ADD_OP(OP_ASSIGN); ADD_SYM($1);
123 + | incrdecr blank SYMBOL {
124 + ADD_OP(OP_PUSH_SYM); ADD_SYM($3); ADD_OP($1);
125 + ADD_OP(OP_ASSIGN); ADD_SYM($3);
127 - | evalsym MODEQ expr {
128 - ADD_OP(OP_MOD); ADD_OP(OP_ASSIGN); ADD_SYM($1);
130 - | evalsym ANDEQ expr {
131 - ADD_OP(OP_BIT_AND); ADD_OP(OP_ASSIGN); ADD_SYM($1);
133 - | evalsym OREQ expr {
134 - ADD_OP(OP_BIT_OR); ADD_OP(OP_ASSIGN); ADD_SYM($1);
135 + | SYMBOL incrdecr {
136 + ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP($2);
137 + ADD_OP(OP_ASSIGN); ADD_SYM($1);
139 - | DELETE arraylv '[' arglist ']' {
140 + /* delete array entry simple statement */
141 + | DELETE arraylv '[' arglistopt ']' {
142 ADD_OP(OP_ARRAY_DELETE); ADD_IMMED($4);
144 | DELETE arraylv dot field {
145 ADD_OP(OP_ARRAY_DELETE); ADD_IMMED(1);
147 -/* array[index] assignment */
148 - | initarraylv '[' arglist ']' '=' expr {
149 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
151 - | initarraylv '[' arglist ']' ADDEQ expr {
152 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
153 - ADD_OP(OP_ADD);
154 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
156 - | initarraylv '[' arglist ']' SUBEQ expr {
157 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
158 - ADD_OP(OP_SUB);
159 + /* array[index] assignment, op-assignment, incr/decrement */
160 + | initarraylv '[' arglistopt ']' '=' blank expr {
161 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
163 - | initarraylv '[' arglist ']' MULEQ expr {
164 + | initarraylv '[' arglistopt ']' operassign blank expr {
165 ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
166 - ADD_OP(OP_MUL);
167 + ADD_OP($5);
168 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
170 - | initarraylv '[' arglist ']' DIVEQ expr {
171 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
172 - ADD_OP(OP_DIV);
173 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
175 - | initarraylv '[' arglist ']' MODEQ expr {
176 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
177 - ADD_OP(OP_MOD);
178 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
180 - | initarraylv '[' arglist ']' ANDEQ expr {
181 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
182 - ADD_OP(OP_BIT_AND);
183 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
185 - | initarraylv '[' arglist ']' OREQ expr {
186 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
187 - ADD_OP(OP_BIT_OR);
188 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
190 - | initarraylv '[' arglist ']' INCR {
191 + | initarraylv '[' arglistopt ']' incrdecr {
192 ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED($3);
193 - ADD_OP(OP_INCR);
194 + ADD_OP($5);
195 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
197 - | initarraylv '[' arglist ']' DECR {
198 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED($3);
199 - ADD_OP(OP_DECR);
200 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
201 + | incrdecr blank initarraylv '[' arglistopt ']' {
202 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED($5);
203 + ADD_OP($1);
204 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($5);
206 - | INCR initarraylv '[' arglist ']' {
207 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED($4);
208 - ADD_OP(OP_INCR);
209 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($4);
211 - | DECR initarraylv '[' arglist ']' {
212 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED($4);
213 - ADD_OP(OP_DECR);
214 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($4);
216 -/* array.field assignment */
217 - | initarraylv dot field '=' expr {
218 + /* array.field assignment, op-assignment, incr/decrement */
219 + | initarraylv dot field '=' blank expr {
220 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
222 - | initarraylv dot field ADDEQ expr {
223 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
224 - ADD_OP(OP_ADD);
225 + | initarraylv dot field operassign blank expr {
226 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1);ADD_IMMED(1);
227 + ADD_OP($4);
228 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
230 - | initarraylv dot field SUBEQ expr {
231 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
232 - ADD_OP(OP_SUB);
233 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
235 - | initarraylv dot field MULEQ expr {
236 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
237 - ADD_OP(OP_MUL);
238 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
240 - | initarraylv dot field DIVEQ expr {
241 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
242 - ADD_OP(OP_DIV);
243 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
245 - | initarraylv dot field MODEQ expr {
246 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
247 - ADD_OP(OP_MOD);
248 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
250 - | initarraylv dot field ANDEQ expr {
251 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
252 - ADD_OP(OP_BIT_AND);
253 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
255 - | initarraylv dot field OREQ expr {
256 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
257 - ADD_OP(OP_BIT_OR);
258 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
260 - | initarraylv dot field INCR {
261 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
262 - ADD_OP(OP_INCR);
263 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
265 - | initarraylv dot field DECR {
266 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
267 - ADD_OP(OP_DECR);
268 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
270 - | INCR initarraylv dot field {
271 + | initarraylv dot field incrdecr {
272 ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
273 - ADD_OP(OP_INCR);
274 + ADD_OP($4);
275 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
277 - | DECR initarraylv dot field {
278 + | incrdecr blank initarraylv dot field {
279 ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
280 - ADD_OP(OP_DECR);
281 + ADD_OP($1);
282 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
284 - | SYMBOL '(' arglist ')' {
285 + /* function call */
286 + | SYMBOL '(' arglistopt ')' {
287 ADD_OP(OP_SUBR_CALL);
288 ADD_SYM(PromoteToGlobal($1)); ADD_IMMED($3);
290 - | INCR SYMBOL {
291 - ADD_OP(OP_PUSH_SYM); ADD_SYM($2); ADD_OP(OP_INCR);
292 - ADD_OP(OP_ASSIGN); ADD_SYM($2);
294 - | SYMBOL INCR {
295 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP(OP_INCR);
296 - ADD_OP(OP_ASSIGN); ADD_SYM($1);
298 - | DECR SYMBOL {
299 - ADD_OP(OP_PUSH_SYM); ADD_SYM($2); ADD_OP(OP_DECR);
300 - ADD_OP(OP_ASSIGN); ADD_SYM($2);
302 - | SYMBOL DECR {
303 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP(OP_DECR);
304 - ADD_OP(OP_ASSIGN); ADD_SYM($1);
308 evalsym: SYMBOL {
309 $$ = $1; ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
312 -comastmts: /* nothing */ {
313 - $$ = GetPC();
315 - | simpstmt {
316 - $$ = GetPC();
318 - | comastmts ',' simpstmt {
319 - $$ = GetPC();
321 +comastmts: blank { $$ = GetPC(); }
322 + | blank comastmtlst { $$ = $2; }
324 -arglist: /* nothing */ {
325 - $$ = 0;
327 - | expr {
328 - $$ = 1;
330 - | arglist ',' expr {
331 - $$ = $1 + 1;
333 +comastmtlst: simpstmt blank { $$ = GetPC(); }
334 + | comastmtlst ',' blank simpstmt blank { $$ = GetPC(); }
337 +arglistopt: blank { $$ = 0; }
338 + | arglist { $$ = $1; }
340 +arglist: blank expr blank { $$ = 1; }
341 + | arglist ',' blank expr blank { $$ = $1 + 1; }
343 +catlist: numexpr %prec CONCAT { $$ = 1; }
344 + | catlist numexpr %prec CONCAT { $$ = $1 + 1; }
346 -catlist: numexpr %prec CONCAT {
347 - $$ = 1;
349 - | catlist numexpr %prec CONCAT {
350 - $$ = $1 + 1;
352 expr: catlist {
353 if ($1 > 1) {
354 ADD_OP(OP_CONCAT); ADD_IMMED($1);
358 initarraylv: SYMBOL {
359 ADD_OP(OP_PUSH_ARRAY_SYM); ADD_SYM($1); ADD_IMMED(1);
361 - | initarraylv '[' arglist ']' {
362 + | initarraylv '[' arglistopt ']' {
363 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
365 | initarraylv dot field {
366 ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
369 arraylv: SYMBOL {
370 ADD_OP(OP_PUSH_ARRAY_SYM); ADD_SYM($1); ADD_IMMED(0);
372 - | arraylv '[' arglist ']' {
373 + | arraylv '[' arglistopt ']' {
374 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
376 | arraylv dot field {
377 ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
379 @@ -398,134 +309,86 @@ field: FIELD {
381 arrayexpr: numexpr {
382 $$ = GetPC();
385 -numexpr: NUMBER {
386 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
388 - | STRING {
389 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
391 - | SYMBOL {
392 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
394 - | SYMBOL '(' arglist ')' {
395 +numexpr: '(' blank expr blank ')'
396 + | NUMBER { ADD_OP(OP_PUSH_SYM); ADD_SYM($1); }
397 + | STRING { ADD_OP(OP_PUSH_SYM); ADD_SYM($1); }
398 + | SYMBOL { ADD_OP(OP_PUSH_SYM); ADD_SYM($1); }
399 + | SYMBOL '(' arglistopt ')' {
400 ADD_OP(OP_SUBR_CALL);
401 ADD_SYM(PromoteToGlobal($1)); ADD_IMMED($3);
402 ADD_OP(OP_FETCH_RET_VAL);
404 - | '(' expr ')'
405 - | ARG_LOOKUP '[' numexpr ']' {
406 - ADD_OP(OP_PUSH_ARG);
408 - | ARG_LOOKUP '[' ']' {
409 - ADD_OP(OP_PUSH_ARG_COUNT);
411 - | ARG_LOOKUP {
412 - ADD_OP(OP_PUSH_ARG_ARRAY);
414 - | numexpr '[' arglist ']' {
415 + | ARG_LOOKUP '[' blank numexpr blank ']' { ADD_OP(OP_PUSH_ARG); }
416 + | ARG_LOOKUP '[' blank ']' { ADD_OP(OP_PUSH_ARG_COUNT); }
417 + | ARG_LOOKUP { ADD_OP(OP_PUSH_ARG_ARRAY); }
418 + | numexpr '[' arglistopt ']' {
419 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
421 | numexpr dot field {
422 ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
424 - | numexpr '+' numexpr {
425 - ADD_OP(OP_ADD);
427 - | numexpr '-' numexpr {
428 - ADD_OP(OP_SUB);
430 - | numexpr '*' numexpr {
431 - ADD_OP(OP_MUL);
433 - | numexpr '/' numexpr {
434 - ADD_OP(OP_DIV);
436 - | numexpr '%' numexpr {
437 - ADD_OP(OP_MOD);
439 - | numexpr POW numexpr {
440 - ADD_OP(OP_POWER);
442 - | '-' numexpr %prec UNARY_MINUS {
443 - ADD_OP(OP_NEGATE);
445 - | numexpr GT numexpr {
446 - ADD_OP(OP_GT);
448 - | numexpr GE numexpr {
449 - ADD_OP(OP_GE);
451 - | numexpr LT numexpr {
452 - ADD_OP(OP_LT);
454 - | numexpr LE numexpr {
455 - ADD_OP(OP_LE);
457 - | numexpr EQ numexpr {
458 - ADD_OP(OP_EQ);
460 - | numexpr NE numexpr {
461 - ADD_OP(OP_NE);
463 - | numexpr '&' numexpr {
464 - ADD_OP(OP_BIT_AND);
466 - | numexpr '|' numexpr {
467 - ADD_OP(OP_BIT_OR);
469 - | numexpr and numexpr %prec AND {
470 + | '-' blank numexpr %prec UNARY_MINUS { ADD_OP(OP_NEGATE); }
471 + | NOT blank numexpr { ADD_OP(OP_NOT); }
472 + | numexpr '+' blank numexpr { ADD_OP(OP_ADD); }
473 + | numexpr '-' blank numexpr { ADD_OP(OP_SUB); }
474 + | numexpr '*' blank numexpr { ADD_OP(OP_MUL); }
475 + | numexpr '/' blank numexpr { ADD_OP(OP_DIV); }
476 + | numexpr '%' blank numexpr { ADD_OP(OP_MOD); }
477 + | numexpr POW blank numexpr { ADD_OP(OP_POWER); }
478 + | numexpr GT blank numexpr { ADD_OP(OP_GT); }
479 + | numexpr GE blank numexpr { ADD_OP(OP_GE); }
480 + | numexpr LT blank numexpr { ADD_OP(OP_LT); }
481 + | numexpr LE blank numexpr { ADD_OP(OP_LE); }
482 + | numexpr EQ blank numexpr { ADD_OP(OP_EQ); }
483 + | numexpr NE blank numexpr { ADD_OP(OP_NE); }
484 + | numexpr '&' blank numexpr { ADD_OP(OP_BIT_AND); }
485 + | numexpr '|' blank numexpr { ADD_OP(OP_BIT_OR); }
486 + | numexpr and blank numexpr %prec AND {
487 ADD_OP(OP_AND); SET_BR_OFF($2, GetPC());
489 - | numexpr or numexpr %prec OR {
490 + | numexpr or blank numexpr %prec OR {
491 ADD_OP(OP_OR); SET_BR_OFF($2, GetPC());
493 - | NOT numexpr {
494 - ADD_OP(OP_NOT);
496 - | INCR SYMBOL {
497 - ADD_OP(OP_PUSH_SYM); ADD_SYM($2); ADD_OP(OP_INCR);
498 - ADD_OP(OP_DUP); ADD_OP(OP_ASSIGN); ADD_SYM($2);
499 + | incrdecr blank SYMBOL %prec INCR {
500 + ADD_OP(OP_PUSH_SYM); ADD_SYM($3); ADD_OP($1);
501 + ADD_OP(OP_DUP); ADD_OP(OP_ASSIGN); ADD_SYM($3);
503 - | SYMBOL INCR {
504 + | SYMBOL incrdecr %prec INCR {
505 ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP(OP_DUP);
506 - ADD_OP(OP_INCR); ADD_OP(OP_ASSIGN); ADD_SYM($1);
507 + ADD_OP($2); ADD_OP(OP_ASSIGN); ADD_SYM($1);
509 - | DECR SYMBOL {
510 - ADD_OP(OP_PUSH_SYM); ADD_SYM($2); ADD_OP(OP_DECR);
511 - ADD_OP(OP_DUP); ADD_OP(OP_ASSIGN); ADD_SYM($2);
513 - | SYMBOL DECR {
514 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP(OP_DUP);
515 - ADD_OP(OP_DECR); ADD_OP(OP_ASSIGN); ADD_SYM($1);
517 - | numexpr IN numexpr {
518 + | numexpr IN blank numexpr {
519 ADD_OP(OP_IN_ARRAY);
521 - | numexpr NOT IN numexpr {
522 + | numexpr NOT IN blank numexpr %prec IN {
523 ADD_OP(OP_IN_ARRAY);
524 ADD_OP(OP_NOT);
527 -while: WHILE {
528 +while: WHILE blank {
529 $$ = GetPC(); StartLoopAddrList();
532 -for: FOR {
533 +do: DO blank {
534 + $$ = GetPC(); StartLoopAddrList();
537 +for: FOR blank {
538 StartLoopAddrList(); $$ = GetPC();
541 -else: ELSE {
542 +else: ELSE blank {
543 ADD_OP(OP_BRANCH); $$ = GetPC(); ADD_BR_OFF(0);
546 -cond: /* nothing */ {
547 +cond: blank {
548 ADD_OP(OP_BRANCH_NEVER); $$ = GetPC(); ADD_BR_OFF(0);
550 - | numexpr {
551 + | blank numexpr blank {
552 ADD_OP(OP_BRANCH_FALSE); $$ = GetPC(); ADD_BR_OFF(0);
555 and: AND {
556 ADD_OP(OP_DUP); ADD_OP(OP_BRANCH_FALSE); $$ = GetPC();
557 @@ -545,11 +408,10 @@ blank: /* nothing */
558 | blank '\n'
561 %% /* User Subroutines Section */
565 ** Parse a null terminated string and create a program from it (this is the
566 ** parser entry point). The program created by this routine can be
567 ** executed using ExecuteProgram. Returns program on success, or NULL
568 ** on failure. If the command failed, the error message is returned
569 @@ -587,42 +449,50 @@ Program *ParseMacro(char *expr, char **m
570 *msg = "";
571 *stoppedAt = InPtr;
572 return prog;
576 -static int yylex(void)
578 - int i, len;
579 - Symbol *s;
580 - static DataValue value = {NO_TAG, {0}};
581 - static char escape[] = "\\\"ntbrfave";
582 -#ifdef EBCDIC_CHARSET
583 - static char replace[] = "\\\"\n\t\b\r\f\a\v\x27"; /* EBCDIC escape */
584 -#else
585 - static char replace[] = "\\\"\n\t\b\r\f\a\v\x1B"; /* ASCII escape */
586 -#endif
588 +static char skipWhitespace(void)
590 /* skip whitespace, backslash-newline combinations, and comments, which are
591 all considered whitespace */
592 for (;;) {
593 if (*InPtr == '\\' && *(InPtr + 1) == '\n')
594 InPtr += 2;
595 else if (*InPtr == ' ' || *InPtr == '\t')
596 InPtr++;
597 - else if (*InPtr == '#')
598 + else if (*InPtr == '#') {
599 + InPtr++;
600 while (*InPtr != '\n' && *InPtr != '\0') {
601 /* Comments stop at escaped newlines */
602 if (*InPtr == '\\' && *(InPtr + 1) == '\n') {
603 InPtr += 2;
604 break;
606 InPtr++;
607 - } else
610 + else
611 break;
613 + return *InPtr;
616 +static int yylex(void)
618 + int len;
619 + Symbol *s;
620 + static DataValue value = {NO_TAG, {0}};
621 + static char escape[] = "\\\"ntbrfave";
622 +#ifdef EBCDIC_CHARSET
623 + static char replace[] = "\\\"\n\t\b\r\f\a\v\x27"; /* EBCDIC escape */
624 +#else
625 + static char replace[] = "\\\"\n\t\b\r\f\a\v\x1B"; /* ASCII escape */
626 +#endif
627 + int result;
629 + skipWhitespace();
631 /* return end of input at the end of the string */
632 if (*InPtr == '\0') {
633 return 0;
635 @@ -653,10 +523,11 @@ static int yylex(void)
636 else
637 *p++ = *InPtr++;
639 *p = '\0';
640 if (!strcmp(symName, "while")) return WHILE;
641 + if (!strcmp(symName, "do")) return DO;
642 if (!strcmp(symName, "if")) return IF;
643 if (!strcmp(symName, "else")) return ELSE;
644 if (!strcmp(symName, "for")) return FOR;
645 if (!strcmp(symName, "break")) return BREAK;
646 if (!strcmp(symName, "continue")) return CONTINUE;
647 @@ -794,11 +665,12 @@ static int yylex(void)
648 yylval.sym = InstallStringConstSymbol(string);
649 return STRING;
652 /* process remaining two character tokens or return single char as token */
653 - switch(*InPtr++) {
654 + result = *InPtr++;
655 + switch (result) {
656 case '>': return follow('=', GE, GT);
657 case '<': return follow('=', LE, LT);
658 case '=': return follow('=', EQ, '=');
659 case '!': return follow('=', NE, NOT);
660 case '+': return follow2('+', INCR, '=', ADDEQ, '+');
661 @@ -807,10 +679,18 @@ static int yylex(void)
662 case '&': return follow2('&', AND, '=', ANDEQ, '&');
663 case '*': return follow2('*', POW, '=', MULEQ, '*');
664 case '/': return follow('=', DIVEQ, '/');
665 case '%': return follow('=', MODEQ, '%');
666 case '^': return POW;
667 + case '\n':
668 + case '(':
669 + case '[': {
670 + /* skip newline ( whitespace* newline )* */
671 + while (skipWhitespace() == '\n')
672 + ++InPtr;
673 + return result; /* but return what we started with */
675 default: return *(InPtr-1);