1 /* Copyright (c) 2007, 2012 by Ian Piumarta
2 * All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the 'Software'),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, provided that the above copyright notice(s) and this
10 * permission notice appear in all copies of the Software. Acknowledgement
11 * of the use of this Software in supporting documentation would be
12 * appreciated but is not required.
13 *
14 * THE SOFTWARE IS PROVIDED 'AS IS'. USE ENTIRELY AT YOUR OWN RISK.
15 *
16 * Last edited: 2012-04-29 16:09:36 by piumarta on emilia
17 */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <assert.h>
23
24 #include "version.h"
25 #include "tree.h"
26
yyl(void)27 static int yyl(void)
28 {
29 static int prev= 0;
30 return ++prev;
31 }
32
charClassSet(unsigned char bits[],int c)33 static void charClassSet (unsigned char bits[], int c) { bits[c >> 3] |= (1 << (c & 7)); }
charClassClear(unsigned char bits[],int c)34 static void charClassClear(unsigned char bits[], int c) { bits[c >> 3] &= ~(1 << (c & 7)); }
35
36 typedef void (*setter)(unsigned char bits[], int c);
37
oigit(int c)38 static inline int oigit(int c) { return '0' <= c && c <= '7'; }
39
cnext(unsigned char ** ccp)40 static int cnext(unsigned char **ccp)
41 {
42 unsigned char *cclass= *ccp;
43 int c= *cclass++;
44 if (c)
45 {
46 if ('\\' == c && *cclass)
47 {
48 switch (c= *cclass++)
49 {
50 case 'a': c= '\a'; break; /* bel */
51 case 'b': c= '\b'; break; /* bs */
52 case 'e': c= '\e'; break; /* esc */
53 case 'f': c= '\f'; break; /* ff */
54 case 'n': c= '\n'; break; /* nl */
55 case 'r': c= '\r'; break; /* cr */
56 case 't': c= '\t'; break; /* ht */
57 case 'v': c= '\v'; break; /* vt */
58 default:
59 if (oigit(c))
60 {
61 c -= '0';
62 if (oigit(*cclass)) c= (c << 3) + *cclass++ - '0';
63 if (oigit(*cclass)) c= (c << 3) + *cclass++ - '0';
64 }
65 break;
66 }
67 }
68 *ccp= cclass;
69 }
70 return c;
71 }
72
makeCharClass(unsigned char * cclass)73 static char *makeCharClass(unsigned char *cclass)
74 {
75 unsigned char bits[32];
76 setter set;
77 int c, prev= -1;
78 static char string[256];
79 char *ptr;
80
81 if ('^' == *cclass)
82 {
83 memset(bits, 255, 32);
84 set= charClassClear;
85 ++cclass;
86 }
87 else
88 {
89 memset(bits, 0, 32);
90 set= charClassSet;
91 }
92
93 while (*cclass)
94 {
95 if ('-' == *cclass && cclass[1] && prev >= 0)
96 {
97 ++cclass;
98 for (c= cnext(&cclass); prev <= c; ++prev)
99 set(bits, prev);
100 prev= -1;
101 }
102 else
103 {
104 c= cnext(&cclass);
105 set(bits, prev= c);
106 }
107 }
108
109 ptr= string;
110 for (c= 0; c < 32; ++c)
111 ptr += sprintf(ptr, "\\%03o", bits[c]);
112
113 return string;
114 }
115
begin(void)116 static void begin(void) { fprintf(output, "\n {"); }
end(void)117 static void end(void) { fprintf(output, "\n }"); }
label(int n)118 static void label(int n) { fprintf(output, "\n l%d:;\t", n); }
jump(int n)119 static void jump(int n) { fprintf(output, " goto l%d;", n); }
save(int n)120 static void save(int n) { fprintf(output, " int yypos%d= ctx->pos, yythunkpos%d= ctx->thunkpos;", n, n); }
restore(int n)121 static void restore(int n) { fprintf(output, " ctx->pos= yypos%d; ctx->thunkpos= yythunkpos%d;", n, n); }
122
Node_compile_c_ko(Node * node,int ko)123 static void Node_compile_c_ko(Node *node, int ko)
124 {
125 assert(node);
126 switch (node->type)
127 {
128 case Rule:
129 fprintf(stderr, "\ninternal error #1 (%s)\n", node->rule.name);
130 exit(1);
131 break;
132
133 case Dot:
134 fprintf(output, " if (!yymatchDot(ctx)) goto l%d;", ko);
135 break;
136
137 case Name:
138 fprintf(output, " if (!yy_%s(ctx)) goto l%d;", node->name.rule->rule.name, ko);
139 if (node->name.variable)
140 fprintf(output, " yyDo(ctx, yySet, %d, 0);", node->name.variable->variable.offset);
141 break;
142
143 case Character:
144 case String:
145 {
146 int len= strlen(node->string.value);
147 if (1 == len)
148 {
149 if ('\'' == node->string.value[0])
150 fprintf(output, " if (!yymatchChar(ctx, '\\'')) goto l%d;", ko);
151 else
152 fprintf(output, " if (!yymatchChar(ctx, '%s')) goto l%d;", node->string.value, ko);
153 }
154 else
155 if (2 == len && '\\' == node->string.value[0])
156 fprintf(output, " if (!yymatchChar(ctx, '%s')) goto l%d;", node->string.value, ko);
157 else
158 fprintf(output, " if (!yymatchString(ctx, \"%s\")) goto l%d;", node->string.value, ko);
159 }
160 break;
161
162 case Class:
163 fprintf(output, " if (!yymatchClass(ctx, (unsigned char *)\"%s\")) goto l%d;", makeCharClass(node->cclass.value), ko);
164 break;
165
166 case Action:
167 fprintf(output, " yyDo(ctx, yy%s, ctx->begin, ctx->end);", node->action.name);
168 break;
169
170 case Predicate:
171 fprintf(output, " yyText(ctx, ctx->begin, ctx->end); if (!(%s)) goto l%d;", node->action.text, ko);
172 break;
173
174 case Alternate:
175 {
176 int ok= yyl();
177 begin();
178 save(ok);
179 for (node= node->alternate.first; node; node= node->alternate.next)
180 if (node->alternate.next)
181 {
182 int next= yyl();
183 Node_compile_c_ko(node, next);
184 jump(ok);
185 label(next);
186 restore(ok);
187 }
188 else
189 Node_compile_c_ko(node, ko);
190 end();
191 label(ok);
192 }
193 break;
194
195 case Sequence:
196 for (node= node->sequence.first; node; node= node->sequence.next)
197 Node_compile_c_ko(node, ko);
198 break;
199
200 case PeekFor:
201 {
202 int ok= yyl();
203 begin();
204 save(ok);
205 Node_compile_c_ko(node->peekFor.element, ko);
206 restore(ok);
207 end();
208 }
209 break;
210
211 case PeekNot:
212 {
213 int ok= yyl();
214 begin();
215 save(ok);
216 Node_compile_c_ko(node->peekFor.element, ok);
217 jump(ko);
218 label(ok);
219 restore(ok);
220 end();
221 }
222 break;
223
224 case Query:
225 {
226 int qko= yyl(), qok= yyl();
227 begin();
228 save(qko);
229 Node_compile_c_ko(node->query.element, qko);
230 jump(qok);
231 label(qko);
232 restore(qko);
233 end();
234 label(qok);
235 }
236 break;
237
238 case Star:
239 {
240 int again= yyl(), out= yyl();
241 label(again);
242 begin();
243 save(out);
244 Node_compile_c_ko(node->star.element, out);
245 jump(again);
246 label(out);
247 restore(out);
248 end();
249 }
250 break;
251
252 case Plus:
253 {
254 int again= yyl(), out= yyl();
255 Node_compile_c_ko(node->plus.element, ko);
256 label(again);
257 begin();
258 save(out);
259 Node_compile_c_ko(node->plus.element, out);
260 jump(again);
261 label(out);
262 restore(out);
263 end();
264 }
265 break;
266
267 default:
268 fprintf(stderr, "\nNode_compile_c_ko: illegal node type %d\n", node->type);
269 exit(1);
270 }
271 }
272
273
countVariables(Node * node)274 static int countVariables(Node *node)
275 {
276 int count= 0;
277 while (node)
278 {
279 ++count;
280 node= node->variable.next;
281 }
282 return count;
283 }
284
defineVariables(Node * node)285 static void defineVariables(Node *node)
286 {
287 int count= 0;
288 while (node)
289 {
290 fprintf(output, "#define %s ctx->val[%d]\n", node->variable.name, --count);
291 node->variable.offset= count;
292 node= node->variable.next;
293 }
294 fprintf(output, "#define yy ctx->yy\n");
295 fprintf(output, "#define yypos ctx->pos\n");
296 fprintf(output, "#define yythunkpos ctx->thunkpos\n");
297 }
298
undefineVariables(Node * node)299 static void undefineVariables(Node *node)
300 {
301 fprintf(output, "#undef yythunkpos\n");
302 fprintf(output, "#undef yypos\n");
303 fprintf(output, "#undef yy\n");
304 while (node)
305 {
306 fprintf(output, "#undef %s\n", node->variable.name);
307 node= node->variable.next;
308 }
309 }
310
311
Rule_compile_c2(Node * node)312 static void Rule_compile_c2(Node *node)
313 {
314 assert(node);
315 assert(Rule == node->type);
316
317 if (!node->rule.expression)
318 fprintf(stderr, "rule '%s' used but not defined\n", node->rule.name);
319 else
320 {
321 int ko= yyl(), safe;
322
323 if ((!(RuleUsed & node->rule.flags)) && (node != start))
324 fprintf(stderr, "rule '%s' defined but not used\n", node->rule.name);
325
326 safe= ((Query == node->rule.expression->type) || (Star == node->rule.expression->type));
327
328 fprintf(output, "\nYY_RULE(int) yy_%s(yycontext *ctx)\n{", node->rule.name);
329 if (!safe) save(0);
330 if (node->rule.variables)
331 fprintf(output, " yyDo(ctx, yyPush, %d, 0);", countVariables(node->rule.variables));
332 fprintf(output, "\n yyprintf((stderr, \"%%s\\n\", \"%s\"));", node->rule.name);
333 Node_compile_c_ko(node->rule.expression, ko);
334 fprintf(output, "\n yyprintf((stderr, \" ok %%s @ %%s\\n\", \"%s\", ctx->buf+ctx->pos));", node->rule.name);
335 if (node->rule.variables)
336 fprintf(output, " yyDo(ctx, yyPop, %d, 0);", countVariables(node->rule.variables));
337 fprintf(output, "\n return 1;");
338 if (!safe)
339 {
340 label(ko);
341 restore(0);
342 fprintf(output, "\n yyprintf((stderr, \" fail %%s @ %%s\\n\", \"%s\", ctx->buf+ctx->pos));", node->rule.name);
343 fprintf(output, "\n return 0;");
344 }
345 fprintf(output, "\n}");
346 }
347
348 if (node->rule.next)
349 Rule_compile_c2(node->rule.next);
350 }
351
352 static char *header= "\
353 #include <stdio.h>\n\
354 #include <stdlib.h>\n\
355 #include <string.h>\n\
356 ";
357
358 static char *preamble= "\
359 #ifndef YY_LOCAL\n\
360 #define YY_LOCAL(T) static T\n\
361 #endif\n\
362 #ifndef YY_ACTION\n\
363 #define YY_ACTION(T) static T\n\
364 #endif\n\
365 #ifndef YY_RULE\n\
366 #define YY_RULE(T) static T\n\
367 #endif\n\
368 #ifndef YY_PARSE\n\
369 #define YY_PARSE(T) T\n\
370 #endif\n\
371 #ifndef YYPARSE\n\
372 #define YYPARSE yyparse\n\
373 #endif\n\
374 #ifndef YYPARSEFROM\n\
375 #define YYPARSEFROM yyparsefrom\n\
376 #endif\n\
377 #ifndef YY_INPUT\n\
378 #define YY_INPUT(buf, result, max_size) \\\n\
379 { \\\n\
380 int yyc= getchar(); \\\n\
381 result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \\\n\
382 yyprintf((stderr, \"<%c>\", yyc)); \\\n\
383 }\n\
384 #endif\n\
385 #ifndef YY_BEGIN\n\
386 #define YY_BEGIN ( ctx->begin= ctx->pos, 1)\n\
387 #endif\n\
388 #ifndef YY_END\n\
389 #define YY_END ( ctx->end= ctx->pos, 1)\n\
390 #endif\n\
391 #ifdef YY_DEBUG\n\
392 # define yyprintf(args) fprintf args\n\
393 #else\n\
394 # define yyprintf(args)\n\
395 #endif\n\
396 #ifndef YYSTYPE\n\
397 #define YYSTYPE int\n\
398 #endif\n\
399 \n\
400 #ifndef YY_PART\n\
401 \n\
402 typedef struct _yycontext yycontext;\n\
403 typedef void (*yyaction)(yycontext *ctx, char *yytext, int yyleng);\n\
404 typedef struct _yythunk { int begin, end; yyaction action; struct _yythunk *next; } yythunk;\n\
405 \n\
406 struct _yycontext {\n\
407 char *buf;\n\
408 int buflen;\n\
409 int pos;\n\
410 int limit;\n\
411 char *text;\n\
412 int textlen;\n\
413 int begin;\n\
414 int end;\n\
415 int textmax;\n\
416 yythunk *thunks;\n\
417 int thunkslen;\n\
418 int thunkpos;\n\
419 YYSTYPE yy;\n\
420 YYSTYPE *val;\n\
421 YYSTYPE *vals;\n\
422 int valslen;\n\
423 #ifdef YY_CTX_MEMBERS\n\
424 YY_CTX_MEMBERS\n\
425 #endif\n\
426 };\n\
427 \n\
428 #ifdef YY_CTX_LOCAL\n\
429 #define YY_CTX_PARAM_ yycontext *yyctx,\n\
430 #define YY_CTX_PARAM yycontext *yyctx\n\
431 #define YY_CTX_ARG_ yyctx,\n\
432 #define YY_CTX_ARG yyctx\n\
433 #else\n\
434 #define YY_CTX_PARAM_\n\
435 #define YY_CTX_PARAM\n\
436 #define YY_CTX_ARG_\n\
437 #define YY_CTX_ARG\n\
438 yycontext yyctx0;\n\
439 yycontext *yyctx= &yyctx0;\n\
440 #endif\n\
441 \n\
442 YY_LOCAL(int) yyrefill(yycontext *ctx)\n\
443 {\n\
444 int yyn;\n\
445 while (ctx->buflen - ctx->pos < 512)\n\
446 {\n\
447 ctx->buflen *= 2;\n\
448 ctx->buf= (char *)realloc(ctx->buf, ctx->buflen);\n\
449 }\n\
450 YY_INPUT((ctx->buf + ctx->pos), yyn, (ctx->buflen - ctx->pos));\n\
451 if (!yyn) return 0;\n\
452 ctx->limit += yyn;\n\
453 return 1;\n\
454 }\n\
455 \n\
456 YY_LOCAL(int) yymatchDot(yycontext *ctx)\n\
457 {\n\
458 if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0;\n\
459 ++ctx->pos;\n\
460 return 1;\n\
461 }\n\
462 \n\
463 YY_LOCAL(int) yymatchChar(yycontext *ctx, int c)\n\
464 {\n\
465 if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0;\n\
466 if ((unsigned char)ctx->buf[ctx->pos] == c)\n\
467 {\n\
468 ++ctx->pos;\n\
469 yyprintf((stderr, \" ok yymatchChar(ctx, %c) @ %s\\n\", c, ctx->buf+ctx->pos));\n\
470 return 1;\n\
471 }\n\
472 yyprintf((stderr, \" fail yymatchChar(ctx, %c) @ %s\\n\", c, ctx->buf+ctx->pos));\n\
473 return 0;\n\
474 }\n\
475 \n\
476 YY_LOCAL(int) yymatchString(yycontext *ctx, char *s)\n\
477 {\n\
478 int yysav= ctx->pos;\n\
479 while (*s)\n\
480 {\n\
481 if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0;\n\
482 if (ctx->buf[ctx->pos] != *s)\n\
483 {\n\
484 ctx->pos= yysav;\n\
485 return 0;\n\
486 }\n\
487 ++s;\n\
488 ++ctx->pos;\n\
489 }\n\
490 return 1;\n\
491 }\n\
492 \n\
493 YY_LOCAL(int) yymatchClass(yycontext *ctx, unsigned char *bits)\n\
494 {\n\
495 int c;\n\
496 if (ctx->pos >= ctx->limit && !yyrefill(ctx)) return 0;\n\
497 c= (unsigned char)ctx->buf[ctx->pos];\n\
498 if (bits[c >> 3] & (1 << (c & 7)))\n\
499 {\n\
500 ++ctx->pos;\n\
501 yyprintf((stderr, \" ok yymatchClass @ %s\\n\", ctx->buf+ctx->pos));\n\
502 return 1;\n\
503 }\n\
504 yyprintf((stderr, \" fail yymatchClass @ %s\\n\", ctx->buf+ctx->pos));\n\
505 return 0;\n\
506 }\n\
507 \n\
508 YY_LOCAL(void) yyDo(yycontext *ctx, yyaction action, int begin, int end)\n\
509 {\n\
510 while (ctx->thunkpos >= ctx->thunkslen)\n\
511 {\n\
512 ctx->thunkslen *= 2;\n\
513 ctx->thunks= (yythunk *)realloc(ctx->thunks, sizeof(yythunk) * ctx->thunkslen);\n\
514 }\n\
515 ctx->thunks[ctx->thunkpos].begin= begin;\n\
516 ctx->thunks[ctx->thunkpos].end= end;\n\
517 ctx->thunks[ctx->thunkpos].action= action;\n\
518 ++ctx->thunkpos;\n\
519 }\n\
520 \n\
521 YY_LOCAL(int) yyText(yycontext *ctx, int begin, int end)\n\
522 {\n\
523 int yyleng= end - begin;\n\
524 if (yyleng <= 0)\n\
525 yyleng= 0;\n\
526 else\n\
527 {\n\
528 while (ctx->textlen < (yyleng + 1))\n\
529 {\n\
530 ctx->textlen *= 2;\n\
531 ctx->text= (char *)realloc(ctx->text, ctx->textlen);\n\
532 }\n\
533 memcpy(ctx->text, ctx->buf + begin, yyleng);\n\
534 }\n\
535 ctx->text[yyleng]= '\\0';\n\
536 return yyleng;\n\
537 }\n\
538 \n\
539 YY_LOCAL(void) yyDone(yycontext *ctx)\n\
540 {\n\
541 int pos;\n\
542 for (pos= 0; pos < ctx->thunkpos; ++pos)\n\
543 {\n\
544 yythunk *thunk= &ctx->thunks[pos];\n\
545 int yyleng= thunk->end ? yyText(ctx, thunk->begin, thunk->end) : thunk->begin;\n\
546 yyprintf((stderr, \"DO [%d] %p %s\\n\", pos, thunk->action, ctx->text));\n\
547 thunk->action(ctx, ctx->text, yyleng);\n\
548 }\n\
549 ctx->thunkpos= 0;\n\
550 }\n\
551 \n\
552 YY_LOCAL(void) yyCommit(yycontext *ctx)\n\
553 {\n\
554 if ((ctx->limit -= ctx->pos))\n\
555 {\n\
556 memmove(ctx->buf, ctx->buf + ctx->pos, ctx->limit);\n\
557 }\n\
558 ctx->begin -= ctx->pos;\n\
559 ctx->end -= ctx->pos;\n\
560 ctx->pos= ctx->thunkpos= 0;\n\
561 }\n\
562 \n\
563 YY_LOCAL(int) yyAccept(yycontext *ctx, int tp0)\n\
564 {\n\
565 if (tp0)\n\
566 {\n\
567 fprintf(stderr, \"accept denied at %d\\n\", tp0);\n\
568 return 0;\n\
569 }\n\
570 else\n\
571 {\n\
572 yyDone(ctx);\n\
573 yyCommit(ctx);\n\
574 }\n\
575 return 1;\n\
576 }\n\
577 \n\
578 YY_LOCAL(void) yyPush(yycontext *ctx, char *text, int count) { ctx->val += count; }\n\
579 YY_LOCAL(void) yyPop(yycontext *ctx, char *text, int count) { ctx->val -= count; }\n\
580 YY_LOCAL(void) yySet(yycontext *ctx, char *text, int count) { ctx->val[count]= ctx->yy; }\n\
581 \n\
582 #endif /* YY_PART */\n\
583 \n\
584 #define YYACCEPT yyAccept(ctx, yythunkpos0)\n\
585 \n\
586 ";
587
588 static char *footer= "\n\
589 \n\
590 #ifndef YY_PART\n\
591 \n\
592 typedef int (*yyrule)(yycontext *ctx);\n\
593 \n\
594 YY_PARSE(int) YYPARSEFROM(YY_CTX_PARAM_ yyrule yystart)\n\
595 {\n\
596 int yyok;\n\
597 if (!yyctx->buflen)\n\
598 {\n\
599 yyctx->buflen= 1024;\n\
600 yyctx->buf= (char *)malloc(yyctx->buflen);\n\
601 yyctx->textlen= 1024;\n\
602 yyctx->text= (char *)malloc(yyctx->textlen);\n\
603 yyctx->thunkslen= 32;\n\
604 yyctx->thunks= (yythunk *)malloc(sizeof(yythunk) * yyctx->thunkslen);\n\
605 yyctx->valslen= 32;\n\
606 yyctx->vals= (YYSTYPE *)malloc(sizeof(YYSTYPE) * yyctx->valslen);\n\
607 yyctx->begin= yyctx->end= yyctx->pos= yyctx->limit= yyctx->thunkpos= 0;\n\
608 }\n\
609 yyctx->begin= yyctx->end= yyctx->pos;\n\
610 yyctx->thunkpos= 0;\n\
611 yyctx->val= yyctx->vals;\n\
612 yyok= yystart(yyctx);\n\
613 if (yyok) yyDone(yyctx);\n\
614 yyCommit(yyctx);\n\
615 return yyok;\n\
616 }\n\
617 \n\
618 YY_PARSE(int) YYPARSE(YY_CTX_PARAM)\n\
619 {\n\
620 return YYPARSEFROM(YY_CTX_ARG_ yy_%s);\n\
621 }\n\
622 \n\
623 #endif\n\
624 ";
625
Rule_compile_c_header(void)626 void Rule_compile_c_header(void)
627 {
628 fprintf(output, "/* A recursive-descent parser generated by peg %d.%d.%d */\n", PEG_MAJOR, PEG_MINOR, PEG_LEVEL);
629 fprintf(output, "\n");
630 fprintf(output, "%s", header);
631 fprintf(output, "#define YYRULECOUNT %d\n", ruleCount);
632 }
633
consumesInput(Node * node)634 int consumesInput(Node *node)
635 {
636 if (!node) return 0;
637
638 switch (node->type)
639 {
640 case Rule:
641 {
642 int result= 0;
643 if (RuleReached & node->rule.flags)
644 fprintf(stderr, "possible infinite left recursion in rule '%s'\n", node->rule.name);
645 else
646 {
647 node->rule.flags |= RuleReached;
648 result= consumesInput(node->rule.expression);
649 node->rule.flags &= ~RuleReached;
650 }
651 return result;
652 }
653 break;
654
655 case Dot: return 1;
656 case Name: return consumesInput(node->name.rule);
657 case Character:
658 case String: return strlen(node->string.value) > 0;
659 case Class: return 1;
660 case Action: return 0;
661 case Predicate: return 0;
662
663 case Alternate:
664 {
665 Node *n;
666 for (n= node->alternate.first; n; n= n->alternate.next)
667 if (!consumesInput(n))
668 return 0;
669 }
670 return 1;
671
672 case Sequence:
673 {
674 Node *n;
675 for (n= node->alternate.first; n; n= n->alternate.next)
676 if (consumesInput(n))
677 return 1;
678 }
679 return 0;
680
681 case PeekFor: return 0;
682 case PeekNot: return 0;
683 case Query: return 0;
684 case Star: return 0;
685 case Plus: return consumesInput(node->plus.element);
686
687 default:
688 fprintf(stderr, "\nconsumesInput: illegal node type %d\n", node->type);
689 exit(1);
690 }
691 return 0;
692 }
693
694
Rule_compile_c(Node * node)695 void Rule_compile_c(Node *node)
696 {
697 Node *n;
698
699 for (n= rules; n; n= n->rule.next)
700 consumesInput(n);
701
702 fprintf(output, "%s", preamble);
703 for (n= node; n; n= n->rule.next)
704 fprintf(output, "YY_RULE(int) yy_%s(yycontext *ctx); /* %d */\n", n->rule.name, n->rule.id);
705 fprintf(output, "\n");
706 for (n= actions; n; n= n->action.list)
707 {
708 fprintf(output, "YY_ACTION(void) yy%s(yycontext *ctx, char *yytext, int yyleng)\n{\n", n->action.name);
709 defineVariables(n->action.rule->rule.variables);
710 fprintf(output, " yyprintf((stderr, \"do yy%s\\n\"));\n", n->action.name);
711 fprintf(output, " %s;\n", n->action.text);
712 undefineVariables(n->action.rule->rule.variables);
713 fprintf(output, "}\n");
714 }
715 Rule_compile_c2(node);
716 fprintf(output, footer, start->rule.name);
717 }
718