1 From: Tony Balinski <ajbj@free.fr>
2 Subject: Enhancements to NEdit macro parsing
6 http://sourceforge.net/tracker/index.php?func=detail&aid=1249914&group_id=11005&atid=311005
7 [ 1249914 ] Enhancements to NEdit macro parsing
8 parseEnhance2.diff 2005-08-03 18:51
10 This patch adds the following features to NEdit's macro language:
12 * the do ... while loop has been lifted from C, as
14 do block-or-statement while ( condition )
16 * N8 Gray's "optional semicolons for statement termination" (SF patch
17 1185506) has been included
19 * added a few productions to group assignment increment/decrement operators
21 * allowed for linebreaks in places where their statement-terminating
22 behaviour makes no sense, ie in argument lists, after prefix or binary
23 operators, after keywords if, while, for and do (They are also allowed in
24 the comma-separated simple-statements in the for loop's initialisation
25 and iteration phrases) and after opening parentheses; you only need "\"
26 in a few cases now, in particular when concatenating strings on different
29 * general reformatting of the parse.y file to "condense" the smaller code
30 blocks (this undoes some of Steve LoBasso's reformatting from some time
31 ago) - I think this enhances the grammar productions over the injected
36 source/parse.y | 453 +++++++++++++++++++++------------------------------------
37 1 file changed, 172 insertions(+), 281 deletions(-)
39 diff --quilt old/source/parse.y new/source/parse.y
40 --- old/source/parse.y
41 +++ new/source/parse.y
42 @@ -87,6 +87,7 @@ static int nextSymIsField = 0;
46 + enum operations oper;
50 @@ -95,11 +96,14 @@ static int nextSymIsField = 0;
51 %token <sym> STRING SYMBOL FIELD
53 %token DELETE ARG_LOOKUP
54 -%token IF WHILE ELSE FOR BREAK CONTINUE RETURN DEFINE
55 -%type <num> arglist catlist
56 -%type <inst> cond comastmts for while else and or arrayexpr
57 +%token IF WHILE DO ELSE FOR BREAK CONTINUE RETURN DEFINE
58 +%type <num> arglistopt arglist catlist
59 +%type <inst> cond comastmts comastmtlst for while do else and or arrayexpr mark
61 %type <define> definesym
62 +%type <oper> operassign incrdecr
63 +%token <oper> '=' ADDEQ SUBEQ MULEQ DIVEQ MODEQ ANDEQ OREQ
64 +%token <oper> INCR DECR
68 @@ -138,6 +142,7 @@ program: blank topstmts {
73 blockwb: '{' blank stmts '}' blank
76 @@ -194,32 +199,40 @@ define: definekw blank definesym bla
81 +mark: /* nothing */ { $$ = GetPC(); } /* record instruction address */
85 | simpstmt stmtend blank
86 - | IF '(' cond ')' blank block %prec IF_NO_ELSE {
87 - SET_BR_OFF($3, GetPC());
88 + | IF blank '(' cond ')' blank block %prec IF_NO_ELSE {
89 + SET_BR_OFF($4, GetPC());
91 - | IF '(' cond ')' blank block else blank block %prec ELSE {
92 - SET_BR_OFF($3, ($7+1)); SET_BR_OFF($7, GetPC());
93 + | IF blank '(' cond ')' blank block else block %prec ELSE {
94 + SET_BR_OFF($4, ($8+1)); SET_BR_OFF($8, GetPC());
96 | while '(' cond ')' blank block {
97 ADD_OP(OP_BRANCH); ADD_BR_OFF($1);
98 SET_BR_OFF($3, GetPC()); FillLoopAddrs(GetPC(), $1);
100 + | do block WHILE blank '(' mark cond ')' stmtend blank {
101 + ADD_OP(OP_BRANCH); ADD_BR_OFF($1);
102 + SET_BR_OFF($7, GetPC()); FillLoopAddrs(GetPC(), $6);
104 | for '(' comastmts ';' cond ';' comastmts ')' blank block {
105 FillLoopAddrs(GetPC()+2+($7-($5+1)), GetPC());
106 SwapCode($5+1, $7, GetPC());
107 ADD_OP(OP_BRANCH); ADD_BR_OFF($3); SET_BR_OFF($5, GetPC());
109 - | for '(' SYMBOL IN arrayexpr ')' {
110 + | for '(' blank SYMBOL IN blank arrayexpr blank ')' {
111 Symbol *iterSym = InstallIteratorSymbol();
112 ADD_OP(OP_BEGIN_ARRAY_ITER); ADD_SYM(iterSym);
113 - ADD_OP(OP_ARRAY_ITER); ADD_SYM($3); ADD_SYM(iterSym); ADD_BR_OFF(0);
114 + ADD_OP(OP_ARRAY_ITER); ADD_SYM($4); ADD_SYM(iterSym); ADD_BR_OFF(0);
117 - ADD_OP(OP_BRANCH); ADD_BR_OFF($5+2);
118 - SET_BR_OFF($5+5, GetPC());
119 - FillLoopAddrs(GetPC(), $5+2);
120 + ADD_OP(OP_BRANCH); ADD_BR_OFF($7+2);
121 + SET_BR_OFF($7+5, GetPC());
122 + FillLoopAddrs(GetPC(), $7+2);
124 | BREAK stmtend blank {
125 ADD_OP(OP_BRANCH); ADD_BR_OFF(0);
126 @@ -240,207 +253,109 @@ stmt: ';' blank
127 ADD_OP(OP_RETURN_NO_VAL);
130 -simpstmt: SYMBOL '=' expr {
132 +operassign: ADDEQ { $$ = OP_ADD; }
133 + | SUBEQ { $$ = OP_SUB; }
134 + | MULEQ { $$ = OP_MUL; }
135 + | DIVEQ { $$ = OP_DIV; }
136 + | MODEQ { $$ = OP_MOD; }
137 + | ANDEQ { $$ = OP_BIT_AND; }
138 + | OREQ { $$ = OP_BIT_OR; }
140 +incrdecr: INCR { $$ = OP_INCR; }
141 + | DECR { $$ = OP_DECR; }
144 +simpstmt: /* simple variable assignment, op-assignment, incr/decrement */
145 + SYMBOL '=' blank expr {
146 ADD_OP(OP_ASSIGN); ADD_SYM($1);
148 - | evalsym ADDEQ expr {
149 - ADD_OP(OP_ADD); ADD_OP(OP_ASSIGN); ADD_SYM($1);
150 + | evalsym operassign blank expr {
151 + ADD_OP($2); ADD_OP(OP_ASSIGN); ADD_SYM($1);
153 - | evalsym SUBEQ expr {
154 - ADD_OP(OP_SUB); ADD_OP(OP_ASSIGN); ADD_SYM($1);
155 + | incrdecr blank SYMBOL {
156 + ADD_OP(OP_PUSH_SYM); ADD_SYM($3); ADD_OP($1);
157 + ADD_OP(OP_ASSIGN); ADD_SYM($3);
159 - | evalsym MULEQ expr {
160 - ADD_OP(OP_MUL); ADD_OP(OP_ASSIGN); ADD_SYM($1);
162 - | evalsym DIVEQ expr {
163 - ADD_OP(OP_DIV); ADD_OP(OP_ASSIGN); ADD_SYM($1);
165 - | evalsym MODEQ expr {
166 - ADD_OP(OP_MOD); ADD_OP(OP_ASSIGN); ADD_SYM($1);
168 - | evalsym ANDEQ expr {
169 - ADD_OP(OP_BIT_AND); ADD_OP(OP_ASSIGN); ADD_SYM($1);
171 - | evalsym OREQ expr {
172 - ADD_OP(OP_BIT_OR); ADD_OP(OP_ASSIGN); ADD_SYM($1);
173 + | SYMBOL incrdecr {
174 + ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP($2);
175 + ADD_OP(OP_ASSIGN); ADD_SYM($1);
177 - | DELETE arraylv '[' arglist ']' {
178 + /* delete array entry simple statement */
179 + | DELETE arraylv '[' arglistopt ']' {
180 ADD_OP(OP_ARRAY_DELETE); ADD_IMMED($4);
182 | DELETE arraylv dot field {
183 ADD_OP(OP_ARRAY_DELETE); ADD_IMMED(1);
185 - /* array[index] assignment */
186 - | initarraylv '[' arglist ']' '=' expr {
187 + /* array[index] assignment, op-assignment, incr/decrement */
188 + | initarraylv '[' arglistopt ']' '=' blank expr {
189 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
191 - | initarraylv '[' arglist ']' ADDEQ expr {
192 + | initarraylv '[' arglistopt ']' operassign blank expr {
193 ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
196 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
198 - | initarraylv '[' arglist ']' SUBEQ expr {
199 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
201 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
203 - | initarraylv '[' arglist ']' MULEQ expr {
204 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
206 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
208 - | initarraylv '[' arglist ']' DIVEQ expr {
209 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
211 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
213 - | initarraylv '[' arglist ']' MODEQ expr {
214 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
216 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
218 - | initarraylv '[' arglist ']' ANDEQ expr {
219 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
220 - ADD_OP(OP_BIT_AND);
221 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
223 - | initarraylv '[' arglist ']' OREQ expr {
224 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED($3);
226 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
228 - | initarraylv '[' arglist ']' INCR {
229 + | initarraylv '[' arglistopt ']' incrdecr {
230 ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED($3);
233 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
235 - | initarraylv '[' arglist ']' DECR {
236 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED($3);
238 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($3);
239 + | incrdecr blank initarraylv '[' arglistopt ']' {
240 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED($5);
242 + ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($5);
244 - | INCR initarraylv '[' arglist ']' {
245 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED($4);
247 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($4);
249 - | DECR initarraylv '[' arglist ']' {
250 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED($4);
252 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED($4);
254 - /* array.field assignment */
255 - | initarraylv dot field '=' expr {
256 + /* array.field assignment, op-assignment, incr/decrement */
257 + | initarraylv dot field '=' blank expr {
258 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
260 - | initarraylv dot field ADDEQ expr {
261 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
263 + | initarraylv dot field operassign blank expr {
264 + ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1);ADD_IMMED(1);
266 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
268 - | initarraylv dot field SUBEQ expr {
269 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
271 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
273 - | initarraylv dot field MULEQ expr {
274 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
276 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
278 - | initarraylv dot field DIVEQ expr {
279 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
281 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
283 - | initarraylv dot field MODEQ expr {
284 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
286 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
288 - | initarraylv dot field ANDEQ expr {
289 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
290 - ADD_OP(OP_BIT_AND);
291 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
293 - | initarraylv dot field OREQ expr {
294 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(1); ADD_IMMED(1);
296 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
298 - | initarraylv dot field INCR {
299 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
301 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
303 - | initarraylv dot field DECR {
304 + | initarraylv dot field incrdecr {
305 ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
308 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
310 - | INCR initarraylv dot field {
311 + | incrdecr blank initarraylv dot field {
312 ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
315 ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
317 - | DECR initarraylv dot field {
318 - ADD_OP(OP_ARRAY_REF_ASSIGN_SETUP); ADD_IMMED(0); ADD_IMMED(1);
320 - ADD_OP(OP_ARRAY_ASSIGN); ADD_IMMED(1);
322 - | SYMBOL '(' arglist ')' {
323 + /* function call */
324 + | SYMBOL '(' arglistopt ')' {
325 ADD_OP(OP_SUBR_CALL);
326 ADD_SYM(PromoteToGlobal($1)); ADD_IMMED($3);
329 - ADD_OP(OP_PUSH_SYM); ADD_SYM($2); ADD_OP(OP_INCR);
330 - ADD_OP(OP_ASSIGN); ADD_SYM($2);
333 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP(OP_INCR);
334 - ADD_OP(OP_ASSIGN); ADD_SYM($1);
337 - ADD_OP(OP_PUSH_SYM); ADD_SYM($2); ADD_OP(OP_DECR);
338 - ADD_OP(OP_ASSIGN); ADD_SYM($2);
341 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP(OP_DECR);
342 - ADD_OP(OP_ASSIGN); ADD_SYM($1);
347 $$ = $1; ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
350 -comastmts: /* nothing */ {
356 - | comastmts ',' simpstmt {
360 +comastmts: blank { $$ = GetPC(); }
361 + | blank comastmtlst { $$ = $2; }
363 -arglist: /* nothing */ {
369 - | arglist ',' expr {
372 +comastmtlst: simpstmt blank { $$ = GetPC(); }
373 + | comastmtlst ',' blank simpstmt blank { $$ = GetPC(); }
376 +/* array key argument lists */
377 +arglistopt: blank { $$ = 0; }
378 + | arglist { $$ = $1; }
380 +arglist: blank expr blank { $$ = 1; }
381 + | arglist ',' blank expr blank { $$ = $1 + 1; }
384 /* string concatenation lists */
385 -catlist: numexpr %prec CONCAT {
388 - | catlist numexpr %prec CONCAT {
391 +catlist: numexpr %prec CONCAT { $$ = 1; }
392 + | catlist numexpr %prec CONCAT { $$ = $1 + 1; }
396 @@ -449,20 +364,22 @@ expr: catlist {
401 initarraylv: SYMBOL {
402 ADD_OP(OP_PUSH_ARRAY_SYM); ADD_SYM($1); ADD_IMMED(1);
404 - | initarraylv '[' arglist ']' {
405 + | initarraylv '[' arglistopt ']' {
406 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
408 | initarraylv dot field {
409 ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
414 ADD_OP(OP_PUSH_ARRAY_SYM); ADD_SYM($1); ADD_IMMED(0);
416 - | arraylv '[' arglist ']' {
417 + | arraylv '[' arglistopt ']' {
418 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
420 | arraylv dot field {
421 @@ -484,134 +401,89 @@ arrayexpr: numexpr {
426 - ADD_OP(OP_PUSH_IMMED); ADD_IMMED($1);
429 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
432 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1);
434 - | SYMBOL '(' arglist ')' {
436 +numexpr: '(' blank expr blank ')'
437 + | NUMBER { ADD_OP(OP_PUSH_IMMED); ADD_IMMED($1); }
438 + | STRING { ADD_OP(OP_PUSH_SYM); ADD_SYM($1); }
439 + | SYMBOL { ADD_OP(OP_PUSH_SYM); ADD_SYM($1); }
440 + | SYMBOL '(' arglistopt ')' {
441 ADD_OP(OP_SUBR_CALL);
442 ADD_SYM(PromoteToGlobal($1)); ADD_IMMED($3);
443 ADD_OP(OP_FETCH_RET_VAL);
446 - | ARG_LOOKUP '[' numexpr ']' {
447 - ADD_OP(OP_PUSH_ARG);
449 - | ARG_LOOKUP '[' ']' {
450 - ADD_OP(OP_PUSH_ARG_COUNT);
453 - ADD_OP(OP_PUSH_ARG_ARRAY);
455 - | numexpr '[' arglist ']' {
456 + | ARG_LOOKUP '[' blank numexpr blank ']' { ADD_OP(OP_PUSH_ARG); }
457 + | ARG_LOOKUP '[' blank ']' { ADD_OP(OP_PUSH_ARG_COUNT); }
458 + | ARG_LOOKUP { ADD_OP(OP_PUSH_ARG_ARRAY); }
459 + | numexpr '[' arglistopt ']' {
460 ADD_OP(OP_ARRAY_REF); ADD_IMMED($3);
462 | numexpr dot field {
463 ADD_OP(OP_ARRAY_REF); ADD_IMMED(1);
465 - | numexpr '+' numexpr {
468 - | numexpr '-' numexpr {
471 - | numexpr '*' numexpr {
474 - | numexpr '/' numexpr {
477 - | numexpr '%' numexpr {
480 - | numexpr POW numexpr {
483 - | '-' numexpr %prec UNARY_MINUS {
486 - | numexpr GT numexpr {
489 - | numexpr GE numexpr {
492 - | numexpr LT numexpr {
495 - | numexpr LE numexpr {
498 - | numexpr EQ numexpr {
501 - | numexpr NE numexpr {
504 - | numexpr '&' numexpr {
505 - ADD_OP(OP_BIT_AND);
507 - | numexpr '|' numexpr {
510 - | numexpr and numexpr %prec AND {
511 + | '-' blank numexpr %prec UNARY_MINUS { ADD_OP(OP_NEGATE); }
512 + | NOT blank numexpr { ADD_OP(OP_NOT); }
513 + | numexpr '+' blank numexpr { ADD_OP(OP_ADD); }
514 + | numexpr '-' blank numexpr { ADD_OP(OP_SUB); }
515 + | numexpr '*' blank numexpr { ADD_OP(OP_MUL); }
516 + | numexpr '/' blank numexpr { ADD_OP(OP_DIV); }
517 + | numexpr '%' blank numexpr { ADD_OP(OP_MOD); }
518 + | numexpr POW blank numexpr { ADD_OP(OP_POWER); }
519 + | numexpr GT blank numexpr { ADD_OP(OP_GT); }
520 + | numexpr GE blank numexpr { ADD_OP(OP_GE); }
521 + | numexpr LT blank numexpr { ADD_OP(OP_LT); }
522 + | numexpr LE blank numexpr { ADD_OP(OP_LE); }
523 + | numexpr EQ blank numexpr { ADD_OP(OP_EQ); }
524 + | numexpr NE blank numexpr { ADD_OP(OP_NE); }
525 + | numexpr '&' blank numexpr { ADD_OP(OP_BIT_AND); }
526 + | numexpr '|' blank numexpr { ADD_OP(OP_BIT_OR); }
527 + | numexpr and blank numexpr %prec AND {
528 ADD_OP(OP_AND); SET_BR_OFF($2, GetPC());
530 - | numexpr or numexpr %prec OR {
531 + | numexpr or blank numexpr %prec OR {
532 ADD_OP(OP_OR); SET_BR_OFF($2, GetPC());
538 - ADD_OP(OP_PUSH_SYM); ADD_SYM($2); ADD_OP(OP_INCR);
539 - ADD_OP(OP_DUP); ADD_OP(OP_ASSIGN); ADD_SYM($2);
540 + | incrdecr blank SYMBOL %prec INCR {
541 + ADD_OP(OP_PUSH_SYM); ADD_SYM($3); ADD_OP($1);
542 + ADD_OP(OP_DUP); ADD_OP(OP_ASSIGN); ADD_SYM($3);
545 + | SYMBOL incrdecr %prec INCR {
546 ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP(OP_DUP);
547 - ADD_OP(OP_INCR); ADD_OP(OP_ASSIGN); ADD_SYM($1);
548 + ADD_OP($2); ADD_OP(OP_ASSIGN); ADD_SYM($1);
551 - ADD_OP(OP_PUSH_SYM); ADD_SYM($2); ADD_OP(OP_DECR);
552 - ADD_OP(OP_DUP); ADD_OP(OP_ASSIGN); ADD_SYM($2);
555 - ADD_OP(OP_PUSH_SYM); ADD_SYM($1); ADD_OP(OP_DUP);
556 - ADD_OP(OP_DECR); ADD_OP(OP_ASSIGN); ADD_SYM($1);
558 - | numexpr IN numexpr {
559 + | numexpr IN blank numexpr {
562 - | numexpr NOT IN numexpr {
563 + | numexpr NOT IN blank numexpr %prec IN {
570 +while: WHILE blank {
571 + $$ = GetPC(); StartLoopAddrList();
575 $$ = GetPC(); StartLoopAddrList();
580 StartLoopAddrList(); $$ = GetPC();
585 ADD_OP(OP_BRANCH); $$ = GetPC(); ADD_BR_OFF(0);
588 -cond: /* nothing */ {
591 ADD_OP(OP_BRANCH_NEVER); $$ = GetPC(); ADD_BR_OFF(0);
594 + | blank numexpr blank {
595 ADD_OP(OP_BRANCH_FALSE); $$ = GetPC(); ADD_BR_OFF(0);
600 ADD_OP(OP_DUP); ADD_OP(OP_BRANCH_FALSE); $$ = GetPC();
602 @@ -622,17 +494,18 @@ or: OR {
616 %% /* User Subroutines Section */
620 ** Parse a null terminated string and create a program from it (this is the
621 ** parser entry point). The program created by this routine can be
622 @@ -698,19 +571,8 @@ Program *ParseMacro(char *expr, char **m
627 -static int yylex(void)
628 +static char skipWhitespace(void)
632 - static DataValue value = {NO_TAG, {0}};
633 - static char escape[] = "\\\"ntbrfave";
634 -#ifdef EBCDIC_CHARSET
635 - static char replace[] = "\\\"\n\t\b\r\f\a\v\x27"; /* EBCDIC escape */
637 - static char replace[] = "\\\"\n\t\b\r\f\a\v\x1B"; /* ASCII escape */
640 /* skip whitespace, backslash-newline combinations, and comments, which are
641 all considered whitespace */
643 @@ -718,7 +580,8 @@ static int yylex(void)
645 else if (*InPtr == ' ' || *InPtr == '\t')
647 - else if (*InPtr == '#')
648 + else if (*InPtr == '#') {
650 while (*InPtr != '\n' && *InPtr != '\0') {
651 /* Comments stop at escaped newlines */
652 if (*InPtr == '\\' && *(InPtr + 1) == '\n') {
653 @@ -726,10 +589,28 @@ static int yylex(void)
666 +static int yylex(void)
670 + static DataValue value = {NO_TAG, {0}};
671 + static char escape[] = "\\\"ntbrfave";
672 +#ifdef EBCDIC_CHARSET
673 + static char replace[] = "\\\"\n\t\b\r\f\a\v\x27"; /* EBCDIC escape */
675 + static char replace[] = "\\\"\n\t\b\r\f\a\v\x1B"; /* ASCII escape */
681 /* return end of input at the end of the string */
682 if (*InPtr == '\0') {
683 @@ -759,6 +640,7 @@ static int yylex(void)
686 if (!strcmp(symName, "while")) return WHILE;
687 + if (!strcmp(symName, "do")) return DO;
688 if (!strcmp(symName, "if")) return IF;
689 if (!strcmp(symName, "else")) return ELSE;
690 if (!strcmp(symName, "for")) return FOR;
691 @@ -898,7 +780,8 @@ static int yylex(void)
694 /* process remaining two character tokens or return single char as token */
698 case '>': return follow('=', GE, GT);
699 case '<': return follow('=', LE, LT);
700 case '=': return follow('=', EQ, '=');
701 @@ -911,6 +794,14 @@ static int yylex(void)
702 case '/': return follow('=', DIVEQ, '/');
703 case '%': return follow('=', MODEQ, '%');
704 case '^': return POW;
708 + /* skip newline ( whitespace* newline )* */
709 + while (skipWhitespace() == '\n')
711 + return result; /* but return what we started with */
713 default: return *(InPtr-1);