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