#include <stdio.h>
#include <limits.h>
#include "iburg.h"
+
+#define YYDEBUG 1
+
static char rcsid[] = "$Id$";
-static int yylineno = 0;
+static int nextesn = 0;
+static int nextern = 0;
+
%}
%union {
int n;
- char *string;
+ char* string;
Tree tree;
+ Stringlist stringlist;
}
%term TERMINAL
%term START
%term PPERCENT
-%token <string> ID
-%token <n> INT
-%type <string> lhs
-%type <tree> tree
-%type <n> cost
+%term PATTERNS
+%term PAT
+%term WHEN
+%term EMIT
+%term COST
+
+%token <string> ID
+%token <string> CFRAGMENT
+%token <n> INT
+
+%type <string> lhs
+%type <tree> rhs
+%type <n> cost
+%type <stringlist> when
+%type <stringlist> stringlist
%%
-spec : decls PPERCENT rules { yylineno = 0; }
- | decls { yylineno = 0; }
+spec
+ : decls PPERCENT patterns
+ | decls
;
decls : /* lambda */
| decls decl
;
-decl : TERMINAL blist '\n'
- | START lhs '\n' {
- if (nonterm($2)->number != 1)
- yyerror("redeclaration of the start symbol\n");
- }
- | '\n'
- | error '\n' { yyerrok; }
+decl
+ : TERMINAL blist ';'
+ | START lhs ';'
+ {
+ if (nonterm($2)->number != 1)
+ yyerror("redeclaration of the start symbol\n");
+ }
+ | ';'
+ | error ';' { yyerrok; }
;
-blist : /* lambda */
- | blist ID '=' INT { term($2, $4); }
- ;
+blist
+ : /* nothing */
+ | blist ID { term($2, nextesn++); }
+ ;
-rules : /* lambda */
- | rules lhs ':' tree '=' INT cost ';' '\n' { rule($2, $4, $6, $7); }
- | rules '\n'
- | rules error '\n' { yyerrok; }
+patterns
+ : /* nothing */
+ | patterns pattern ';'
+ | patterns ';'
+ | patterns error ';' { yyerrok; }
;
-lhs : ID { nonterm($$ = $1); }
+pattern
+ : lhs '=' rhs when cost { rule($1, $3, nextern++, $4, $5); }
+ ;
+
+lhs
+ : ID { $$ = $1; nonterm($$); }
;
-tree : ID { $$ = tree($1, NULL, NULL); }
- | ID '(' tree ')' { $$ = tree($1, $3, NULL); }
- | ID '(' tree ',' tree ')' { $$ = tree($1, $3, $5); }
+rhs
+ : ID { $$ = tree($1, NULL, NULL); }
+ | ID '(' rhs ')' { $$ = tree($1, $3, NULL); }
+ | ID '(' rhs ',' rhs ')' { $$ = tree($1, $3, $5); }
;
-cost : /* lambda */ { $$ = 0; }
- | '(' INT ')' { if ($2 > maxcost) {
- yyerror("%d exceeds maximum cost of %d\n", $2, maxcost);
- $$ = maxcost;
- } else
- $$ = $2; }
+when
+ : /* nothing */ { $$ = NULL; }
+ | WHEN stringlist { $$ = $2; }
+ ;
+
+stringlist
+ : /* nothing */ { $$ = NULL; }
+ | CFRAGMENT stringlist { $$ = pushstring($1, $2); }
+ ;
+
+cost
+ : /* lambda */ { $$ = 0; }
+ | COST INT {
+ if ($2 > maxcost) {
+ yyerror("%d exceeds maximum cost of %d\n", $2, maxcost);
+ $$ = maxcost;
+ } else
+ $$ = $2;
+ }
;
%%
#include <stdarg.h>
static char buf[BUFSIZ], *bp = buf;
static int ppercent = 0;
-static int get(void) {
- if (*bp == 0) {
- bp = buf;
- *bp = 0;
- if (fgets(buf, sizeof buf, infp) == NULL)
- return EOF;
- yylineno++;
- while (buf[0] == '%' && buf[1] == '{' && (buf[2] == '\n' || buf[2] == '\r')) {
- for (;;) {
- if (fgets(buf, sizeof buf, infp) == NULL) {
- yywarn("unterminated %{...%}\n");
- return EOF;
- }
- yylineno++;
- if (strcmp(buf, "%}\n") == 0 || strcmp(buf, "%}\r\n") == 0)
- break;
- fputs(buf, outfp);
- }
- if (fgets(buf, sizeof buf, infp) == NULL)
- return EOF;
- yylineno++;
- }
- }
- return *bp++;
-}
-
void yyerror(char *fmt, ...) {
va_list ap;
errcnt++;
}
-int yylex(void) {
- int c;
-
- while ((c = get()) != EOF) {
- switch (c) {
- case ' ': case '\f': case '\t': case '\r':
- continue;
- case '\n':
- case '(': case ')': case ',':
- case ';': case '=': case ':':
- return c;
- }
- if (c == '%' && *bp == '%') {
- bp++;
- return ppercent++ ? 0 : PPERCENT;
- } else if (c == '%' && strncmp(bp, "term", 4) == 0
- && isspace(bp[4])) {
- bp += 4;
- return TERMINAL;
- } else if (c == '%' && strncmp(bp, "start", 5) == 0
- && isspace(bp[5])) {
- bp += 5;
- return START;
- } else if (isdigit(c)) {
- int n = 0;
- do {
- int d = c - '0';
- if (n > (INT_MAX - d)/10)
- yyerror("integer greater than %d\n", INT_MAX);
- else
- n = 10*n + d;
- c = get();
- } while (c != EOF && isdigit(c));
- bp--;
- yylval.n = n;
- return INT;
- } else if (isalpha(c)) {
- char *p = bp - 1;
- while (isalpha(*bp) || isdigit(*bp) || *bp == '_')
- bp++;
- yylval.string = alloc(bp - p + 1);
- strncpy(yylval.string, p, bp - p);
- yylval.string[bp - p] = 0;
- return ID;
- } else if (isprint(c))
- yyerror("invalid character `%c'\n", c);
- else
- yyerror("invalid character `\\%03o'\n", (unsigned char)c);
- }
- return 0;
-}
-
void yywarn(char *fmt, ...) {
va_list ap;
fprintf(stderr, "warning: ");
vfprintf(stderr, fmt, ap);
}
+
+/* vim: set sw=4 ts=4 expandtab : */
static Rule rules;
static int nrules;
-static char* stringf(char* fmt, ...);
static void print(char* fmt, ...);
static void ckreach(Nonterm p);
static void emitclosure(Nonterm nts);
static void emitnts(Rule rules, int nrules);
static void emitrecord(char* pre, Rule r, int cost);
static void emitrule(Nonterm nts);
+static void emitpredicatedefinitions(Rule rules);
+static void emitpredicatecall(Rule rule);
static void emitstate(Term terms, Nonterm start, int ntnumber);
static void emitstring(Rule rules);
static void emitstruct(Nonterm nts, int ntnumber);
int c, i;
Nonterm p;
+ #if 0
+ extern int yydebug;
+ yydebug = 1;
+ #endif
+
if (sizeof(short) == sizeof(int))
maxcost = SHRT_MAX / 2;
for (i = 1; i < argc; i++)
infp = stdin;
if (outfp == NULL)
outfp = stdout;
+
+ yyin = infp;
yyparse();
+
if (start)
ckreach(start);
for (p = nts; p; p = p->link)
emitstring(rules);
emitrule(nts);
emitclosure(nts);
+ emitpredicatedefinitions(rules);
if (start)
emitstate(terms, start, ntnumber);
print("#ifdef STATE_LABEL\n");
emitkids(rules, nrules);
emitfuncs();
print("#endif\n");
- if (!feof(infp))
- while ((c = getc(infp)) != EOF)
- putc(c, outfp);
+ print("#include \"mcgg_generated_footer.h\"\n");
return errcnt > 0;
}
-/* alloc - allocate nbytes or issue fatal error */
-void* alloc(int nbytes)
+/* stringf - format and save a string */
+char* stringf(char* fmt, ...)
{
- void* p = calloc(1, nbytes);
+ int n;
+ char* p;
+ va_list ap;
- if (p == NULL)
- {
- yyerror("out of memory\n");
- exit(1);
- }
- return p;
-}
+ va_start(ap, fmt);
+ n = vsnprintf(NULL, 0, fmt, ap) + 1;
+ va_end(ap);
-/* stringf - format and save a string */
-static char* stringf(char* fmt, ...)
-{
- va_list ap;
- char* s, buf[512];
+ p = malloc(n);
+ if (!p)
+ return NULL;
- va_start(ap, fmt);
- vsprintf(buf, fmt, ap);
- va_end(ap);
- return strcpy(alloc(strlen(buf) + 1), buf);
+ va_start(ap, fmt);
+ vsnprintf(p, n, fmt, ap);
+ va_end(ap);
+
+ return p;
}
struct entry
/* install - install symbol name */
static void* install(char* name)
{
- struct entry* p = alloc(sizeof *p);
+ struct entry* p = calloc(1, sizeof *p);
int i = hash(name) % HASHSIZE;
p->sym.name = name;
p->name, p->esn);
p->link = *q;
*q = p;
+
+ if (esn != -1)
+ print("enum { %s = %d };\n", id, esn);
return p;
}
/* tree - create & initialize a tree node with the given fields */
Tree tree(char* id, Tree left, Tree right)
{
- Tree t = alloc(sizeof *t);
+ Tree t = calloc(1, sizeof *t);
Term p = lookup(id);
int arity = 0;
}
/* rule - create & initialize a rule with the given fields */
-Rule rule(char* id, Tree pattern, int ern, int cost)
+Rule rule(char* id, Tree pattern, int ern, Stringlist when, int cost)
{
- Rule r = alloc(sizeof *r), *q;
+ Rule r = calloc(1, sizeof *r);
+ Rule *q;
Term p = pattern->op;
+ if (when && (p->arity == 0))
+ yyerror("can't have a when clause on leaf nodes");
+
nrules++;
+ r->when = when;
r->lhs = nonterm(id);
r->packed = ++r->lhs->lhscount;
for (q = &r->lhs->rules; *q; q = &(*q)->decode)
return r;
}
+Stringlist pushstring(const char* data, Stringlist list)
+{
+ Stringlist sl = calloc(1, sizeof *sl);
+ sl->payload = data;
+ sl->next = list;
+ return sl;
+}
+
/* print - formatted output */
static void print(char* fmt, ...)
{
va_end(ap);
}
+void printlineno(void)
+{
+ print("#line %d\n", yylineno);
+}
+
/* reach - mark all non-terminals in tree t as reachable */
static void reach(Tree t)
{
{
case 0:
case -1:
- print("%2{%1/* %R */\n%3c = ", r);
+ print("%2if (");
+ emitpredicatecall(r);
+ print(")\n%2{%1/* %R */\n%3c = ", r);
break;
case 1:
if (r->pattern->nterms > 1)
{
print("%2if (%1/* %R */\n", r);
emittest(r->pattern->left, "l", " ");
+ print("%3&& ");
+ emitpredicatecall(r);
+ print("\n");
print("%2) {\n%3c = ");
}
else
- print("%2{%1/* %R */\n%3c = ", r);
+ {
+ print("%2if (");
+ emitpredicatecall(r);
+ print(")\n%2{%1/* %R */\n%3c = ", r);
+ }
emitcost(r->pattern->left, "l");
break;
case 2:
emittest(r->pattern->left, "l",
r->pattern->right->nterms ? " && " : " ");
emittest(r->pattern->right, "r", " ");
+ print("%3&& ");
+ emitpredicatecall(r);
+ print("\n");
print("%2) {\n%3c = ");
}
else
- print("%2{%1/* %R */\n%3c = ", r);
+ {
+ print("%2if (");
+ emitpredicatecall(r);
+ print(")\n%2{%1/* %R */\n%3c = ", r);
+ }
emitcost(r->pattern->left, "l");
emitcost(r->pattern->right, "r");
break;
static void emitkids(Rule rules, int nrules)
{
int i;
- Rule r, * rc = alloc((nrules + 1) * sizeof *rc);
- char** str = alloc((nrules + 1) * sizeof *str);
+ Rule r, * rc = calloc(nrules+1, sizeof *rc);
+ char** str = calloc(nrules+1, sizeof *str);
for (i = 0, r = rules; r; r = r->link)
{
for (j = 0; str[j] && strcmp(str[j], buf); j++)
;
if (str[j] == NULL)
- str[j] = strcpy(alloc(strlen(buf) + 1), buf);
+ str[j] = strdup(buf);
r->kids = rc[j];
rc[j] = r;
}
"%1case 0:\n");
if (Tflag)
print("%2%Pnp = p;\n");
- print("%2STATE_LABEL(p) = %Pstate(OP_LABEL(p), 0, 0);\n%2break;\n"
+ print("%2STATE_LABEL(p) = %Pstate(p, 0, 0);\n%2break;\n"
"%1case 1:\n%2%Plabel1(LEFT_CHILD(p));\n");
if (Tflag)
print("%2%Pnp = p;\n");
- print("%2STATE_LABEL(p) = %Pstate(OP_LABEL(p),\n"
+ print("%2STATE_LABEL(p) = %Pstate(p,\n"
"%3STATE_LABEL(LEFT_CHILD(p)), 0);\n%2break;\n"
"%1case 2:\n%2%Plabel1(LEFT_CHILD(p));\n%2%Plabel1(RIGHT_CHILD(p));\n");
if (Tflag)
print("%2%Pnp = p;\n");
- print("%2STATE_LABEL(p) = %Pstate(OP_LABEL(p),\n"
+ print("%2STATE_LABEL(p) = %Pstate(p,\n"
"%3STATE_LABEL(LEFT_CHILD(p)),\n%3STATE_LABEL(RIGHT_CHILD(p)));\n%2break;\n"
"%1}\n}\n\n");
print(
if (cost == NULL)
{
- cost = alloc((ntnumber + 1) * sizeof *cost);
- rule = alloc((ntnumber + 1) * sizeof *rule);
+ cost = calloc(ntnumber+1, sizeof *cost);
+ rule = calloc(ntnumber+1, sizeof *rule);
}
for (i = 0; i <= ntnumber; i++)
{
static void emitnts(Rule rules, int nrules)
{
Rule r;
- int i, j, * nts = alloc(nrules * sizeof *nts);
- char** str = alloc(nrules * sizeof *str);
+ int i, j, * nts = calloc(nrules, sizeof *nts);
+ char** str = calloc(nrules, sizeof *str);
for (i = 0, r = rules; r; r = r->link)
{
if (str[j] == NULL)
{
print("static short %Pnts_%d[] = { %s0 };\n", j, buf);
- str[j] = strcpy(alloc(strlen(buf) + 1), buf);
+ str[j] = strdup(buf);
}
nts[i++] = j;
}
print("%1default:\n%2%Passert(0, PANIC(\"Bad goal nonterminal %%d in %Prule\\n\", goalnt));\n%1}\n%1return 0;\n}\n\n");
}
+/* emitpredicates - emit predicates for rules */
+static void emitpredicatedefinitions(Rule r)
+{
+ while (r)
+ {
+ Stringlist s = r->when;
+ if (s)
+ {
+ print("static int %Ppredicate_%d(NODEPTR_TYPE n) {\n", r->ern);
+ while (s)
+ {
+ print("%s", s->payload);
+ s = s->next;
+ }
+ print("\n}\n\n");
+ }
+ r = r->link;
+ }
+}
+
+/* emitpredicatecall - emit a call to a predicate */
+static void emitpredicatecall(Rule r)
+{
+ if (r->when)
+ print("%Ppredicate_%d(node)", r->ern);
+ else
+ print("1");
+}
+
/* emitstate - emit state function */
static void emitstate(Term terms, Nonterm start, int ntnumber)
{
int i;
Term p;
- print("STATE_TYPE %Pstate(int op, STATE_TYPE left, STATE_TYPE right) {\n%1int c;\n"
- "%1struct %Pstate *p, *l = (struct %Pstate *)left,\n"
- "%2*r = (struct %Pstate *)right;\n\n%1assert(sizeof (STATE_TYPE) >= sizeof (void *));\n%1");
+ print("STATE_TYPE %Pstate(NODEPTR_TYPE node, STATE_TYPE left, STATE_TYPE right) {\n%1int c;\n"
+ "%1int op = OP_LABEL(node);\n"
+ "%1struct %Pstate* p;\n"
+ "%1struct %Pstate* l = (struct %Pstate *)left;\n"
+ "%1struct %Pstate* r = (struct %Pstate *)right;\n"
+ "\n"
+ "%1assert(sizeof (STATE_TYPE) >= sizeof (void *));\n%1");
if (!Tflag)
print("if (%Parity[op] > 0) ");
print("{\n%2p = ALLOC(sizeof *p);\n"
/* $Id$ */
/* iburg.c: */
-extern void* alloc(int nbytes);
+extern char* stringf(char* fmt, ...);
+
+typedef struct stringlist* Stringlist;
+struct stringlist {
+ const char* payload;
+ Stringlist next;
+};
+extern Stringlist pushstring(const char* data, Stringlist list);
typedef enum
{
struct rule
{ /* rules: */
- Nonterm lhs; /* lefthand side non-terminal */
- Tree pattern; /* rule pattern */
- int ern; /* external rule number */
- int packed; /* packed external rule number */
- int cost; /* associated cost */
- Rule link; /* next rule in ern order */
- Rule next; /* next rule with same pattern root */
- Rule chain; /* next chain rule with same rhs */
- Rule decode; /* next rule with same lhs */
- Rule kids; /* next rule with same burm_kids pattern */
+ Nonterm lhs; /* lefthand side non-terminal */
+ Tree pattern; /* rule pattern */
+ int ern; /* external rule number */
+ int packed; /* packed external rule number */
+ int cost; /* associated cost */
+ Rule link; /* next rule in ern order */
+ Rule next; /* next rule with same pattern root */
+ Rule chain; /* next chain rule with same rhs */
+ Rule decode; /* next rule with same lhs */
+ Rule kids; /* next rule with same burm_kids pattern */
+ Stringlist when; /* C predicate string */
};
-extern Rule rule(char* id, Tree pattern, int ern, int cost);
+extern Rule rule(char* id, Tree pattern, int ern, Stringlist when, int cost);
extern int maxcost; /* maximum cost */
/* gram.y: */
extern FILE* infp;
extern FILE* outfp;
+/* Stupid flex imports --- why mo header file? */
+
+extern FILE* yyin;
+extern int yylineno;
+
+extern void printlineno(void);
+
#endif