diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7ae22a5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+.DS_Store
+leg
+peg
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..bc45e64
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,58 @@
+CFLAGS = -g -Wall $(OFLAGS) $(XFLAGS)
+OFLAGS = -O3 -DNDEBUG
+#OFLAGS = -pg
+
+OBJS = tree.o compile.o
+
+all : peg leg
+
+peg : peg.o $(OBJS)
+ $(CC) $(CFLAGS) -o $@-new peg.o $(OBJS)
+ mv $@-new $@
+
+leg : leg.o $(OBJS)
+ $(CC) $(CFLAGS) -o $@-new leg.o $(OBJS)
+ mv $@-new $@
+
+ROOT =
+PREFIX = /usr/local
+BINDIR = $(ROOT)$(PREFIX)/bin
+
+install : $(BINDIR)/peg $(BINDIR)/leg
+
+$(BINDIR)/% : %
+ cp -p $< $@
+ strip $@
+
+uninstall : .FORCE
+ rm -f $(BINDIR)/peg
+ rm -f $(BINDIR)/leg
+
+peg.o : peg.c peg.peg-c
+
+%.peg-c : %.peg
+# ./peg -o $@ $<
+
+leg.o : leg.c
+
+leg.c : leg.leg
+# ./leg -o $@ $<
+
+check : peg .FORCE
+ ./peg < peg.peg > peg.out
+ diff peg.peg-c peg.out
+ rm peg.out
+
+test examples : .FORCE
+ $(SHELL) -ec '(cd examples; $(MAKE))'
+
+clean : .FORCE
+ rm -f *~ *.o *.peg.[cd] *.leg.[cd]
+ $(SHELL) -ec '(cd examples; $(MAKE) $@)'
+
+spotless : clean .FORCE
+ rm -f peg
+ rm -f leg
+ $(SHELL) -ec '(cd examples; $(MAKE) $@)'
+
+.FORCE :
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..02fef7a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,30 @@
+# peg/leg — recursive-descent parser generators for C
+
+`peg` and `leg` are tools for generating recursive-descent parsers: programs that perform pattern matching on
+text. They processes a Parsing Expression Grammar (PEG)[Ford 2004] to produce a program that recognises legal sentences of that grammar.
+
+`peg` processes PEGs written using the original syntax described by Ford.
+
+`leg` processes PEGs written using slightly different syntax and conventions that are intended to make it an attractive replacement for parsers built with `lex` and `yacc`.
+
+Unlike `lex` and `yacc`, `peg` and `leg` support unlimited backtracking, provide ordered choice as a means for disambiguation, and can combine scanning (lexical analysis) and parsing (syntactic analysis) into a single activity.
+
+`peg` is distributed under the MIT license. It will not infect your project with a contagious license disease if you
+decide to modify it for your own use. The parser generators that `peg` creates are unencumbered and you are free to use and/or
+distribute them any way you like.
+
+`peg`/`leg` is copyright (c) 2007 by Ian Piumarta.
+
+## References
+
+* `peg`/`leg` manual page: [peg.1.html][1]
+
+* [Ford 2004] Bryan Ford, [*Parsing Expression Grammars: A Recognition-Based Syntactic Foundation*][2]. ACM SIGPLAN Symposium on Principles of Programming Languages (POPL), 2004.
+
+[1]: http://piumarta.com/software/peg/peg.1.html "peg/leg manual"
+[2]: http://bford.info/pub/lang/peg "Parsing Expression Grammars: A Recognition-Based Syntactic Foundation"
+
+## Version history
+
+* **0.1.1** ([zip](peg/zipball/0.1.1), [tar.gz](peg/tarball/0.1.1)) — 2007-05-15
+First public release.
diff --git a/compile.c b/compile.c
new file mode 100644
index 0000000..b6ce7ad
--- /dev/null
+++ b/compile.c
@@ -0,0 +1,676 @@
+/* Copyright (c) 2007 by Ian Piumarta
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the 'Software'),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, provided that the above copyright notice(s) and this
+ * permission notice appear in all copies of the Software. Acknowledgement
+ * of the use of this Software in supporting documentation would be
+ * appreciated but is not required.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS'. USE ENTIRELY AT YOUR OWN RISK.
+ *
+ * Last edited: 2007-05-15 10:31:16 by piumarta on emilia
+ */
+
+#include
+#include
+#include
+#include
+
+#include "version.h"
+#include "tree.h"
+
+static int yyl(void)
+{
+ static int prev= 0;
+ return ++prev;
+}
+
+static void charClassSet (unsigned char bits[], int c) { bits[c >> 3] |= (1 << (c & 7)); }
+static void charClassClear(unsigned char bits[], int c) { bits[c >> 3] &= ~(1 << (c & 7)); }
+
+typedef void (*setter)(unsigned char bits[], int c);
+
+static char *makeCharClass(unsigned char *cclass)
+{
+ unsigned char bits[32];
+ setter set;
+ int c, prev= -1;
+ static char string[256];
+ char *ptr;
+
+ if ('^' == *cclass)
+ {
+ memset(bits, 255, 32);
+ set= charClassClear;
+ ++cclass;
+ }
+ else
+ {
+ memset(bits, 0, 32);
+ set= charClassSet;
+ }
+ while ((c= *cclass++))
+ {
+ if ('-' == c && *cclass && prev >= 0)
+ {
+ for (c= *cclass++; prev <= c; ++prev)
+ set(bits, prev);
+ prev= -1;
+ }
+ else if ('\\' == c && *cclass)
+ {
+ switch (c= *cclass++)
+ {
+ case 'a': c= '\a'; break; /* bel */
+ case 'b': c= '\b'; break; /* bs */
+ case 'e': c= '\e'; break; /* esc */
+ case 'f': c= '\f'; break; /* ff */
+ case 'n': c= '\n'; break; /* nl */
+ case 'r': c= '\r'; break; /* cr */
+ case 't': c= '\t'; break; /* ht */
+ case 'v': c= '\v'; break; /* vt */
+ default: break;
+ }
+ set(bits, prev= c);
+ }
+ else
+ set(bits, prev= c);
+ }
+
+ ptr= string;
+ for (c= 0; c < 32; ++c)
+ ptr += sprintf(ptr, "\\%03o", bits[c]);
+
+ return string;
+}
+
+static void begin(void) { fprintf(output, "\n {"); }
+static void end(void) { fprintf(output, "\n }"); }
+static void label(int n) { fprintf(output, "\n l%d:;\t", n); }
+static void jump(int n) { fprintf(output, " goto l%d;", n); }
+static void save(int n) { fprintf(output, " int yypos%d= yypos, yythunkpos%d= yythunkpos;", n, n); }
+static void restore(int n) { fprintf(output, " yypos= yypos%d; yythunkpos= yythunkpos%d;", n, n); }
+
+static void Node_compile_c_ko(Node *node, int ko)
+{
+ assert(node);
+ switch (node->type)
+ {
+ case Rule:
+ fprintf(stderr, "\ninternal error #1 (%s)\n", node->rule.name);
+ exit(1);
+ break;
+
+ case Dot:
+ fprintf(output, " if (!yymatchDot()) goto l%d;", ko);
+ break;
+
+ case Name:
+ fprintf(output, " if (!yy_%s()) goto l%d;", node->name.rule->rule.name, ko);
+ if (node->name.variable)
+ fprintf(output, " yyDo(yySet, %d, 0);", node->name.variable->variable.offset);
+ break;
+
+ case Character:
+ case String:
+ {
+ int len= strlen(node->string.value);
+ if (1 == len || (2 == len && '\\' == node->string.value[0]))
+ fprintf(output, " if (!yymatchChar('%s')) goto l%d;", node->string.value, ko);
+ else
+ fprintf(output, " if (!yymatchString(\"%s\")) goto l%d;", node->string.value, ko);
+ }
+ break;
+
+ case Class:
+ fprintf(output, " if (!yymatchClass((unsigned char *)\"%s\")) goto l%d;", makeCharClass(node->cclass.value), ko);
+ break;
+
+ case Action:
+ fprintf(output, " yyDo(yy%s, yybegin, yyend);", node->action.name);
+ break;
+
+ case Predicate:
+ fprintf(output, " yyText(yybegin, yyend); if (!(%s)) goto l%d;", node->action.text, ko);
+ break;
+
+ case Alternate:
+ {
+ int ok= yyl();
+ begin();
+ save(ok);
+ for (node= node->alternate.first; node; node= node->alternate.next)
+ if (node->alternate.next)
+ {
+ int next= yyl();
+ Node_compile_c_ko(node, next);
+ jump(ok);
+ label(next);
+ restore(ok);
+ }
+ else
+ Node_compile_c_ko(node, ko);
+ end();
+ label(ok);
+ }
+ break;
+
+ case Sequence:
+ for (node= node->sequence.first; node; node= node->sequence.next)
+ Node_compile_c_ko(node, ko);
+ break;
+
+ case PeekFor:
+ {
+ int ok= yyl();
+ begin();
+ save(ok);
+ Node_compile_c_ko(node->peekFor.element, ko);
+ restore(ok);
+ end();
+ }
+ break;
+
+ case PeekNot:
+ {
+ int ok= yyl();
+ begin();
+ save(ok);
+ Node_compile_c_ko(node->peekFor.element, ok);
+ jump(ko);
+ label(ok);
+ restore(ok);
+ end();
+ }
+ break;
+
+ case Query:
+ {
+ int qko= yyl(), qok= yyl();
+ begin();
+ save(qko);
+ Node_compile_c_ko(node->query.element, qko);
+ jump(qok);
+ label(qko);
+ restore(qko);
+ end();
+ label(qok);
+ }
+ break;
+
+ case Star:
+ {
+ int again= yyl(), out= yyl();
+ label(again);
+ begin();
+ save(out);
+ Node_compile_c_ko(node->star.element, out);
+ jump(again);
+ label(out);
+ restore(out);
+ end();
+ }
+ break;
+
+ case Plus:
+ {
+ int again= yyl(), out= yyl();
+ Node_compile_c_ko(node->plus.element, ko);
+ label(again);
+ begin();
+ save(out);
+ Node_compile_c_ko(node->plus.element, out);
+ jump(again);
+ label(out);
+ restore(out);
+ end();
+ }
+ break;
+
+ default:
+ fprintf(stderr, "\nNode_compile_c_ko: illegal node type %d\n", node->type);
+ exit(1);
+ }
+}
+
+
+static int countVariables(Node *node)
+{
+ int count= 0;
+ while (node)
+ {
+ ++count;
+ node= node->variable.next;
+ }
+ return count;
+}
+
+static void defineVariables(Node *node)
+{
+ int count= 0;
+ while (node)
+ {
+ fprintf(output, "#define %s yyval[%d]\n", node->variable.name, --count);
+ node->variable.offset= count;
+ node= node->variable.next;
+ }
+}
+
+static void undefineVariables(Node *node)
+{
+ while (node)
+ {
+ fprintf(output, "#undef %s\n", node->variable.name);
+ node= node->variable.next;
+ }
+}
+
+
+static void Rule_compile_c2(Node *node)
+{
+ assert(node);
+ assert(Rule == node->type);
+
+ if (!node->rule.expression)
+ fprintf(stderr, "rule '%s' used but not defined\n", node->rule.name);
+ else
+ {
+ int ko= yyl(), safe;
+
+ if ((!(RuleUsed & node->rule.flags)) && (node != start))
+ fprintf(stderr, "rule '%s' defined but not used\n", node->rule.name);
+
+ safe= ((Query == node->rule.expression->type) || (Star == node->rule.expression->type));
+
+ fprintf(output, "\nYY_RULE(int) yy_%s()\n{", node->rule.name);
+ if (!safe) save(0);
+ if (node->rule.variables)
+ fprintf(output, " yyDo(yyPush, %d, 0);", countVariables(node->rule.variables));
+ fprintf(output, "\n yyprintf((stderr, \"%%s\\n\", \"%s\"));", node->rule.name);
+ Node_compile_c_ko(node->rule.expression, ko);
+ fprintf(output, "\n yyprintf((stderr, \" ok %%s @ %%s\\n\", \"%s\", yybuf+yypos));", node->rule.name);
+ if (node->rule.variables)
+ fprintf(output, " yyDo(yyPop, %d, 0);", countVariables(node->rule.variables));
+ fprintf(output, "\n return 1;");
+ if (!safe)
+ {
+ label(ko);
+ restore(0);
+ fprintf(output, "\n yyprintf((stderr, \" fail %%s @ %%s\\n\", \"%s\", yybuf+yypos));", node->rule.name);
+ fprintf(output, "\n return 0;");
+ }
+ fprintf(output, "\n}");
+ }
+
+ if (node->rule.next)
+ Rule_compile_c2(node->rule.next);
+}
+
+static char *header= "\
+#include \n\
+#include \n\
+#include \n\
+";
+
+static char *preamble= "\
+#ifndef YY_VARIABLE\n\
+#define YY_VARIABLE(T) static T\n\
+#endif\n\
+#ifndef YY_LOCAL\n\
+#define YY_LOCAL(T) static T\n\
+#endif\n\
+#ifndef YY_ACTION\n\
+#define YY_ACTION(T) static T\n\
+#endif\n\
+#ifndef YY_RULE\n\
+#define YY_RULE(T) static T\n\
+#endif\n\
+#ifndef YY_PARSE\n\
+#define YY_PARSE(T) T\n\
+#endif\n\
+#ifndef YYPARSE\n\
+#define YYPARSE yyparse\n\
+#endif\n\
+#ifndef YYPARSEFROM\n\
+#define YYPARSEFROM yyparsefrom\n\
+#endif\n\
+#ifndef YY_INPUT\n\
+#define YY_INPUT(buf, result, max_size) \\\n\
+ { \\\n\
+ int yyc= getchar(); \\\n\
+ result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \\\n\
+ yyprintf((stderr, \"<%c>\", yyc)); \\\n\
+ }\n\
+#endif\n\
+#ifndef YY_BEGIN\n\
+#define YY_BEGIN ( yybegin= yypos, 1)\n\
+#endif\n\
+#ifndef YY_END\n\
+#define YY_END ( yyend= yypos, 1)\n\
+#endif\n\
+#ifdef YY_DEBUG\n\
+# define yyprintf(args) fprintf args\n\
+#else\n\
+# define yyprintf(args)\n\
+#endif\n\
+#ifndef YYSTYPE\n\
+#define YYSTYPE int\n\
+#endif\n\
+\n\
+#ifndef YY_PART\n\
+\n\
+typedef void (*yyaction)(char *yytext, int yyleng);\n\
+typedef struct _yythunk { int begin, end; yyaction action; struct _yythunk *next; } yythunk;\n\
+\n\
+YY_VARIABLE(char * ) yybuf= 0;\n\
+YY_VARIABLE(int ) yybuflen= 0;\n\
+YY_VARIABLE(int ) yypos= 0;\n\
+YY_VARIABLE(int ) yylimit= 0;\n\
+YY_VARIABLE(char * ) yytext= 0;\n\
+YY_VARIABLE(int ) yytextlen= 0;\n\
+YY_VARIABLE(int ) yybegin= 0;\n\
+YY_VARIABLE(int ) yyend= 0;\n\
+YY_VARIABLE(int ) yytextmax= 0;\n\
+YY_VARIABLE(yythunk *) yythunks= 0;\n\
+YY_VARIABLE(int ) yythunkslen= 0;\n\
+YY_VARIABLE(int ) yythunkpos= 0;\n\
+YY_VARIABLE(YYSTYPE ) yy;\n\
+YY_VARIABLE(YYSTYPE *) yyval= 0;\n\
+YY_VARIABLE(YYSTYPE *) yyvals= 0;\n\
+YY_VARIABLE(int ) yyvalslen= 0;\n\
+\n\
+YY_LOCAL(int) yyrefill(void)\n\
+{\n\
+ int yyn;\n\
+ if (yybuflen - yypos < 512)\n\
+ {\n\
+ yybuflen *= 2;\n\
+ yybuf= realloc(yybuf, yybuflen);\n\
+ }\n\
+ YY_INPUT((yybuf + yypos), yyn, (yybuflen - yypos));\n\
+ if (!yyn) return 0;\n\
+ yylimit += yyn;\n\
+ return 1;\n\
+}\n\
+\n\
+YY_LOCAL(int) yymatchDot(void)\n\
+{\n\
+ if (yypos >= yylimit && !yyrefill()) return 0;\n\
+ ++yypos;\n\
+ return 1;\n\
+}\n\
+\n\
+YY_LOCAL(int) yymatchChar(int c)\n\
+{\n\
+ if (yypos >= yylimit && !yyrefill()) return 0;\n\
+ if (yybuf[yypos] == c)\n\
+ {\n\
+ ++yypos;\n\
+ yyprintf((stderr, \" ok yymatchChar(%c) @ %s\\n\", c, yybuf+yypos));\n\
+ return 1;\n\
+ }\n\
+ yyprintf((stderr, \" fail yymatchChar(%c) @ %s\\n\", c, yybuf+yypos));\n\
+ return 0;\n\
+}\n\
+\n\
+YY_LOCAL(int) yymatchString(char *s)\n\
+{\n\
+ int yysav= yypos;\n\
+ while (*s)\n\
+ {\n\
+ if (yypos >= yylimit && !yyrefill()) return 0;\n\
+ if (yybuf[yypos] != *s)\n\
+ {\n\
+ yypos= yysav;\n\
+ return 0;\n\
+ }\n\
+ ++s;\n\
+ ++yypos;\n\
+ }\n\
+ return 1;\n\
+}\n\
+\n\
+YY_LOCAL(int) yymatchClass(unsigned char *bits)\n\
+{\n\
+ int c;\n\
+ if (yypos >= yylimit && !yyrefill()) return 0;\n\
+ c= yybuf[yypos];\n\
+ if (bits[c >> 3] & (1 << (c & 7)))\n\
+ {\n\
+ ++yypos;\n\
+ yyprintf((stderr, \" ok yymatchClass @ %s\\n\", yybuf+yypos));\n\
+ return 1;\n\
+ }\n\
+ yyprintf((stderr, \" fail yymatchClass @ %s\\n\", yybuf+yypos));\n\
+ return 0;\n\
+}\n\
+\n\
+YY_LOCAL(void) yyDo(yyaction action, int begin, int end)\n\
+{\n\
+ if (yythunkpos >= yythunkslen)\n\
+ {\n\
+ yythunkslen *= 2;\n\
+ yythunks= realloc(yythunks, sizeof(yythunk) * yythunkslen);\n\
+ }\n\
+ yythunks[yythunkpos].begin= begin;\n\
+ yythunks[yythunkpos].end= end;\n\
+ yythunks[yythunkpos].action= action;\n\
+ ++yythunkpos;\n\
+}\n\
+\n\
+YY_LOCAL(int) yyText(int begin, int end)\n\
+{\n\
+ int yyleng= end - begin;\n\
+ if (yyleng <= 0)\n\
+ yyleng= 0;\n\
+ else\n\
+ {\n\
+ if (yytextlen < (yyleng - 1))\n\
+ {\n\
+ yytextlen *= 2;\n\
+ yytext= realloc(yytext, yytextlen);\n\
+ }\n\
+ memcpy(yytext, yybuf + begin, yyleng);\n\
+ }\n\
+ yytext[yyleng]= '\\0';\n\
+ return yyleng;\n\
+}\n\
+\n\
+YY_LOCAL(void) yyDone(void)\n\
+{\n\
+ int pos;\n\
+ for (pos= 0; pos < yythunkpos; ++pos)\n\
+ {\n\
+ yythunk *thunk= &yythunks[pos];\n\
+ int yyleng= thunk->end ? yyText(thunk->begin, thunk->end) : thunk->begin;\n\
+ yyprintf((stderr, \"DO [%d] %p %s\\n\", pos, thunk->action, yytext));\n\
+ thunk->action(yytext, yyleng);\n\
+ }\n\
+ yythunkpos= 0;\n\
+}\n\
+\n\
+YY_LOCAL(void) yyCommit()\n\
+{\n\
+ if ((yylimit -= yypos))\n\
+ {\n\
+ memmove(yybuf, yybuf + yypos, yylimit);\n\
+ }\n\
+ yybegin -= yypos;\n\
+ yyend -= yypos;\n\
+ yypos= yythunkpos= 0;\n\
+}\n\
+\n\
+YY_LOCAL(int) yyAccept(int tp0)\n\
+{\n\
+ if (tp0)\n\
+ {\n\
+ fprintf(stderr, \"accept denied at %d\\n\", tp0);\n\
+ return 0;\n\
+ }\n\
+ else\n\
+ {\n\
+ yyDone();\n\
+ yyCommit();\n\
+ }\n\
+ return 1;\n\
+}\n\
+\n\
+YY_LOCAL(void) yyPush(char *text, int count) { yyval += count; }\n\
+YY_LOCAL(void) yyPop(char *text, int count) { yyval -= count; }\n\
+YY_LOCAL(void) yySet(char *text, int count) { yyval[count]= yy; }\n\
+\n\
+#endif /* YY_PART */\n\
+\n\
+#define YYACCEPT yyAccept(yythunkpos0)\n\
+\n\
+";
+
+static char *footer= "\n\
+\n\
+#ifndef YY_PART\n\
+\n\
+typedef int (*yyrule)();\n\
+\n\
+YY_PARSE(int) YYPARSEFROM(yyrule yystart)\n\
+{\n\
+ int yyok;\n\
+ if (!yybuflen)\n\
+ {\n\
+ yybuflen= 1024;\n\
+ yybuf= malloc(yybuflen);\n\
+ yytextlen= 1024;\n\
+ yytext= malloc(yytextlen);\n\
+ yythunkslen= 32;\n\
+ yythunks= malloc(sizeof(yythunk) * yythunkslen);\n\
+ yyvalslen= 32;\n\
+ yyvals= malloc(sizeof(YYSTYPE) * yyvalslen);\n\
+ yybegin= yyend= yypos= yylimit= yythunkpos= 0;\n\
+ }\n\
+ yybegin= yyend= yypos;\n\
+ yythunkpos= 0;\n\
+ yyval= yyvals;\n\
+ yyok= yystart();\n\
+ if (yyok) yyDone();\n\
+ yyCommit();\n\
+ return yyok;\n\
+ (void)yyrefill;\n\
+ (void)yymatchDot;\n\
+ (void)yymatchChar;\n\
+ (void)yymatchString;\n\
+ (void)yymatchClass;\n\
+ (void)yyDo;\n\
+ (void)yyText;\n\
+ (void)yyDone;\n\
+ (void)yyCommit;\n\
+ (void)yyAccept;\n\
+ (void)yyPush;\n\
+ (void)yyPop;\n\
+ (void)yySet;\n\
+ (void)yytextmax;\n\
+}\n\
+\n\
+YY_PARSE(int) YYPARSE(void)\n\
+{\n\
+ return YYPARSEFROM(yy_%s);\n\
+}\n\
+\n\
+#endif\n\
+";
+
+void Rule_compile_c_header(void)
+{
+ fprintf(output, "/* A recursive-descent parser generated by peg %d.%d.%d */\n", PEG_MAJOR, PEG_MINOR, PEG_LEVEL);
+ fprintf(output, "\n");
+ fprintf(output, "%s", header);
+ fprintf(output, "#define YYRULECOUNT %d\n", ruleCount);
+}
+
+int consumesInput(Node *node)
+{
+ if (!node) return 0;
+
+ switch (node->type)
+ {
+ case Rule:
+ {
+ int result= 0;
+ if (RuleReached & node->rule.flags)
+ fprintf(stderr, "possible infinite left recursion in rule '%s'\n", node->rule.name);
+ else
+ {
+ node->rule.flags |= RuleReached;
+ result= consumesInput(node->rule.expression);
+ node->rule.flags &= ~RuleReached;
+ }
+ return result;
+ }
+ break;
+
+ case Dot: return 1;
+ case Name: return consumesInput(node->name.rule);
+ case Character:
+ case String: return strlen(node->string.value) > 0;
+ case Class: return 1;
+ case Action: return 0;
+ case Predicate: return 0;
+
+ case Alternate:
+ {
+ Node *n;
+ for (n= node->alternate.first; n; n= n->alternate.next)
+ if (!consumesInput(n))
+ return 0;
+ }
+ return 1;
+
+ case Sequence:
+ {
+ Node *n;
+ for (n= node->alternate.first; n; n= n->alternate.next)
+ if (consumesInput(n))
+ return 1;
+ }
+ return 0;
+
+ case PeekFor: return 0;
+ case PeekNot: return 0;
+ case Query: return 0;
+ case Star: return 0;
+ case Plus: return consumesInput(node->plus.element);
+
+ default:
+ fprintf(stderr, "\nconsumesInput: illegal node type %d\n", node->type);
+ exit(1);
+ }
+ return 0;
+}
+
+
+void Rule_compile_c(Node *node)
+{
+ Node *n;
+
+ for (n= rules; n; n= n->rule.next)
+ consumesInput(n);
+
+ fprintf(output, "%s", preamble);
+ for (n= node; n; n= n->rule.next)
+ fprintf(output, "YY_RULE(int) yy_%s(); /* %d */\n", n->rule.name, n->rule.id);
+ fprintf(output, "\n");
+ for (n= actions; n; n= n->action.list)
+ {
+ fprintf(output, "YY_ACTION(void) yy%s(char *yytext, int yyleng)\n{\n", n->action.name);
+ defineVariables(n->action.rule->rule.variables);
+ fprintf(output, " yyprintf((stderr, \"do yy%s\\n\"));\n", n->action.name);
+ fprintf(output, " %s;\n", n->action.text);
+ undefineVariables(n->action.rule->rule.variables);
+ fprintf(output, "}\n");
+ }
+ Rule_compile_c2(node);
+ fprintf(output, footer, start->rule.name);
+}
diff --git a/examples/Makefile b/examples/Makefile
new file mode 100644
index 0000000..57ac5f5
--- /dev/null
+++ b/examples/Makefile
@@ -0,0 +1,79 @@
+EXAMPLES = test rule accept wc dc dcv calc basic
+
+CFLAGS = -g -O3
+
+DIFF = diff
+TEE = cat >
+
+all : $(EXAMPLES)
+
+test : .FORCE
+ ../peg -o test.peg.c test.peg
+ $(CC) $(CFLAGS) -o test test.c
+ echo 'ab.ac.ad.ae.afg.afh.afg.afh.afi.afj.' | ./$@ | $(TEE) $@.out
+ $(DIFF) $@.ref $@.out
+ rm -f $@.out
+ @echo
+
+rule : .FORCE
+ ../peg -o rule.peg.c rule.peg
+ $(CC) $(CFLAGS) -o rule rule.c
+ echo 'abcbcdabcbcdabcbcdabcbcd' | ./$@ | $(TEE) $@.out
+ $(DIFF) $@.ref $@.out
+ rm -f $@.out
+ @echo
+
+accept : .FORCE
+ ../peg -o accept.peg.c accept.peg
+ $(CC) $(CFLAGS) -o accept accept.c
+ echo 'abcbcdabcbcdabcbcdabcbcd' | ./$@ | $(TEE) $@.out
+ $(DIFF) $@.ref $@.out
+ rm -f $@.out
+ @echo
+
+wc : .FORCE
+ ../leg -o wc.leg.c wc.leg
+ $(CC) $(CFLAGS) -o wc wc.leg.c
+ cat wc.leg | ./$@ | $(TEE) $@.out
+ $(DIFF) $@.ref $@.out
+ rm -f $@.out
+ @echo
+
+dc : .FORCE
+ ../peg -o dc.peg.c dc.peg
+ $(CC) $(CFLAGS) -o dc dc.c
+ echo ' 2 *3 *(3+ 4) ' | ./dc | $(TEE) $@.out
+ $(DIFF) $@.ref $@.out
+ rm -f $@.out
+ @echo
+
+dcv : .FORCE
+ ../peg -o dcv.peg.c dcv.peg
+ $(CC) $(CFLAGS) -o dcv dcv.c
+ echo 'a = 6; b = 7; a * b' | ./dcv | $(TEE) $@.out
+ $(DIFF) $@.ref $@.out
+ rm -f $@.out
+ @echo
+
+calc : .FORCE
+ ../leg -o calc.leg.c calc.leg
+ $(CC) $(CFLAGS) -o calc calc.leg.c
+ echo 'a = 6; b = 7; a * b' | ./calc | $(TEE) $@.out
+ $(DIFF) $@.ref $@.out
+ rm -f $@.out
+ @echo
+
+basic : .FORCE
+ ../leg -o basic.leg.c basic.leg
+ $(CC) $(CFLAGS) -o basic basic.leg.c
+ ( echo 'load "test"'; echo "run" ) | ./basic | $(TEE) $@.out
+ $(DIFF) $@.ref $@.out
+ rm -f $@.out
+ @echo
+
+clean : .FORCE
+ rm -f *~ *.o *.[pl]eg.[cd] $(EXAMPLES)
+
+spotless : clean
+
+.FORCE :
diff --git a/examples/accept.c b/examples/accept.c
new file mode 100644
index 0000000..781e3b1
--- /dev/null
+++ b/examples/accept.c
@@ -0,0 +1,11 @@
+#include
+#include
+
+#include "accept.peg.c"
+
+int main()
+{
+ while (yyparse());
+
+ return 0;
+}
diff --git a/examples/accept.peg b/examples/accept.peg
new file mode 100644
index 0000000..9b28e40
--- /dev/null
+++ b/examples/accept.peg
@@ -0,0 +1,8 @@
+start <- abcd+
+
+abcd <- 'a' { printf("A %d\n", yypos); } bc { printf("ABC %d\n", yypos); } &{YYACCEPT}
+ / 'b' { printf("B %d\n", yypos); } cd { printf("BCD %d\n", yypos); } &{YYACCEPT}
+
+bc <- 'b' { printf("B %d\n", yypos); } 'c' { printf("C %d\n", yypos); }
+
+cd <- 'c' { printf("C %d\n", yypos); } 'd' { printf("D %d\n", yypos); }
diff --git a/examples/accept.ref b/examples/accept.ref
new file mode 100644
index 0000000..789f528
--- /dev/null
+++ b/examples/accept.ref
@@ -0,0 +1,32 @@
+A 3
+B 3
+C 3
+ABC 3
+B 3
+C 3
+D 3
+BCD 3
+A 3
+B 3
+C 3
+ABC 3
+B 3
+C 3
+D 3
+BCD 3
+A 3
+B 3
+C 3
+ABC 3
+B 3
+C 3
+D 3
+BCD 3
+A 3
+B 3
+C 3
+ABC 3
+B 3
+C 3
+D 3
+BCD 3
diff --git a/examples/basic.leg b/examples/basic.leg
new file mode 100644
index 0000000..20227af
--- /dev/null
+++ b/examples/basic.leg
@@ -0,0 +1,360 @@
+# A 'syntax-directed interpreter' (all execution is a side-effect of parsing).
+# Inspired by Dennis Allison's original Tiny BASIC grammar, circa 1975.
+#
+# Copyright (c) 2007 by Ian Piumarta
+# All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the 'Software'),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, provided that the above copyright notice(s) and this
+# permission notice appear in all copies of the Software. Acknowledgement
+# of the use of this Software in supporting documentation would be
+# appreciated but is not required.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS'. USE ENTIRELY AT YOUR OWN RISK.
+#
+# Last edited: 2007-05-14 11:32:49 by piumarta on emilia
+
+%{
+# include
+
+ typedef struct line line;
+
+ struct line
+ {
+ int number;
+ int length;
+ char *text;
+ };
+
+ line *lines= 0;
+ int numLines= 0;
+ int pc= -1, epc= -1;
+ int batch= 0;
+
+ int getline(char *buf, int max);
+
+# define min(x, y) ((x) < (y) ? (x) : (y))
+
+# define YY_INPUT(buf, result, max_size) \
+ { \
+ if ((pc >= 0) && (pc < numLines)) \
+ { \
+ line *linep= lines+pc++; \
+ result= min(max_size, linep->length); \
+ memcpy(buf, linep->text, result); \
+ } \
+ else \
+ result= getline(buf, max_size); \
+ }
+
+ union value {
+ int number;
+ char *string;
+ int (*binop)(int lhs, int rhs);
+ };
+
+# define YYSTYPE union value
+
+ int variables[26];
+
+ void accept(int number, char *line);
+
+ void save(char *name);
+ void load(char *name);
+ void type(char *name);
+
+ int lessThan(int lhs, int rhs) { return lhs < rhs; }
+ int lessEqual(int lhs, int rhs) { return lhs <= rhs; }
+ int notEqual(int lhs, int rhs) { return lhs != rhs; }
+ int equalTo(int lhs, int rhs) { return lhs == rhs; }
+ int greaterEqual(int lhs, int rhs) { return lhs >= rhs; }
+ int greaterThan(int lhs, int rhs) { return lhs > rhs; }
+
+ int input(void);
+
+ int stack[1024], sp= 0;
+
+ char *help;
+
+ void error(char *fmt, ...);
+%}
+
+line = - s:statement CR
+| - n:number < ( !CR . )* CR > { accept(n.number, yytext); }
+| - CR
+| - < ( !CR . )* CR > { epc= pc; error("syntax error"); }
+| - !. { exit(0); }
+
+statement = 'print'- expr-list
+| 'if'- e1:expression r:relop e2:expression { if (!r.binop(e1.number, e2.number)) yythunkpos= 0; }
+ 'then'- statement
+| 'goto'- e:expression { epc= pc; if ((pc= findLine(e.number, 0)) < 0) error("no such line"); }
+| 'input'- var-list
+| 'let'- v:var EQUAL e:expression { variables[v.number]= e.number; }
+| 'gosub'- e:expression { epc= pc; if (sp < 1024) stack[sp++]= pc, pc= findLine(e.number); else error("too many gosubs");
+ if (pc < 0) error("no such line"); }
+| 'return'- { epc= pc; if ((pc= sp ? stack[--sp] : -1) < 0) error("no gosub"); }
+| 'clear'- { while (numLines) accept(lines->number, "\n"); }
+| 'list'- { int i; for (i= 0; i < numLines; ++i) printf("%5d %s", lines[i].number, lines[i].text); }
+| 'run'- s:string { load(s.string); pc= 0; }
+| 'run'- { pc= 0; }
+| 'end'- { pc= -1; if (batch) exit(0); }
+| 'rem'- ( !CR . )*
+| ('bye'|'quit'|'exit')- { exit(0); }
+| 'save'- s:string { save(s.string); }
+| 'load'- s:string { load(s.string); }
+| 'type'- s:string { type(s.string); }
+| 'dir'- { system("ls *.bas"); }
+| 'help'- { fprintf(stderr, "%s", help); }
+
+expr-list = ( e:string { printf("%s", e.string); }
+ | e:expression { printf("%d", e.number); }
+ )? ( COMMA ( e:string { printf("%s", e.string); }
+ | e:expression { printf("%d", e.number); }
+ )
+ )* ( COMMA
+ | !COMMA { printf("\n"); }
+ )
+
+var-list = v:var { variables[v.number]= input(); }
+ ( COMMA v:var { variables[v.number]= input(); }
+ )*
+
+expression = ( PLUS? l:term
+ | MINUS l:term { l.number = -l.number }
+ ) ( PLUS r:term { l.number += r.number }
+ | MINUS r:term { l.number -= r.number }
+ )* { $$.number = l.number }
+
+term = l:factor ( STAR r:factor { l.number *= r.number }
+ | SLASH r:factor { l.number /= r.number }
+ )* { $$.number = l.number }
+
+factor = v:var { $$.number = variables[v.number] }
+| n:number
+| OPEN expression CLOSE
+
+var = < [a-z] > - { $$.number = yytext[0] - 'a' }
+
+number = < digit+ > - { $$.number = atoi(yytext); }
+
+digit = [0-9]
+
+string = '"' < [^\"]* > '"' - { $$.string = yytext; }
+
+relop = '<=' - { $$.binop= lessEqual; }
+| '<>' - { $$.binop= notEqual; }
+| '<' - { $$.binop= lessThan; }
+| '>=' - { $$.binop= greaterEqual; }
+| '>' - { $$.binop= greaterThan; }
+| '=' - { $$.binop= equalTo; }
+
+EQUAL = '=' - CLOSE = ')' - OPEN = '(' -
+SLASH = '/' - STAR = '*' - MINUS = '-' -
+PLUS = '+' - COMMA = ',' -
+
+- = [ \t]*
+
+CR = '\n' | '\r' | '\r\n'
+
+%%
+
+#include
+#include
+
+char *help=
+ "print | [, | ...] [,]\n"
+ "if <|<=|<>|=|>=|> then \n"
+ "input [, ...] let = \n"
+ "goto gosub \n"
+ "end return\n"
+ "list clear\n"
+ "run [\"filename\"] rem \n"
+ "dir type \"filename\"\n"
+ "save \"filename\" load \"filename\"\n"
+ "bye|quit|exit help\n"
+ ;
+
+void error(char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if (epc > 0)
+ fprintf(stderr, "\nline %d: %s", lines[epc-1].number, lines[epc-1].text);
+ else
+ fprintf(stderr, "\n");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ epc= pc= -1;
+}
+
+#ifdef USE_READLINE
+# include
+# include
+#endif
+
+int getline(char *buf, int max)
+{
+ pc= -1;
+ if (batch) exit(0);
+ if (isatty(fileno(stdin)))
+ {
+# ifdef USE_READLINE
+ char *line= readline(">");
+ if (line)
+ {
+ int len= strlen(line);
+ if (len >= max) len= max - 1;
+ strncpy(buf, line, len);
+ (buf)[len]= '\n';
+ add_history(line);
+ free(line);
+ return len + 1;
+ }
+ else
+ {
+ printf("\n");
+ return 0;
+ }
+# endif
+ putchar('>');
+ fflush(stdout);
+ }
+ return fgets(buf, max, stdin) ? strlen(buf) : 0;
+}
+
+int maxLines= 0;
+
+int findLine(int n, int create)
+{
+ int lo= 0, hi= numLines - 1;
+ while (lo <= hi)
+ {
+ int mid= (lo + hi) / 2, lno= lines[mid].number;
+ if (lno > n)
+ hi= mid - 1;
+ else if (lno < n)
+ lo= mid + 1;
+ else
+ return mid;
+ }
+ if (create)
+ {
+ if (numLines == maxLines)
+ {
+ maxLines *= 2;
+ lines= realloc(lines, sizeof(line) * maxLines);
+ }
+ if (lo < numLines)
+ memmove(lines + lo + 1, lines + lo, sizeof(line) * (numLines - lo));
+ ++numLines;
+ lines[lo].number= n;
+ lines[lo].text= 0;
+ return lo;
+ }
+ return -1;
+}
+
+void accept(int n, char *s)
+{
+ if (s[0] < 32) /* delete */
+ {
+ int lno= findLine(n, 0);
+ if (lno >= 0)
+ {
+ if (lno < numLines - 1)
+ memmove(lines + lno, lines + lno + 1, sizeof(line) * (numLines - lno - 1));
+ --numLines;
+ }
+ }
+ else /* insert */
+ {
+ int lno= findLine(n, 1);
+ if (lines[lno].text) free(lines[lno].text);
+ lines[lno].length= strlen(s);
+ lines[lno].text= strdup(s);
+ }
+}
+
+char *extend(char *name)
+{
+ static char path[1024];
+ int len= strlen(name);
+ sprintf(path, "%s%s", name, (((len > 4) && !strcasecmp(".bas", name + len - 4)) ? "" : ".bas"));
+ return path;
+}
+
+void save(char *name)
+{
+ FILE *f= fopen(name= extend(name), "w");
+ if (!f)
+ perror(name);
+ else
+ {
+ int i;
+ for (i= 0; i < numLines; ++i)
+ fprintf(f, "%d %s", lines[i].number, lines[i].text);
+ fclose(f);
+ }
+}
+
+void load(char *name)
+{
+ FILE *f= fopen(name= extend(name), "r");
+ if (!f)
+ perror(name);
+ else
+ {
+ int lineNumber;
+ char lineText[1024];
+ while ((1 == fscanf(f, " %d ", &lineNumber)) && fgets(lineText, sizeof(lineText), f))
+ accept(lineNumber, lineText);
+ fclose(f);
+ }
+}
+
+void type(char *name)
+{
+ FILE *f= fopen(name= extend(name), "r");
+ if (!f)
+ perror(name);
+ else
+ {
+ int c, d;
+ while ((c= getc(f)) >= 0)
+ putchar(d= c);
+ fclose(f);
+ if ('\n' != d && '\r' != d) putchar('\n');
+ }
+}
+
+int input(void)
+{
+ char line[32];
+ fgets(line, sizeof(line), stdin);
+ return atoi(line);
+}
+
+int main(int argc, char **argv)
+{
+ lines= malloc(sizeof(line) * (maxLines= 32));
+ numLines= 0;
+
+ if (argc > 1)
+ {
+ batch= 1;
+ while (argc-- > 1)
+ load(*++argv);
+ pc= 0;
+ }
+
+ while (!feof(stdin))
+ yyparse();
+
+ return 0;
+}
diff --git a/examples/basic.ref b/examples/basic.ref
new file mode 100644
index 0000000..90d916c
--- /dev/null
+++ b/examples/basic.ref
@@ -0,0 +1,10 @@
+ 1
+ 2 4
+ 3 6 9
+ 4 8 12 16
+ 5 10 15 20 25
+ 6 12 18 24 30 36
+ 7 14 21 28 35 42 49
+ 8 16 24 32 40 48 56 64
+ 9 18 27 36 45 54 63 72 81
+ 10 20 30 40 50 60 70 80 90 100
diff --git a/examples/bench.bas b/examples/bench.bas
new file mode 100644
index 0000000..ffdbd44
--- /dev/null
+++ b/examples/bench.bas
@@ -0,0 +1,8 @@
+100 let n=100000
+120 let m=0
+110 let s=0
+130 let m=m+1
+140 let s=s+m
+150 if m
+int vars[26];
+%}
+
+Stmt = - e:Expr EOL { printf("%d\n", e); }
+ | ( !EOL . )* EOL { printf("error\n"); }
+
+Expr = i:ID ASSIGN s:Sum { $$= vars[i]= s; }
+ | s:Sum { $$= s; }
+
+Sum = l:Product
+ ( PLUS r:Product { l += r; }
+ | MINUS r:Product { l -= r; }
+ )* { $$= l; }
+
+Product = l:Value
+ ( TIMES r:Value { l *= r; }
+ | DIVIDE r:Value { l /= r; }
+ )* { $$= l; }
+
+Value = i:NUMBER { $$= atoi(yytext); }
+ | i:ID !ASSIGN { $$= vars[i]; }
+ | OPEN i:Expr CLOSE { $$= i; }
+
+NUMBER = < [0-9]+ > - { $$= atoi(yytext); }
+ID = < [a-z] > - { $$= yytext[0] - 'a'; }
+ASSIGN = '=' -
+PLUS = '+' -
+MINUS = '-' -
+TIMES = '*' -
+DIVIDE = '/' -
+OPEN = '(' -
+CLOSE = ')' -
+
+- = [ \t]*
+EOL = '\n' | '\r\n' | '\r' | ';'
+
+%%
+
+int main()
+{
+ while (yyparse());
+
+ return 0;
+}
diff --git a/examples/calc.ref b/examples/calc.ref
new file mode 100644
index 0000000..dbd7d59
--- /dev/null
+++ b/examples/calc.ref
@@ -0,0 +1,3 @@
+6
+7
+42
diff --git a/examples/dc.c b/examples/dc.c
new file mode 100644
index 0000000..32bf1a5
--- /dev/null
+++ b/examples/dc.c
@@ -0,0 +1,17 @@
+#include
+#include
+
+int stack[1024];
+int stackp= -1;
+
+int push(int n) { return stack[++stackp]= n; }
+int pop(void) { return stack[stackp--]; }
+
+#include "dc.peg.c"
+
+int main()
+{
+ while (yyparse());
+
+ return 0;
+}
diff --git a/examples/dc.peg b/examples/dc.peg
new file mode 100644
index 0000000..75dcb67
--- /dev/null
+++ b/examples/dc.peg
@@ -0,0 +1,27 @@
+# Grammar
+
+Expr <- SPACE Sum EOL { printf("%d\n", pop()); }
+ / (!EOL .)* EOL { printf("error\n"); }
+
+Sum <- Product ( PLUS Product { int r= pop(), l= pop(); push(l + r); }
+ / MINUS Product { int r= pop(), l= pop(); push(l - r); }
+ )*
+
+Product <- Value ( TIMES Value { int r= pop(), l= pop(); push(l * r); }
+ / DIVIDE Value { int r= pop(), l= pop(); push(l / r); }
+ )*
+
+Value <- NUMBER { push(atoi(yytext)); }
+ / OPEN Sum CLOSE
+
+# Lexemes
+
+NUMBER <- < [0-9]+ > SPACE
+PLUS <- '+' SPACE
+MINUS <- '-' SPACE
+TIMES <- '*' SPACE
+DIVIDE <- '/' SPACE
+OPEN <- '(' SPACE
+CLOSE <- ')' SPACE
+SPACE <- [ \t]*
+EOL <- '\n' / '\r\n' / '\r'
diff --git a/examples/dc.ref b/examples/dc.ref
new file mode 100644
index 0000000..d81cc07
--- /dev/null
+++ b/examples/dc.ref
@@ -0,0 +1 @@
+42
diff --git a/examples/dcv.c b/examples/dcv.c
new file mode 100644
index 0000000..0c5c46d
--- /dev/null
+++ b/examples/dcv.c
@@ -0,0 +1,20 @@
+#include
+#include
+
+int stack[1024];
+int stackp= -1;
+int var= 0;
+int vars[26];
+
+int push(int n) { return stack[++stackp]= n; }
+int pop(void) { return stack[stackp--]; }
+int top(void) { return stack[stackp]; }
+
+#include "dcv.peg.c"
+
+int main()
+{
+ while (yyparse());
+
+ return 0;
+}
diff --git a/examples/dcv.peg b/examples/dcv.peg
new file mode 100644
index 0000000..2ae3a8c
--- /dev/null
+++ b/examples/dcv.peg
@@ -0,0 +1,34 @@
+# Grammar
+
+Stmt <- SPACE Expr EOL { printf("%d\n", pop()); }
+ / (!EOL .)* EOL { printf("error\n"); }
+
+Expr <- ID { var= yytext[0] } ASSIGN Sum { vars[var - 'a']= top(); }
+ / Sum
+
+Sum <- Product ( PLUS Product { int r= pop(), l= pop(); push(l + r); }
+ / MINUS Product { int r= pop(), l= pop(); push(l - r); }
+ )*
+
+Product <- Value ( TIMES Value { int r= pop(), l= pop(); push(l * r); }
+ / DIVIDE Value { int r= pop(), l= pop(); push(l / r); }
+ )*
+
+Value <- NUMBER { push(atoi(yytext)); }
+ / < ID > !ASSIGN { push(vars[yytext[0] - 'a']); }
+ / OPEN Expr CLOSE
+
+# Lexemes
+
+NUMBER <- < [0-9]+ > SPACE
+ID <- < [a-z] > SPACE
+ASSIGN <- '=' SPACE
+PLUS <- '+' SPACE
+MINUS <- '-' SPACE
+TIMES <- '*' SPACE
+DIVIDE <- '/' SPACE
+OPEN <- '(' SPACE
+CLOSE <- ')' SPACE
+
+SPACE <- [ \t]*
+EOL <- '\n' / '\r\n' / '\r' / ';'
diff --git a/examples/dcv.ref b/examples/dcv.ref
new file mode 100644
index 0000000..dbd7d59
--- /dev/null
+++ b/examples/dcv.ref
@@ -0,0 +1,3 @@
+6
+7
+42
diff --git a/examples/fibonacci.bas b/examples/fibonacci.bas
new file mode 100644
index 0000000..1872bd3
--- /dev/null
+++ b/examples/fibonacci.bas
@@ -0,0 +1,17 @@
+100 let n=32
+110 gosub 200
+120 print "fibonacci(",n,") = ", m
+130 end
+
+200 let c=n
+210 let b=1
+220 if c<2 then goto 400
+230 let c=c-1
+240 let a=1
+300 let c=c-1
+310 let d=a+b
+320 let a=b
+330 let b=d+1
+340 if c<>0 then goto 300
+400 let m=b
+410 return
diff --git a/examples/left.c b/examples/left.c
new file mode 100644
index 0000000..ac8cd0b
--- /dev/null
+++ b/examples/left.c
@@ -0,0 +1,17 @@
+#include
+
+#define YY_INPUT(buf, result, max) \
+{ \
+ int c= getchar(); \
+ result= (EOF == c) ? 0 : (*(buf)= c, 1); \
+ if (EOF != c) printf("<%c>\n", c); \
+}
+
+#include "left.peg.c"
+
+int main()
+{
+ printf(yyparse() ? "success\n" : "failure\n");
+
+ return 0;
+}
diff --git a/examples/left.peg b/examples/left.peg
new file mode 100644
index 0000000..f282227
--- /dev/null
+++ b/examples/left.peg
@@ -0,0 +1,3 @@
+# Grammar
+
+S <- (S 'a' / 'a') !'a'
diff --git a/examples/rule.c b/examples/rule.c
new file mode 100644
index 0000000..15eb0c6
--- /dev/null
+++ b/examples/rule.c
@@ -0,0 +1,11 @@
+#include
+#include
+
+#include "rule.peg.c"
+
+int main()
+{
+ while (yyparse());
+
+ return 0;
+}
diff --git a/examples/rule.peg b/examples/rule.peg
new file mode 100644
index 0000000..60a32fa
--- /dev/null
+++ b/examples/rule.peg
@@ -0,0 +1,8 @@
+start <- abcd+
+
+abcd <- 'a' { printf("A %d\n", yypos); } bc { printf("ABC %d\n", yypos); }
+ / 'b' { printf("B %d\n", yypos); } cd { printf("BCD %d\n", yypos); }
+
+bc <- 'b' { printf("B %d\n", yypos); } 'c' { printf("C %d\n", yypos); }
+
+cd <- 'c' { printf("C %d\n", yypos); } 'd' { printf("D %d\n", yypos); }
diff --git a/examples/rule.ref b/examples/rule.ref
new file mode 100644
index 0000000..4249ebe
--- /dev/null
+++ b/examples/rule.ref
@@ -0,0 +1,32 @@
+A 24
+B 24
+C 24
+ABC 24
+B 24
+C 24
+D 24
+BCD 24
+A 24
+B 24
+C 24
+ABC 24
+B 24
+C 24
+D 24
+BCD 24
+A 24
+B 24
+C 24
+ABC 24
+B 24
+C 24
+D 24
+BCD 24
+A 24
+B 24
+C 24
+ABC 24
+B 24
+C 24
+D 24
+BCD 24
diff --git a/examples/test.bas b/examples/test.bas
new file mode 100644
index 0000000..8a96e10
--- /dev/null
+++ b/examples/test.bas
@@ -0,0 +1,12 @@
+10 let i=1
+20 gosub 100
+30 let i=i+1
+40 if i<=10 then goto 20
+50 end
+
+100 let j=1
+110 print " ", i*j,
+120 let j=j+1
+130 if j<=i then goto 110
+140 print
+150 return
diff --git a/examples/test.c b/examples/test.c
new file mode 100644
index 0000000..0403422
--- /dev/null
+++ b/examples/test.c
@@ -0,0 +1,8 @@
+#include
+#include "test.peg.c"
+
+int main()
+{
+ while (yyparse());
+ return 0;
+}
diff --git a/examples/test.peg b/examples/test.peg
new file mode 100644
index 0000000..716d523
--- /dev/null
+++ b/examples/test.peg
@@ -0,0 +1,13 @@
+start <- body '.' { printf(".\n"); }
+
+body <- 'a' { printf("a1 "); } 'b' { printf("ab1 "); }
+
+ / 'a' { printf("a2 "); } 'c' { printf("ac2 "); }
+
+ / 'a' { printf("a3 "); } ( 'd' { printf("ad3 "); } / 'e' { printf("ae3 "); } )
+
+ / 'a' { printf("a4 "); } ( 'f' { printf("af4 "); } 'g' { printf("afg4 "); }
+ / 'f' { printf("af5 "); } 'h' { printf("afh5 "); } )
+
+ / 'a' { printf("a6 "); } ( 'f' &{ printf("af6 ") } 'i' &{ printf("afi6 ") }
+ / 'f' &{ printf("af7 ") } 'j' &{ printf("afj7 ") } )
diff --git a/examples/test.ref b/examples/test.ref
new file mode 100644
index 0000000..2d18109
--- /dev/null
+++ b/examples/test.ref
@@ -0,0 +1,10 @@
+a1 ab1 .
+a2 ac2 .
+a3 ad3 .
+a3 ae3 .
+a4 af4 afg4 .
+a4 af5 afh5 .
+a4 af4 afg4 .
+a4 af5 afh5 .
+af6 afi6 a6 .
+af6 af7 afj7 a6 .
diff --git a/examples/username.leg b/examples/username.leg
new file mode 100644
index 0000000..2170052
--- /dev/null
+++ b/examples/username.leg
@@ -0,0 +1,14 @@
+%{
+#include
+%}
+
+start = "username" { printf("%s", getlogin()); }
+| < . > { putchar(yytext[0]); }
+
+%%
+
+int main()
+{
+ while (yyparse());
+ return 0;
+}
diff --git a/examples/wc.leg b/examples/wc.leg
new file mode 100644
index 0000000..59199c8
--- /dev/null
+++ b/examples/wc.leg
@@ -0,0 +1,22 @@
+%{
+#include
+int lines= 0, words= 0, chars= 0;
+%}
+
+start = (line | word | char)
+
+line = < (( '\n' '\r'* ) | ( '\r' '\n'* )) > { lines++; chars += yyleng; }
+word = < [a-zA-Z]+ > { words++; chars += yyleng; printf("<%s>\n", yytext); }
+char = . { chars++; }
+
+%%
+
+int main()
+{
+ while (yyparse())
+ ;
+ printf("%d lines\n", lines);
+ printf("%d chars\n", chars);
+ printf("%d words\n", words);
+ return 0;
+}
diff --git a/examples/wc.ref b/examples/wc.ref
new file mode 100644
index 0000000..083a46e
--- /dev/null
+++ b/examples/wc.ref
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+22 lines
+425 chars
+52 words
diff --git a/leg.c b/leg.c
new file mode 100644
index 0000000..36372ba
--- /dev/null
+++ b/leg.c
@@ -0,0 +1,1058 @@
+/* A recursive-descent parser generated by peg 0.1.0 */
+
+#include
+#include
+#include
+#define YYRULECOUNT 35
+
+# include "tree.h"
+# include "version.h"
+
+# include
+# include
+# include
+# include
+# include
+# include
+
+ typedef struct Header Header;
+
+ struct Header {
+ char *text;
+ Header *next;
+ };
+
+ FILE *input= 0;
+
+ int verboseFlag= 0;
+
+ static int lineNumber= 0;
+ static char *fileName= 0;
+ static char *trailer= 0;
+ static Header *headers= 0;
+
+ void makeHeader(char *text);
+ void makeTrailer(char *text);
+
+ void yyerror(char *message);
+
+# define YY_INPUT(buf, result, max) \
+ { \
+ int c= getc(input); \
+ if ('\n' == c || '\r' == c) ++lineNumber; \
+ result= (EOF == c) ? 0 : (*(buf)= c, 1); \
+ }
+
+# define YY_LOCAL(T) static T
+# define YY_RULE(T) static T
+
+#ifndef YY_VARIABLE
+#define YY_VARIABLE(T) static T
+#endif
+#ifndef YY_LOCAL
+#define YY_LOCAL(T) static T
+#endif
+#ifndef YY_ACTION
+#define YY_ACTION(T) static T
+#endif
+#ifndef YY_RULE
+#define YY_RULE(T) static T
+#endif
+#ifndef YY_PARSE
+#define YY_PARSE(T) T
+#endif
+#ifndef YYPARSE
+#define YYPARSE yyparse
+#endif
+#ifndef YYPARSEFROM
+#define YYPARSEFROM yyparsefrom
+#endif
+#ifndef YY_INPUT
+#define YY_INPUT(buf, result, max_size) \
+ { \
+ int yyc= getchar(); \
+ result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \
+ yyprintf((stderr, "<%c>", yyc)); \
+ }
+#endif
+#ifndef YY_BEGIN
+#define YY_BEGIN ( yybegin= yypos, 1)
+#endif
+#ifndef YY_END
+#define YY_END ( yyend= yypos, 1)
+#endif
+#ifdef YY_DEBUG
+# define yyprintf(args) fprintf args
+#else
+# define yyprintf(args)
+#endif
+#ifndef YYSTYPE
+#define YYSTYPE int
+#endif
+
+#ifndef YY_PART
+
+typedef void (*yyaction)(char *yytext, int yyleng);
+typedef struct _yythunk { int begin, end; yyaction action; struct _yythunk *next; } yythunk;
+
+YY_VARIABLE(char * ) yybuf= 0;
+YY_VARIABLE(int ) yybuflen= 0;
+YY_VARIABLE(int ) yypos= 0;
+YY_VARIABLE(int ) yylimit= 0;
+YY_VARIABLE(char * ) yytext= 0;
+YY_VARIABLE(int ) yytextlen= 0;
+YY_VARIABLE(int ) yybegin= 0;
+YY_VARIABLE(int ) yyend= 0;
+YY_VARIABLE(int ) yytextmax= 0;
+YY_VARIABLE(yythunk *) yythunks= 0;
+YY_VARIABLE(int ) yythunkslen= 0;
+YY_VARIABLE(int ) yythunkpos= 0;
+YY_VARIABLE(YYSTYPE ) yy;
+YY_VARIABLE(YYSTYPE *) yyval= 0;
+YY_VARIABLE(YYSTYPE *) yyvals= 0;
+YY_VARIABLE(int ) yyvalslen= 0;
+
+YY_LOCAL(int) yyrefill(void)
+{
+ int yyn;
+ if (yybuflen - yypos < 512)
+ {
+ yybuflen *= 2;
+ yybuf= realloc(yybuf, yybuflen);
+ }
+ YY_INPUT((yybuf + yypos), yyn, (yybuflen - yypos));
+ if (!yyn) return 0;
+ yylimit += yyn;
+ return 1;
+}
+
+YY_LOCAL(int) yymatchDot(void)
+{
+ if (yypos >= yylimit && !yyrefill()) return 0;
+ ++yypos;
+ return 1;
+}
+
+YY_LOCAL(int) yymatchChar(int c)
+{
+ if (yypos >= yylimit && !yyrefill()) return 0;
+ if (yybuf[yypos] == c)
+ {
+ ++yypos;
+ yyprintf((stderr, " ok yymatchChar(%c) @ %s\n", c, yybuf+yypos));
+ return 1;
+ }
+ yyprintf((stderr, " fail yymatchChar(%c) @ %s\n", c, yybuf+yypos));
+ return 0;
+}
+
+YY_LOCAL(int) yymatchString(char *s)
+{
+ int yysav= yypos;
+ while (*s)
+ {
+ if (yypos >= yylimit && !yyrefill()) return 0;
+ if (yybuf[yypos] != *s)
+ {
+ yypos= yysav;
+ return 0;
+ }
+ ++s;
+ ++yypos;
+ }
+ return 1;
+}
+
+YY_LOCAL(int) yymatchClass(unsigned char *bits)
+{
+ int c;
+ if (yypos >= yylimit && !yyrefill()) return 0;
+ c= yybuf[yypos];
+ if (bits[c >> 3] & (1 << (c & 7)))
+ {
+ ++yypos;
+ yyprintf((stderr, " ok yymatchClass @ %s\n", yybuf+yypos));
+ return 1;
+ }
+ yyprintf((stderr, " fail yymatchClass @ %s\n", yybuf+yypos));
+ return 0;
+}
+
+YY_LOCAL(void) yyDo(yyaction action, int begin, int end)
+{
+ if (yythunkpos >= yythunkslen)
+ {
+ yythunkslen *= 2;
+ yythunks= realloc(yythunks, sizeof(yythunk) * yythunkslen);
+ }
+ yythunks[yythunkpos].begin= begin;
+ yythunks[yythunkpos].end= end;
+ yythunks[yythunkpos].action= action;
+ ++yythunkpos;
+}
+
+YY_LOCAL(int) yyText(int begin, int end)
+{
+ int yyleng= end - begin;
+ if (yyleng <= 0)
+ yyleng= 0;
+ else
+ {
+ if (yytextlen < (yyleng - 1))
+ {
+ yytextlen *= 2;
+ yytext= realloc(yytext, yytextlen);
+ }
+ memcpy(yytext, yybuf + begin, yyleng);
+ }
+ yytext[yyleng]= '\0';
+ return yyleng;
+}
+
+YY_LOCAL(void) yyDone(void)
+{
+ int pos;
+ for (pos= 0; pos < yythunkpos; ++pos)
+ {
+ yythunk *thunk= &yythunks[pos];
+ int yyleng= thunk->end ? yyText(thunk->begin, thunk->end) : thunk->begin;
+ yyprintf((stderr, "DO [%d] %p %s\n", pos, thunk->action, yytext));
+ thunk->action(yytext, yyleng);
+ }
+ yythunkpos= 0;
+}
+
+YY_LOCAL(void) yyCommit()
+{
+ if ((yylimit -= yypos))
+ {
+ memmove(yybuf, yybuf + yypos, yylimit);
+ }
+ yybegin -= yypos;
+ yyend -= yypos;
+ yypos= yythunkpos= 0;
+}
+
+YY_LOCAL(int) yyAccept(int tp0)
+{
+ if (tp0)
+ {
+ fprintf(stderr, "accept denied at %d\n", tp0);
+ return 0;
+ }
+ else
+ {
+ yyDone();
+ yyCommit();
+ }
+ return 1;
+}
+
+YY_LOCAL(void) yyPush(char *text, int count) { yyval += count; }
+YY_LOCAL(void) yyPop(char *text, int count) { yyval -= count; }
+YY_LOCAL(void) yySet(char *text, int count) { yyval[count]= yy; }
+
+#endif /* YY_PART */
+
+#define YYACCEPT yyAccept(yythunkpos0)
+
+YY_RULE(int) yy_end_of_line(); /* 35 */
+YY_RULE(int) yy_comment(); /* 34 */
+YY_RULE(int) yy_space(); /* 33 */
+YY_RULE(int) yy_range(); /* 32 */
+YY_RULE(int) yy_char(); /* 31 */
+YY_RULE(int) yy_END(); /* 30 */
+YY_RULE(int) yy_BEGIN(); /* 29 */
+YY_RULE(int) yy_DOT(); /* 28 */
+YY_RULE(int) yy_class(); /* 27 */
+YY_RULE(int) yy_literal(); /* 26 */
+YY_RULE(int) yy_CLOSE(); /* 25 */
+YY_RULE(int) yy_OPEN(); /* 24 */
+YY_RULE(int) yy_COLON(); /* 23 */
+YY_RULE(int) yy_PLUS(); /* 22 */
+YY_RULE(int) yy_STAR(); /* 21 */
+YY_RULE(int) yy_QUESTION(); /* 20 */
+YY_RULE(int) yy_primary(); /* 19 */
+YY_RULE(int) yy_NOT(); /* 18 */
+YY_RULE(int) yy_suffix(); /* 17 */
+YY_RULE(int) yy_action(); /* 16 */
+YY_RULE(int) yy_AND(); /* 15 */
+YY_RULE(int) yy_prefix(); /* 14 */
+YY_RULE(int) yy_BAR(); /* 13 */
+YY_RULE(int) yy_sequence(); /* 12 */
+YY_RULE(int) yy_SEMICOLON(); /* 11 */
+YY_RULE(int) yy_expression(); /* 10 */
+YY_RULE(int) yy_EQUAL(); /* 9 */
+YY_RULE(int) yy_identifier(); /* 8 */
+YY_RULE(int) yy_RPERCENT(); /* 7 */
+YY_RULE(int) yy_end_of_file(); /* 6 */
+YY_RULE(int) yy_trailer(); /* 5 */
+YY_RULE(int) yy_definition(); /* 4 */
+YY_RULE(int) yy_declaration(); /* 3 */
+YY_RULE(int) yy__(); /* 2 */
+YY_RULE(int) yy_grammar(); /* 1 */
+
+YY_ACTION(void) yy_9_primary(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_9_primary\n"));
+ push(makePredicate("YY_END")); ;
+}
+YY_ACTION(void) yy_8_primary(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_8_primary\n"));
+ push(makePredicate("YY_BEGIN")); ;
+}
+YY_ACTION(void) yy_7_primary(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_7_primary\n"));
+ push(makeAction(yytext)); ;
+}
+YY_ACTION(void) yy_6_primary(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_6_primary\n"));
+ push(makeDot()); ;
+}
+YY_ACTION(void) yy_5_primary(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_5_primary\n"));
+ push(makeClass(yytext)); ;
+}
+YY_ACTION(void) yy_4_primary(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_4_primary\n"));
+ push(makeString(yytext)); ;
+}
+YY_ACTION(void) yy_3_primary(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_3_primary\n"));
+ push(makeName(findRule(yytext))); ;
+}
+YY_ACTION(void) yy_2_primary(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_2_primary\n"));
+ Node *name= makeName(findRule(yytext)); name->name.variable= pop(); push(name); ;
+}
+YY_ACTION(void) yy_1_primary(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_1_primary\n"));
+ push(makeVariable(yytext)); ;
+}
+YY_ACTION(void) yy_3_suffix(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_3_suffix\n"));
+ push(makePlus (pop())); ;
+}
+YY_ACTION(void) yy_2_suffix(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_2_suffix\n"));
+ push(makeStar (pop())); ;
+}
+YY_ACTION(void) yy_1_suffix(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_1_suffix\n"));
+ push(makeQuery(pop())); ;
+}
+YY_ACTION(void) yy_3_prefix(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_3_prefix\n"));
+ push(makePeekNot(pop())); ;
+}
+YY_ACTION(void) yy_2_prefix(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_2_prefix\n"));
+ push(makePeekFor(pop())); ;
+}
+YY_ACTION(void) yy_1_prefix(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_1_prefix\n"));
+ push(makePredicate(yytext)); ;
+}
+YY_ACTION(void) yy_1_sequence(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_1_sequence\n"));
+ Node *f= pop(); push(Sequence_append(pop(), f)); ;
+}
+YY_ACTION(void) yy_1_expression(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_1_expression\n"));
+ Node *f= pop(); push(Alternate_append(pop(), f)); ;
+}
+YY_ACTION(void) yy_2_definition(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_2_definition\n"));
+ Node *e= pop(); Rule_setExpression(pop(), e); ;
+}
+YY_ACTION(void) yy_1_definition(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_1_definition\n"));
+ if (push(beginRule(findRule(yytext)))->rule.expression)
+ fprintf(stderr, "rule '%s' redefined\n", yytext); ;
+}
+YY_ACTION(void) yy_1_trailer(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_1_trailer\n"));
+ makeTrailer(yytext); ;
+}
+YY_ACTION(void) yy_1_declaration(char *yytext, int yyleng)
+{
+ yyprintf((stderr, "do yy_1_declaration\n"));
+ makeHeader(yytext); ;
+}
+
+YY_RULE(int) yy_end_of_line()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "end_of_line"));
+ { int yypos2= yypos, yythunkpos2= yythunkpos; if (!yymatchString("\r\n")) goto l3; goto l2;
+ l3:; yypos= yypos2; yythunkpos= yythunkpos2; if (!yymatchChar('\n')) goto l4; goto l2;
+ l4:; yypos= yypos2; yythunkpos= yythunkpos2; if (!yymatchChar('\r')) goto l1;
+ }
+ l2:;
+ yyprintf((stderr, " ok %s @ %s\n", "end_of_line", yybuf+yypos));
+ return 1;
+ l1:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "end_of_line", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_comment()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "comment")); if (!yymatchChar('#')) goto l5;
+ l6:;
+ { int yypos7= yypos, yythunkpos7= yythunkpos;
+ { int yypos8= yypos, yythunkpos8= yythunkpos; if (!yy_end_of_line()) goto l8; goto l7;
+ l8:; yypos= yypos8; yythunkpos= yythunkpos8;
+ } if (!yymatchDot()) goto l7; goto l6;
+ l7:; yypos= yypos7; yythunkpos= yythunkpos7;
+ } if (!yy_end_of_line()) goto l5;
+ yyprintf((stderr, " ok %s @ %s\n", "comment", yybuf+yypos));
+ return 1;
+ l5:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "comment", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_space()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "space"));
+ { int yypos10= yypos, yythunkpos10= yythunkpos; if (!yymatchChar(' ')) goto l11; goto l10;
+ l11:; yypos= yypos10; yythunkpos= yythunkpos10; if (!yymatchChar('\t')) goto l12; goto l10;
+ l12:; yypos= yypos10; yythunkpos= yythunkpos10; if (!yy_end_of_line()) goto l9;
+ }
+ l10:;
+ yyprintf((stderr, " ok %s @ %s\n", "space", yybuf+yypos));
+ return 1;
+ l9:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "space", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_range()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "range"));
+ { int yypos14= yypos, yythunkpos14= yythunkpos; if (!yy_char()) goto l15; if (!yymatchChar('-')) goto l15; if (!yy_char()) goto l15; goto l14;
+ l15:; yypos= yypos14; yythunkpos= yythunkpos14; if (!yy_char()) goto l13;
+ }
+ l14:;
+ yyprintf((stderr, " ok %s @ %s\n", "range", yybuf+yypos));
+ return 1;
+ l13:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "range", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_char()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "char"));
+ { int yypos17= yypos, yythunkpos17= yythunkpos; if (!yymatchChar('\\')) goto l18; if (!yymatchClass((unsigned char *)"\000\000\000\000\204\000\000\000\000\000\000\070\146\100\124\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l18; goto l17;
+ l18:; yypos= yypos17; yythunkpos= yythunkpos17; if (!yymatchChar('\\')) goto l19; if (!yymatchClass((unsigned char *)"\000\000\000\000\000\000\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l19; if (!yymatchClass((unsigned char *)"\000\000\000\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l19; if (!yymatchClass((unsigned char *)"\000\000\000\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l19; goto l17;
+ l19:; yypos= yypos17; yythunkpos= yythunkpos17; if (!yymatchChar('\\')) goto l20; if (!yymatchClass((unsigned char *)"\000\000\000\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l20;
+ { int yypos21= yypos, yythunkpos21= yythunkpos; if (!yymatchClass((unsigned char *)"\000\000\000\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l21; goto l22;
+ l21:; yypos= yypos21; yythunkpos= yythunkpos21;
+ }
+ l22:; goto l17;
+ l20:; yypos= yypos17; yythunkpos= yythunkpos17;
+ { int yypos23= yypos, yythunkpos23= yythunkpos; if (!yymatchChar('\\')) goto l23; goto l16;
+ l23:; yypos= yypos23; yythunkpos= yythunkpos23;
+ } if (!yymatchDot()) goto l16;
+ }
+ l17:;
+ yyprintf((stderr, " ok %s @ %s\n", "char", yybuf+yypos));
+ return 1;
+ l16:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "char", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_END()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "END")); if (!yymatchChar('>')) goto l24; if (!yy__()) goto l24;
+ yyprintf((stderr, " ok %s @ %s\n", "END", yybuf+yypos));
+ return 1;
+ l24:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "END", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_BEGIN()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "BEGIN")); if (!yymatchChar('<')) goto l25; if (!yy__()) goto l25;
+ yyprintf((stderr, " ok %s @ %s\n", "BEGIN", yybuf+yypos));
+ return 1;
+ l25:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "BEGIN", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_DOT()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "DOT")); if (!yymatchChar('.')) goto l26; if (!yy__()) goto l26;
+ yyprintf((stderr, " ok %s @ %s\n", "DOT", yybuf+yypos));
+ return 1;
+ l26:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "DOT", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_class()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "class")); if (!yymatchChar('[')) goto l27; yyText(yybegin, yyend); if (!(YY_BEGIN)) goto l27;
+ l28:;
+ { int yypos29= yypos, yythunkpos29= yythunkpos;
+ { int yypos30= yypos, yythunkpos30= yythunkpos; if (!yymatchChar(']')) goto l30; goto l29;
+ l30:; yypos= yypos30; yythunkpos= yythunkpos30;
+ } if (!yy_range()) goto l29; goto l28;
+ l29:; yypos= yypos29; yythunkpos= yythunkpos29;
+ } yyText(yybegin, yyend); if (!(YY_END)) goto l27; if (!yymatchChar(']')) goto l27; if (!yy__()) goto l27;
+ yyprintf((stderr, " ok %s @ %s\n", "class", yybuf+yypos));
+ return 1;
+ l27:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "class", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_literal()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "literal"));
+ { int yypos32= yypos, yythunkpos32= yythunkpos; if (!yymatchClass((unsigned char *)"\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l33; yyText(yybegin, yyend); if (!(YY_BEGIN)) goto l33;
+ l34:;
+ { int yypos35= yypos, yythunkpos35= yythunkpos;
+ { int yypos36= yypos, yythunkpos36= yythunkpos; if (!yymatchClass((unsigned char *)"\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l36; goto l35;
+ l36:; yypos= yypos36; yythunkpos= yythunkpos36;
+ } if (!yy_char()) goto l35; goto l34;
+ l35:; yypos= yypos35; yythunkpos= yythunkpos35;
+ } yyText(yybegin, yyend); if (!(YY_END)) goto l33; if (!yymatchClass((unsigned char *)"\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l33; if (!yy__()) goto l33; goto l32;
+ l33:; yypos= yypos32; yythunkpos= yythunkpos32; if (!yymatchClass((unsigned char *)"\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l31; yyText(yybegin, yyend); if (!(YY_BEGIN)) goto l31;
+ l37:;
+ { int yypos38= yypos, yythunkpos38= yythunkpos;
+ { int yypos39= yypos, yythunkpos39= yythunkpos; if (!yymatchClass((unsigned char *)"\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l39; goto l38;
+ l39:; yypos= yypos39; yythunkpos= yythunkpos39;
+ } if (!yy_char()) goto l38; goto l37;
+ l38:; yypos= yypos38; yythunkpos= yythunkpos38;
+ } yyText(yybegin, yyend); if (!(YY_END)) goto l31; if (!yymatchClass((unsigned char *)"\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l31; if (!yy__()) goto l31;
+ }
+ l32:;
+ yyprintf((stderr, " ok %s @ %s\n", "literal", yybuf+yypos));
+ return 1;
+ l31:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "literal", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_CLOSE()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "CLOSE")); if (!yymatchChar(')')) goto l40; if (!yy__()) goto l40;
+ yyprintf((stderr, " ok %s @ %s\n", "CLOSE", yybuf+yypos));
+ return 1;
+ l40:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "CLOSE", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_OPEN()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "OPEN")); if (!yymatchChar('(')) goto l41; if (!yy__()) goto l41;
+ yyprintf((stderr, " ok %s @ %s\n", "OPEN", yybuf+yypos));
+ return 1;
+ l41:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "OPEN", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_COLON()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "COLON")); if (!yymatchChar(':')) goto l42; if (!yy__()) goto l42;
+ yyprintf((stderr, " ok %s @ %s\n", "COLON", yybuf+yypos));
+ return 1;
+ l42:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "COLON", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_PLUS()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "PLUS")); if (!yymatchChar('+')) goto l43; if (!yy__()) goto l43;
+ yyprintf((stderr, " ok %s @ %s\n", "PLUS", yybuf+yypos));
+ return 1;
+ l43:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "PLUS", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_STAR()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "STAR")); if (!yymatchChar('*')) goto l44; if (!yy__()) goto l44;
+ yyprintf((stderr, " ok %s @ %s\n", "STAR", yybuf+yypos));
+ return 1;
+ l44:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "STAR", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_QUESTION()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "QUESTION")); if (!yymatchChar('?')) goto l45; if (!yy__()) goto l45;
+ yyprintf((stderr, " ok %s @ %s\n", "QUESTION", yybuf+yypos));
+ return 1;
+ l45:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "QUESTION", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_primary()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "primary"));
+ { int yypos47= yypos, yythunkpos47= yythunkpos; if (!yy_identifier()) goto l48; yyDo(yy_1_primary, yybegin, yyend); if (!yy_COLON()) goto l48; if (!yy_identifier()) goto l48;
+ { int yypos49= yypos, yythunkpos49= yythunkpos; if (!yy_EQUAL()) goto l49; goto l48;
+ l49:; yypos= yypos49; yythunkpos= yythunkpos49;
+ } yyDo(yy_2_primary, yybegin, yyend); goto l47;
+ l48:; yypos= yypos47; yythunkpos= yythunkpos47; if (!yy_identifier()) goto l50;
+ { int yypos51= yypos, yythunkpos51= yythunkpos; if (!yy_EQUAL()) goto l51; goto l50;
+ l51:; yypos= yypos51; yythunkpos= yythunkpos51;
+ } yyDo(yy_3_primary, yybegin, yyend); goto l47;
+ l50:; yypos= yypos47; yythunkpos= yythunkpos47; if (!yy_OPEN()) goto l52; if (!yy_expression()) goto l52; if (!yy_CLOSE()) goto l52; goto l47;
+ l52:; yypos= yypos47; yythunkpos= yythunkpos47; if (!yy_literal()) goto l53; yyDo(yy_4_primary, yybegin, yyend); goto l47;
+ l53:; yypos= yypos47; yythunkpos= yythunkpos47; if (!yy_class()) goto l54; yyDo(yy_5_primary, yybegin, yyend); goto l47;
+ l54:; yypos= yypos47; yythunkpos= yythunkpos47; if (!yy_DOT()) goto l55; yyDo(yy_6_primary, yybegin, yyend); goto l47;
+ l55:; yypos= yypos47; yythunkpos= yythunkpos47; if (!yy_action()) goto l56; yyDo(yy_7_primary, yybegin, yyend); goto l47;
+ l56:; yypos= yypos47; yythunkpos= yythunkpos47; if (!yy_BEGIN()) goto l57; yyDo(yy_8_primary, yybegin, yyend); goto l47;
+ l57:; yypos= yypos47; yythunkpos= yythunkpos47; if (!yy_END()) goto l46; yyDo(yy_9_primary, yybegin, yyend);
+ }
+ l47:;
+ yyprintf((stderr, " ok %s @ %s\n", "primary", yybuf+yypos));
+ return 1;
+ l46:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "primary", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_NOT()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "NOT")); if (!yymatchChar('!')) goto l58; if (!yy__()) goto l58;
+ yyprintf((stderr, " ok %s @ %s\n", "NOT", yybuf+yypos));
+ return 1;
+ l58:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "NOT", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_suffix()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "suffix")); if (!yy_primary()) goto l59;
+ { int yypos60= yypos, yythunkpos60= yythunkpos;
+ { int yypos62= yypos, yythunkpos62= yythunkpos; if (!yy_QUESTION()) goto l63; yyDo(yy_1_suffix, yybegin, yyend); goto l62;
+ l63:; yypos= yypos62; yythunkpos= yythunkpos62; if (!yy_STAR()) goto l64; yyDo(yy_2_suffix, yybegin, yyend); goto l62;
+ l64:; yypos= yypos62; yythunkpos= yythunkpos62; if (!yy_PLUS()) goto l60; yyDo(yy_3_suffix, yybegin, yyend);
+ }
+ l62:; goto l61;
+ l60:; yypos= yypos60; yythunkpos= yythunkpos60;
+ }
+ l61:;
+ yyprintf((stderr, " ok %s @ %s\n", "suffix", yybuf+yypos));
+ return 1;
+ l59:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "suffix", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_action()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "action")); if (!yymatchChar('{')) goto l65; yyText(yybegin, yyend); if (!(YY_BEGIN)) goto l65;
+ l66:;
+ { int yypos67= yypos, yythunkpos67= yythunkpos; if (!yymatchClass((unsigned char *)"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\337\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377")) goto l67; goto l66;
+ l67:; yypos= yypos67; yythunkpos= yythunkpos67;
+ } yyText(yybegin, yyend); if (!(YY_END)) goto l65; if (!yymatchChar('}')) goto l65; if (!yy__()) goto l65;
+ yyprintf((stderr, " ok %s @ %s\n", "action", yybuf+yypos));
+ return 1;
+ l65:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "action", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_AND()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "AND")); if (!yymatchChar('&')) goto l68; if (!yy__()) goto l68;
+ yyprintf((stderr, " ok %s @ %s\n", "AND", yybuf+yypos));
+ return 1;
+ l68:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "AND", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_prefix()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "prefix"));
+ { int yypos70= yypos, yythunkpos70= yythunkpos; if (!yy_AND()) goto l71; if (!yy_action()) goto l71; yyDo(yy_1_prefix, yybegin, yyend); goto l70;
+ l71:; yypos= yypos70; yythunkpos= yythunkpos70; if (!yy_AND()) goto l72; if (!yy_suffix()) goto l72; yyDo(yy_2_prefix, yybegin, yyend); goto l70;
+ l72:; yypos= yypos70; yythunkpos= yythunkpos70; if (!yy_NOT()) goto l73; if (!yy_suffix()) goto l73; yyDo(yy_3_prefix, yybegin, yyend); goto l70;
+ l73:; yypos= yypos70; yythunkpos= yythunkpos70; if (!yy_suffix()) goto l69;
+ }
+ l70:;
+ yyprintf((stderr, " ok %s @ %s\n", "prefix", yybuf+yypos));
+ return 1;
+ l69:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "prefix", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_BAR()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "BAR")); if (!yymatchChar('|')) goto l74; if (!yy__()) goto l74;
+ yyprintf((stderr, " ok %s @ %s\n", "BAR", yybuf+yypos));
+ return 1;
+ l74:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "BAR", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_sequence()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "sequence")); if (!yy_prefix()) goto l75;
+ l76:;
+ { int yypos77= yypos, yythunkpos77= yythunkpos; if (!yy_prefix()) goto l77; yyDo(yy_1_sequence, yybegin, yyend); goto l76;
+ l77:; yypos= yypos77; yythunkpos= yythunkpos77;
+ }
+ yyprintf((stderr, " ok %s @ %s\n", "sequence", yybuf+yypos));
+ return 1;
+ l75:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "sequence", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_SEMICOLON()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "SEMICOLON")); if (!yymatchChar(';')) goto l78; if (!yy__()) goto l78;
+ yyprintf((stderr, " ok %s @ %s\n", "SEMICOLON", yybuf+yypos));
+ return 1;
+ l78:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "SEMICOLON", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_expression()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "expression")); if (!yy_sequence()) goto l79;
+ l80:;
+ { int yypos81= yypos, yythunkpos81= yythunkpos; if (!yy_BAR()) goto l81; if (!yy_sequence()) goto l81; yyDo(yy_1_expression, yybegin, yyend); goto l80;
+ l81:; yypos= yypos81; yythunkpos= yythunkpos81;
+ }
+ yyprintf((stderr, " ok %s @ %s\n", "expression", yybuf+yypos));
+ return 1;
+ l79:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "expression", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_EQUAL()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "EQUAL")); if (!yymatchChar('=')) goto l82; if (!yy__()) goto l82;
+ yyprintf((stderr, " ok %s @ %s\n", "EQUAL", yybuf+yypos));
+ return 1;
+ l82:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "EQUAL", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_identifier()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "identifier")); yyText(yybegin, yyend); if (!(YY_BEGIN)) goto l83; if (!yymatchClass((unsigned char *)"\000\000\000\000\000\040\000\000\376\377\377\207\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l83;
+ l84:;
+ { int yypos85= yypos, yythunkpos85= yythunkpos; if (!yymatchClass((unsigned char *)"\000\000\000\000\000\040\377\003\376\377\377\207\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l85; goto l84;
+ l85:; yypos= yypos85; yythunkpos= yythunkpos85;
+ } yyText(yybegin, yyend); if (!(YY_END)) goto l83; if (!yy__()) goto l83;
+ yyprintf((stderr, " ok %s @ %s\n", "identifier", yybuf+yypos));
+ return 1;
+ l83:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "identifier", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_RPERCENT()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "RPERCENT")); if (!yymatchString("%}")) goto l86; if (!yy__()) goto l86;
+ yyprintf((stderr, " ok %s @ %s\n", "RPERCENT", yybuf+yypos));
+ return 1;
+ l86:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "RPERCENT", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_end_of_file()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "end_of_file"));
+ { int yypos88= yypos, yythunkpos88= yythunkpos; if (!yymatchDot()) goto l88; goto l87;
+ l88:; yypos= yypos88; yythunkpos= yythunkpos88;
+ }
+ yyprintf((stderr, " ok %s @ %s\n", "end_of_file", yybuf+yypos));
+ return 1;
+ l87:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "end_of_file", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_trailer()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "trailer")); if (!yymatchString("%%")) goto l89; yyText(yybegin, yyend); if (!(YY_BEGIN)) goto l89;
+ l90:;
+ { int yypos91= yypos, yythunkpos91= yythunkpos; if (!yymatchDot()) goto l91; goto l90;
+ l91:; yypos= yypos91; yythunkpos= yythunkpos91;
+ } yyText(yybegin, yyend); if (!(YY_END)) goto l89; yyDo(yy_1_trailer, yybegin, yyend);
+ yyprintf((stderr, " ok %s @ %s\n", "trailer", yybuf+yypos));
+ return 1;
+ l89:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "trailer", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_definition()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "definition")); if (!yy_identifier()) goto l92; yyDo(yy_1_definition, yybegin, yyend); if (!yy_EQUAL()) goto l92; if (!yy_expression()) goto l92; yyDo(yy_2_definition, yybegin, yyend);
+ { int yypos93= yypos, yythunkpos93= yythunkpos; if (!yy_SEMICOLON()) goto l93; goto l94;
+ l93:; yypos= yypos93; yythunkpos= yythunkpos93;
+ }
+ l94:;
+ yyprintf((stderr, " ok %s @ %s\n", "definition", yybuf+yypos));
+ return 1;
+ l92:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "definition", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy_declaration()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "declaration")); if (!yymatchString("%{")) goto l95; yyText(yybegin, yyend); if (!(YY_BEGIN)) goto l95;
+ l96:;
+ { int yypos97= yypos, yythunkpos97= yythunkpos;
+ { int yypos98= yypos, yythunkpos98= yythunkpos; if (!yymatchString("%}")) goto l98; goto l97;
+ l98:; yypos= yypos98; yythunkpos= yythunkpos98;
+ } if (!yymatchDot()) goto l97; goto l96;
+ l97:; yypos= yypos97; yythunkpos= yythunkpos97;
+ } yyText(yybegin, yyend); if (!(YY_END)) goto l95; if (!yy_RPERCENT()) goto l95; yyDo(yy_1_declaration, yybegin, yyend);
+ yyprintf((stderr, " ok %s @ %s\n", "declaration", yybuf+yypos));
+ return 1;
+ l95:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "declaration", yybuf+yypos));
+ return 0;
+}
+YY_RULE(int) yy__()
+{
+ yyprintf((stderr, "%s\n", "_"));
+ l100:;
+ { int yypos101= yypos, yythunkpos101= yythunkpos;
+ { int yypos102= yypos, yythunkpos102= yythunkpos; if (!yy_space()) goto l103; goto l102;
+ l103:; yypos= yypos102; yythunkpos= yythunkpos102; if (!yy_comment()) goto l101;
+ }
+ l102:; goto l100;
+ l101:; yypos= yypos101; yythunkpos= yythunkpos101;
+ }
+ yyprintf((stderr, " ok %s @ %s\n", "_", yybuf+yypos));
+ return 1;
+}
+YY_RULE(int) yy_grammar()
+{ int yypos0= yypos, yythunkpos0= yythunkpos;
+ yyprintf((stderr, "%s\n", "grammar")); if (!yy__()) goto l104;
+ { int yypos107= yypos, yythunkpos107= yythunkpos; if (!yy_declaration()) goto l108; goto l107;
+ l108:; yypos= yypos107; yythunkpos= yythunkpos107; if (!yy_definition()) goto l104;
+ }
+ l107:;
+ l105:;
+ { int yypos106= yypos, yythunkpos106= yythunkpos;
+ { int yypos109= yypos, yythunkpos109= yythunkpos; if (!yy_declaration()) goto l110; goto l109;
+ l110:; yypos= yypos109; yythunkpos= yythunkpos109; if (!yy_definition()) goto l106;
+ }
+ l109:; goto l105;
+ l106:; yypos= yypos106; yythunkpos= yythunkpos106;
+ }
+ { int yypos111= yypos, yythunkpos111= yythunkpos; if (!yy_trailer()) goto l111; goto l112;
+ l111:; yypos= yypos111; yythunkpos= yythunkpos111;
+ }
+ l112:; if (!yy_end_of_file()) goto l104;
+ yyprintf((stderr, " ok %s @ %s\n", "grammar", yybuf+yypos));
+ return 1;
+ l104:; yypos= yypos0; yythunkpos= yythunkpos0;
+ yyprintf((stderr, " fail %s @ %s\n", "grammar", yybuf+yypos));
+ return 0;
+}
+
+#ifndef YY_PART
+
+typedef int (*yyrule)();
+
+YY_PARSE(int) YYPARSEFROM(yyrule yystart)
+{
+ int yyok;
+ if (!yybuflen)
+ {
+ yybuflen= 1024;
+ yybuf= malloc(yybuflen);
+ yytextlen= 1024;
+ yytext= malloc(yytextlen);
+ yythunkslen= 32;
+ yythunks= malloc(sizeof(yythunk) * yythunkslen);
+ yyvalslen= 32;
+ yyvals= malloc(sizeof(YYSTYPE) * yyvalslen);
+ yybegin= yyend= yypos= yylimit= yythunkpos= 0;
+ }
+ yybegin= yyend= yypos;
+ yythunkpos= 0;
+ yyval= yyvals;
+ yyok= yystart();
+ if (yyok) yyDone();
+ yyCommit();
+ return yyok;
+ (void)yyrefill;
+ (void)yymatchDot;
+ (void)yymatchChar;
+ (void)yymatchString;
+ (void)yymatchClass;
+ (void)yyDo;
+ (void)yyText;
+ (void)yyDone;
+ (void)yyCommit;
+ (void)yyAccept;
+ (void)yyPush;
+ (void)yyPop;
+ (void)yySet;
+ (void)yytextmax;
+}
+
+YY_PARSE(int) YYPARSE(void)
+{
+ return YYPARSEFROM(yy_grammar);
+}
+
+#endif
+
+
+void yyerror(char *message)
+{
+ fprintf(stderr, "%s:%d: %s", fileName, lineNumber, message);
+ if (yytext[0]) fprintf(stderr, " near token '%s'", yytext);
+ if (yypos < yylimit || !feof(input))
+ {
+ yybuf[yylimit]= '\0';
+ fprintf(stderr, " before text \"");
+ while (yypos < yylimit)
+ {
+ if ('\n' == yybuf[yypos] || '\r' == yybuf[yypos]) break;
+ fputc(yybuf[yypos++], stderr);
+ }
+ if (yypos == yylimit)
+ {
+ int c;
+ while (EOF != (c= fgetc(input)) && '\n' != c && '\r' != c)
+ fputc(c, stderr);
+ }
+ fputc('\"', stderr);
+ }
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+void makeHeader(char *text)
+{
+ Header *header= (Header *)malloc(sizeof(Header));
+ header->text= strdup(text);
+ header->next= headers;
+ headers= header;
+}
+
+void makeTrailer(char *text)
+{
+ trailer= strdup(text);
+}
+
+static void version(char *name)
+{
+ printf("%s version %d.%d.%d\n", name, PEG_MAJOR, PEG_MINOR, PEG_LEVEL);
+}
+
+static void usage(char *name)
+{
+ version(name);
+ fprintf(stderr, "usage: %s [