Massive grammar overhaul and refactor. Hacked in support for predicates, where
instructions can be turned on and off based on their parameters. New lexer using a lexer. Now quite a lot of the way towards being a real instruction selector.
This commit is contained in:
parent
2183c6c622
commit
4546dd5f22
|
@ -27,6 +27,7 @@ cprogram {
|
||||||
"modules/src/read_em+lib_kv",
|
"modules/src/read_em+lib_kv",
|
||||||
"modules/src/system+lib",
|
"modules/src/system+lib",
|
||||||
"./*.h",
|
"./*.h",
|
||||||
|
"util/mcgg+mcgg",
|
||||||
},
|
},
|
||||||
vars = {
|
vars = {
|
||||||
["+cflags"] = {
|
["+cflags"] = {
|
||||||
|
|
25
util/mcgg/build.lua
Normal file
25
util/mcgg/build.lua
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
include("first/yacc.lua")
|
||||||
|
|
||||||
|
flex {
|
||||||
|
name = "flex",
|
||||||
|
srcs = { "./*.l" },
|
||||||
|
}
|
||||||
|
|
||||||
|
yacc {
|
||||||
|
name = "yacc",
|
||||||
|
srcs = { "./*.y" },
|
||||||
|
}
|
||||||
|
|
||||||
|
cprogram {
|
||||||
|
name = "mcgg",
|
||||||
|
srcs = {
|
||||||
|
"./*.c",
|
||||||
|
matching(filenamesof("+flex"), "%.c$"),
|
||||||
|
matching(filenamesof("+yacc"), "%.c$")
|
||||||
|
},
|
||||||
|
deps = {
|
||||||
|
"./*.h",
|
||||||
|
"+yacc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
186
util/mcgg/gram.y
186
util/mcgg/gram.y
|
@ -3,65 +3,105 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include "iburg.h"
|
#include "iburg.h"
|
||||||
|
|
||||||
|
#define YYDEBUG 1
|
||||||
|
|
||||||
static char rcsid[] = "$Id$";
|
static char rcsid[] = "$Id$";
|
||||||
static int yylineno = 0;
|
static int nextesn = 0;
|
||||||
|
static int nextern = 0;
|
||||||
|
|
||||||
%}
|
%}
|
||||||
%union {
|
%union {
|
||||||
int n;
|
int n;
|
||||||
char *string;
|
char* string;
|
||||||
Tree tree;
|
Tree tree;
|
||||||
|
Stringlist stringlist;
|
||||||
}
|
}
|
||||||
%term TERMINAL
|
%term TERMINAL
|
||||||
%term START
|
%term START
|
||||||
%term PPERCENT
|
%term PPERCENT
|
||||||
|
|
||||||
%token <string> ID
|
%term PATTERNS
|
||||||
%token <n> INT
|
%term PAT
|
||||||
%type <string> lhs
|
%term WHEN
|
||||||
%type <tree> tree
|
%term EMIT
|
||||||
%type <n> cost
|
%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; }
|
spec
|
||||||
| decls { yylineno = 0; }
|
: decls PPERCENT patterns
|
||||||
|
| decls
|
||||||
;
|
;
|
||||||
|
|
||||||
decls : /* lambda */
|
decls : /* lambda */
|
||||||
| decls decl
|
| decls decl
|
||||||
;
|
;
|
||||||
|
|
||||||
decl : TERMINAL blist '\n'
|
decl
|
||||||
| START lhs '\n' {
|
: TERMINAL blist ';'
|
||||||
if (nonterm($2)->number != 1)
|
| START lhs ';'
|
||||||
yyerror("redeclaration of the start symbol\n");
|
{
|
||||||
}
|
if (nonterm($2)->number != 1)
|
||||||
| '\n'
|
yyerror("redeclaration of the start symbol\n");
|
||||||
| error '\n' { yyerrok; }
|
}
|
||||||
|
| ';'
|
||||||
|
| error ';' { yyerrok; }
|
||||||
;
|
;
|
||||||
|
|
||||||
blist : /* lambda */
|
blist
|
||||||
| blist ID '=' INT { term($2, $4); }
|
: /* nothing */
|
||||||
|
| blist ID { term($2, nextesn++); }
|
||||||
|
;
|
||||||
|
|
||||||
|
patterns
|
||||||
|
: /* nothing */
|
||||||
|
| patterns pattern ';'
|
||||||
|
| patterns ';'
|
||||||
|
| patterns error ';' { yyerrok; }
|
||||||
;
|
;
|
||||||
|
|
||||||
rules : /* lambda */
|
pattern
|
||||||
| rules lhs ':' tree '=' INT cost ';' '\n' { rule($2, $4, $6, $7); }
|
: lhs '=' rhs when cost { rule($1, $3, nextern++, $4, $5); }
|
||||||
| rules '\n'
|
;
|
||||||
| rules error '\n' { yyerrok; }
|
|
||||||
|
lhs
|
||||||
|
: ID { $$ = $1; nonterm($$); }
|
||||||
;
|
;
|
||||||
|
|
||||||
lhs : ID { nonterm($$ = $1); }
|
rhs
|
||||||
|
: ID { $$ = tree($1, NULL, NULL); }
|
||||||
|
| ID '(' rhs ')' { $$ = tree($1, $3, NULL); }
|
||||||
|
| ID '(' rhs ',' rhs ')' { $$ = tree($1, $3, $5); }
|
||||||
;
|
;
|
||||||
|
|
||||||
tree : ID { $$ = tree($1, NULL, NULL); }
|
when
|
||||||
| ID '(' tree ')' { $$ = tree($1, $3, NULL); }
|
: /* nothing */ { $$ = NULL; }
|
||||||
| ID '(' tree ',' tree ')' { $$ = tree($1, $3, $5); }
|
| WHEN stringlist { $$ = $2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
cost : /* lambda */ { $$ = 0; }
|
stringlist
|
||||||
| '(' INT ')' { if ($2 > maxcost) {
|
: /* nothing */ { $$ = NULL; }
|
||||||
yyerror("%d exceeds maximum cost of %d\n", $2, maxcost);
|
| CFRAGMENT stringlist { $$ = pushstring($1, $2); }
|
||||||
$$ = maxcost;
|
;
|
||||||
} else
|
|
||||||
$$ = $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>
|
#include <stdarg.h>
|
||||||
|
@ -73,32 +113,6 @@ FILE *outfp = NULL;
|
||||||
static char buf[BUFSIZ], *bp = buf;
|
static char buf[BUFSIZ], *bp = buf;
|
||||||
static int ppercent = 0;
|
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, ...) {
|
void yyerror(char *fmt, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
|
@ -111,58 +125,6 @@ void yyerror(char *fmt, ...) {
|
||||||
errcnt++;
|
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, ...) {
|
void yywarn(char *fmt, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
|
@ -172,3 +134,5 @@ void yywarn(char *fmt, ...) {
|
||||||
fprintf(stderr, "warning: ");
|
fprintf(stderr, "warning: ");
|
||||||
vfprintf(stderr, fmt, ap);
|
vfprintf(stderr, fmt, ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* vim: set sw=4 ts=4 expandtab : */
|
||||||
|
|
|
@ -20,7 +20,6 @@ static Nonterm nts;
|
||||||
static Rule rules;
|
static Rule rules;
|
||||||
static int nrules;
|
static int nrules;
|
||||||
|
|
||||||
static char* stringf(char* fmt, ...);
|
|
||||||
static void print(char* fmt, ...);
|
static void print(char* fmt, ...);
|
||||||
static void ckreach(Nonterm p);
|
static void ckreach(Nonterm p);
|
||||||
static void emitclosure(Nonterm nts);
|
static void emitclosure(Nonterm nts);
|
||||||
|
@ -34,6 +33,8 @@ static void emitleaf(Term p, int ntnumber);
|
||||||
static void emitnts(Rule rules, int nrules);
|
static void emitnts(Rule rules, int nrules);
|
||||||
static void emitrecord(char* pre, Rule r, int cost);
|
static void emitrecord(char* pre, Rule r, int cost);
|
||||||
static void emitrule(Nonterm nts);
|
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 emitstate(Term terms, Nonterm start, int ntnumber);
|
||||||
static void emitstring(Rule rules);
|
static void emitstring(Rule rules);
|
||||||
static void emitstruct(Nonterm nts, int ntnumber);
|
static void emitstruct(Nonterm nts, int ntnumber);
|
||||||
|
@ -45,6 +46,11 @@ int main(int argc, char* argv[])
|
||||||
int c, i;
|
int c, i;
|
||||||
Nonterm p;
|
Nonterm p;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
extern int yydebug;
|
||||||
|
yydebug = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (sizeof(short) == sizeof(int))
|
if (sizeof(short) == sizeof(int))
|
||||||
maxcost = SHRT_MAX / 2;
|
maxcost = SHRT_MAX / 2;
|
||||||
for (i = 1; i < argc; i++)
|
for (i = 1; i < argc; i++)
|
||||||
|
@ -88,7 +94,10 @@ int main(int argc, char* argv[])
|
||||||
infp = stdin;
|
infp = stdin;
|
||||||
if (outfp == NULL)
|
if (outfp == NULL)
|
||||||
outfp = stdout;
|
outfp = stdout;
|
||||||
|
|
||||||
|
yyin = infp;
|
||||||
yyparse();
|
yyparse();
|
||||||
|
|
||||||
if (start)
|
if (start)
|
||||||
ckreach(start);
|
ckreach(start);
|
||||||
for (p = nts; p; p = p->link)
|
for (p = nts; p; p = p->link)
|
||||||
|
@ -103,6 +112,7 @@ int main(int argc, char* argv[])
|
||||||
emitstring(rules);
|
emitstring(rules);
|
||||||
emitrule(nts);
|
emitrule(nts);
|
||||||
emitclosure(nts);
|
emitclosure(nts);
|
||||||
|
emitpredicatedefinitions(rules);
|
||||||
if (start)
|
if (start)
|
||||||
emitstate(terms, start, ntnumber);
|
emitstate(terms, start, ntnumber);
|
||||||
print("#ifdef STATE_LABEL\n");
|
print("#ifdef STATE_LABEL\n");
|
||||||
|
@ -111,35 +121,30 @@ int main(int argc, char* argv[])
|
||||||
emitkids(rules, nrules);
|
emitkids(rules, nrules);
|
||||||
emitfuncs();
|
emitfuncs();
|
||||||
print("#endif\n");
|
print("#endif\n");
|
||||||
if (!feof(infp))
|
print("#include \"mcgg_generated_footer.h\"\n");
|
||||||
while ((c = getc(infp)) != EOF)
|
|
||||||
putc(c, outfp);
|
|
||||||
return errcnt > 0;
|
return errcnt > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* alloc - allocate nbytes or issue fatal error */
|
|
||||||
void* alloc(int nbytes)
|
|
||||||
{
|
|
||||||
void* p = calloc(1, nbytes);
|
|
||||||
|
|
||||||
if (p == NULL)
|
|
||||||
{
|
|
||||||
yyerror("out of memory\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* stringf - format and save a string */
|
/* stringf - format and save a string */
|
||||||
static char* stringf(char* fmt, ...)
|
char* stringf(char* fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
int n;
|
||||||
char* s, buf[512];
|
char* p;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vsprintf(buf, fmt, ap);
|
n = vsnprintf(NULL, 0, fmt, ap) + 1;
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return strcpy(alloc(strlen(buf) + 1), buf);
|
|
||||||
|
p = malloc(n);
|
||||||
|
if (!p)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(p, n, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct entry
|
struct entry
|
||||||
|
@ -178,7 +183,7 @@ static void* lookup(char* name)
|
||||||
/* install - install symbol name */
|
/* install - install symbol name */
|
||||||
static void* install(char* name)
|
static void* install(char* name)
|
||||||
{
|
{
|
||||||
struct entry* p = alloc(sizeof *p);
|
struct entry* p = calloc(1, sizeof *p);
|
||||||
int i = hash(name) % HASHSIZE;
|
int i = hash(name) % HASHSIZE;
|
||||||
|
|
||||||
p->sym.name = name;
|
p->sym.name = name;
|
||||||
|
@ -228,13 +233,16 @@ Term term(char* id, int esn)
|
||||||
p->name, p->esn);
|
p->name, p->esn);
|
||||||
p->link = *q;
|
p->link = *q;
|
||||||
*q = p;
|
*q = p;
|
||||||
|
|
||||||
|
if (esn != -1)
|
||||||
|
print("enum { %s = %d };\n", id, esn);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tree - create & initialize a tree node with the given fields */
|
/* tree - create & initialize a tree node with the given fields */
|
||||||
Tree tree(char* id, Tree left, Tree right)
|
Tree tree(char* id, Tree left, Tree right)
|
||||||
{
|
{
|
||||||
Tree t = alloc(sizeof *t);
|
Tree t = calloc(1, sizeof *t);
|
||||||
Term p = lookup(id);
|
Term p = lookup(id);
|
||||||
int arity = 0;
|
int arity = 0;
|
||||||
|
|
||||||
|
@ -268,12 +276,17 @@ Tree tree(char* id, Tree left, Tree right)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rule - create & initialize a rule with the given fields */
|
/* 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;
|
Term p = pattern->op;
|
||||||
|
|
||||||
|
if (when && (p->arity == 0))
|
||||||
|
yyerror("can't have a when clause on leaf nodes");
|
||||||
|
|
||||||
nrules++;
|
nrules++;
|
||||||
|
r->when = when;
|
||||||
r->lhs = nonterm(id);
|
r->lhs = nonterm(id);
|
||||||
r->packed = ++r->lhs->lhscount;
|
r->packed = ++r->lhs->lhscount;
|
||||||
for (q = &r->lhs->rules; *q; q = &(*q)->decode)
|
for (q = &r->lhs->rules; *q; q = &(*q)->decode)
|
||||||
|
@ -302,6 +315,14 @@ Rule rule(char* id, Tree pattern, int ern, int cost)
|
||||||
return r;
|
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 */
|
/* print - formatted output */
|
||||||
static void print(char* fmt, ...)
|
static void print(char* fmt, ...)
|
||||||
{
|
{
|
||||||
|
@ -360,6 +381,11 @@ static void print(char* fmt, ...)
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printlineno(void)
|
||||||
|
{
|
||||||
|
print("#line %d\n", yylineno);
|
||||||
|
}
|
||||||
|
|
||||||
/* reach - mark all non-terminals in tree t as reachable */
|
/* reach - mark all non-terminals in tree t as reachable */
|
||||||
static void reach(Tree t)
|
static void reach(Tree t)
|
||||||
{
|
{
|
||||||
|
@ -415,17 +441,26 @@ static void emitcase(Term p, int ntnumber)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
case -1:
|
case -1:
|
||||||
print("%2{%1/* %R */\n%3c = ", r);
|
print("%2if (");
|
||||||
|
emitpredicatecall(r);
|
||||||
|
print(")\n%2{%1/* %R */\n%3c = ", r);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (r->pattern->nterms > 1)
|
if (r->pattern->nterms > 1)
|
||||||
{
|
{
|
||||||
print("%2if (%1/* %R */\n", r);
|
print("%2if (%1/* %R */\n", r);
|
||||||
emittest(r->pattern->left, "l", " ");
|
emittest(r->pattern->left, "l", " ");
|
||||||
|
print("%3&& ");
|
||||||
|
emitpredicatecall(r);
|
||||||
|
print("\n");
|
||||||
print("%2) {\n%3c = ");
|
print("%2) {\n%3c = ");
|
||||||
}
|
}
|
||||||
else
|
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->left, "l");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -435,10 +470,17 @@ static void emitcase(Term p, int ntnumber)
|
||||||
emittest(r->pattern->left, "l",
|
emittest(r->pattern->left, "l",
|
||||||
r->pattern->right->nterms ? " && " : " ");
|
r->pattern->right->nterms ? " && " : " ");
|
||||||
emittest(r->pattern->right, "r", " ");
|
emittest(r->pattern->right, "r", " ");
|
||||||
|
print("%3&& ");
|
||||||
|
emitpredicatecall(r);
|
||||||
|
print("\n");
|
||||||
print("%2) {\n%3c = ");
|
print("%2) {\n%3c = ");
|
||||||
}
|
}
|
||||||
else
|
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->left, "l");
|
||||||
emitcost(r->pattern->right, "r");
|
emitcost(r->pattern->right, "r");
|
||||||
break;
|
break;
|
||||||
|
@ -555,8 +597,8 @@ static char* computekids(Tree t, char* v, char* bp, int* ip)
|
||||||
static void emitkids(Rule rules, int nrules)
|
static void emitkids(Rule rules, int nrules)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
Rule r, * rc = alloc((nrules + 1) * sizeof *rc);
|
Rule r, * rc = calloc(nrules+1, sizeof *rc);
|
||||||
char** str = alloc((nrules + 1) * sizeof *str);
|
char** str = calloc(nrules+1, sizeof *str);
|
||||||
|
|
||||||
for (i = 0, r = rules; r; r = r->link)
|
for (i = 0, r = rules; r; r = r->link)
|
||||||
{
|
{
|
||||||
|
@ -566,7 +608,7 @@ static void emitkids(Rule rules, int nrules)
|
||||||
for (j = 0; str[j] && strcmp(str[j], buf); j++)
|
for (j = 0; str[j] && strcmp(str[j], buf); j++)
|
||||||
;
|
;
|
||||||
if (str[j] == NULL)
|
if (str[j] == NULL)
|
||||||
str[j] = strcpy(alloc(strlen(buf) + 1), buf);
|
str[j] = strdup(buf);
|
||||||
r->kids = rc[j];
|
r->kids = rc[j];
|
||||||
rc[j] = r;
|
rc[j] = r;
|
||||||
}
|
}
|
||||||
|
@ -592,16 +634,16 @@ static void emitlabel(Nonterm start)
|
||||||
"%1case 0:\n");
|
"%1case 0:\n");
|
||||||
if (Tflag)
|
if (Tflag)
|
||||||
print("%2%Pnp = p;\n");
|
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");
|
"%1case 1:\n%2%Plabel1(LEFT_CHILD(p));\n");
|
||||||
if (Tflag)
|
if (Tflag)
|
||||||
print("%2%Pnp = p;\n");
|
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"
|
"%3STATE_LABEL(LEFT_CHILD(p)), 0);\n%2break;\n"
|
||||||
"%1case 2:\n%2%Plabel1(LEFT_CHILD(p));\n%2%Plabel1(RIGHT_CHILD(p));\n");
|
"%1case 2:\n%2%Plabel1(LEFT_CHILD(p));\n%2%Plabel1(RIGHT_CHILD(p));\n");
|
||||||
if (Tflag)
|
if (Tflag)
|
||||||
print("%2%Pnp = p;\n");
|
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"
|
"%3STATE_LABEL(LEFT_CHILD(p)),\n%3STATE_LABEL(RIGHT_CHILD(p)));\n%2break;\n"
|
||||||
"%1}\n}\n\n");
|
"%1}\n}\n\n");
|
||||||
print(
|
print(
|
||||||
|
@ -635,8 +677,8 @@ static void emitleaf(Term p, int ntnumber)
|
||||||
|
|
||||||
if (cost == NULL)
|
if (cost == NULL)
|
||||||
{
|
{
|
||||||
cost = alloc((ntnumber + 1) * sizeof *cost);
|
cost = calloc(ntnumber+1, sizeof *cost);
|
||||||
rule = alloc((ntnumber + 1) * sizeof *rule);
|
rule = calloc(ntnumber+1, sizeof *rule);
|
||||||
}
|
}
|
||||||
for (i = 0; i <= ntnumber; i++)
|
for (i = 0; i <= ntnumber; i++)
|
||||||
{
|
{
|
||||||
|
@ -686,8 +728,8 @@ static char* computents(Tree t, char* bp)
|
||||||
static void emitnts(Rule rules, int nrules)
|
static void emitnts(Rule rules, int nrules)
|
||||||
{
|
{
|
||||||
Rule r;
|
Rule r;
|
||||||
int i, j, * nts = alloc(nrules * sizeof *nts);
|
int i, j, * nts = calloc(nrules, sizeof *nts);
|
||||||
char** str = alloc(nrules * sizeof *str);
|
char** str = calloc(nrules, sizeof *str);
|
||||||
|
|
||||||
for (i = 0, r = rules; r; r = r->link)
|
for (i = 0, r = rules; r; r = r->link)
|
||||||
{
|
{
|
||||||
|
@ -698,7 +740,7 @@ static void emitnts(Rule rules, int nrules)
|
||||||
if (str[j] == NULL)
|
if (str[j] == NULL)
|
||||||
{
|
{
|
||||||
print("static short %Pnts_%d[] = { %s0 };\n", j, buf);
|
print("static short %Pnts_%d[] = { %s0 };\n", j, buf);
|
||||||
str[j] = strcpy(alloc(strlen(buf) + 1), buf);
|
str[j] = strdup(buf);
|
||||||
}
|
}
|
||||||
nts[i++] = j;
|
nts[i++] = j;
|
||||||
}
|
}
|
||||||
|
@ -752,15 +794,48 @@ static void emitrule(Nonterm nts)
|
||||||
print("%1default:\n%2%Passert(0, PANIC(\"Bad goal nonterminal %%d in %Prule\\n\", goalnt));\n%1}\n%1return 0;\n}\n\n");
|
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 */
|
/* emitstate - emit state function */
|
||||||
static void emitstate(Term terms, Nonterm start, int ntnumber)
|
static void emitstate(Term terms, Nonterm start, int ntnumber)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
Term p;
|
Term p;
|
||||||
|
|
||||||
print("STATE_TYPE %Pstate(int op, STATE_TYPE left, STATE_TYPE right) {\n%1int c;\n"
|
print("STATE_TYPE %Pstate(NODEPTR_TYPE node, STATE_TYPE left, STATE_TYPE right) {\n%1int c;\n"
|
||||||
"%1struct %Pstate *p, *l = (struct %Pstate *)left,\n"
|
"%1int op = OP_LABEL(node);\n"
|
||||||
"%2*r = (struct %Pstate *)right;\n\n%1assert(sizeof (STATE_TYPE) >= sizeof (void *));\n%1");
|
"%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)
|
if (!Tflag)
|
||||||
print("if (%Parity[op] > 0) ");
|
print("if (%Parity[op] > 0) ");
|
||||||
print("{\n%2p = ALLOC(sizeof *p);\n"
|
print("{\n%2p = ALLOC(sizeof *p);\n"
|
||||||
|
|
|
@ -3,7 +3,14 @@
|
||||||
|
|
||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
/* iburg.c: */
|
/* 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
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -48,18 +55,19 @@ extern Tree tree(char* op, Tree left, Tree right);
|
||||||
|
|
||||||
struct rule
|
struct rule
|
||||||
{ /* rules: */
|
{ /* rules: */
|
||||||
Nonterm lhs; /* lefthand side non-terminal */
|
Nonterm lhs; /* lefthand side non-terminal */
|
||||||
Tree pattern; /* rule pattern */
|
Tree pattern; /* rule pattern */
|
||||||
int ern; /* external rule number */
|
int ern; /* external rule number */
|
||||||
int packed; /* packed external rule number */
|
int packed; /* packed external rule number */
|
||||||
int cost; /* associated cost */
|
int cost; /* associated cost */
|
||||||
Rule link; /* next rule in ern order */
|
Rule link; /* next rule in ern order */
|
||||||
Rule next; /* next rule with same pattern root */
|
Rule next; /* next rule with same pattern root */
|
||||||
Rule chain; /* next chain rule with same rhs */
|
Rule chain; /* next chain rule with same rhs */
|
||||||
Rule decode; /* next rule with same lhs */
|
Rule decode; /* next rule with same lhs */
|
||||||
Rule kids; /* next rule with same burm_kids pattern */
|
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 */
|
extern int maxcost; /* maximum cost */
|
||||||
|
|
||||||
/* gram.y: */
|
/* gram.y: */
|
||||||
|
@ -70,4 +78,11 @@ extern int errcnt;
|
||||||
extern FILE* infp;
|
extern FILE* infp;
|
||||||
extern FILE* outfp;
|
extern FILE* outfp;
|
||||||
|
|
||||||
|
/* Stupid flex imports --- why mo header file? */
|
||||||
|
|
||||||
|
extern FILE* yyin;
|
||||||
|
extern int yylineno;
|
||||||
|
|
||||||
|
extern void printlineno(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
43
util/mcgg/mcgg_generated_footer.h
Normal file
43
util/mcgg/mcgg_generated_footer.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
static void dumpCover(NODEPTR_TYPE p, int goalnt, int indent) {
|
||||||
|
#ifdef TRACE
|
||||||
|
int eruleno = burm_rule(STATE_LABEL(p), goalnt);
|
||||||
|
short *nts = burm_nts[eruleno];
|
||||||
|
NODEPTR_TYPE kids[10];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < indent; i++)
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
fprintf(stderr, "%s\n", burm_string[eruleno]);
|
||||||
|
burm_kids(p, eruleno, kids);
|
||||||
|
for (i = 0; nts[i]; i++)
|
||||||
|
dumpCover(kids[i], nts[i], indent + 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static NODEPTR_TYPE tree(int op, NODEPTR_TYPE l, NODEPTR_TYPE r) {
|
||||||
|
NODEPTR_TYPE p = malloc(sizeof *p);
|
||||||
|
|
||||||
|
assert(p);
|
||||||
|
p->op = op;
|
||||||
|
p->kids[0] = l; p->kids[1] = r;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
NODEPTR_TYPE p;
|
||||||
|
|
||||||
|
p = tree(STORE,
|
||||||
|
tree(LABEL, 0, 0),
|
||||||
|
tree(ADD,
|
||||||
|
tree(LOAD,
|
||||||
|
tree(LABEL, 0, 0),
|
||||||
|
0
|
||||||
|
),
|
||||||
|
tree(CONST, 0, 0)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
burm_label(p);
|
||||||
|
dumpCover(p, 1, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
69
util/mcgg/scan.l
Normal file
69
util/mcgg/scan.l
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
%{
|
||||||
|
#include "iburg.h"
|
||||||
|
#include "y.tab.h"
|
||||||
|
|
||||||
|
static int braces = 0;
|
||||||
|
|
||||||
|
%}
|
||||||
|
%option warn
|
||||||
|
%option nodefault
|
||||||
|
%option noyywrap
|
||||||
|
%option yylineno
|
||||||
|
|
||||||
|
%x CSTRING
|
||||||
|
%x ECHO
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
<INITIAL>"%{" { printlineno(); BEGIN(ECHO); }
|
||||||
|
|
||||||
|
<ECHO>"%}" BEGIN(INITIAL);
|
||||||
|
<ECHO>[%\n] fputc(yytext[0], outfp);
|
||||||
|
<ECHO>[^%\n]* fputs(yytext, outfp);
|
||||||
|
|
||||||
|
<INITIAL>"{" {
|
||||||
|
yylval.string = stringf("#line %d\n", yylineno);
|
||||||
|
braces = 1;
|
||||||
|
BEGIN(CSTRING);
|
||||||
|
return CFRAGMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
<CSTRING>"{" {
|
||||||
|
braces++;
|
||||||
|
yylval.string = strdup(yytext);
|
||||||
|
return CFRAGMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
<CSTRING>"}" {
|
||||||
|
braces--;
|
||||||
|
if (braces == 0)
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yylval.string = strdup(yytext);
|
||||||
|
return CFRAGMENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<CSTRING>[^{}]+ {
|
||||||
|
yylval.string = strdup(yytext);
|
||||||
|
return CFRAGMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
"%%" return PPERCENT;
|
||||||
|
"%term" return TERMINAL;
|
||||||
|
"%start" return START;
|
||||||
|
|
||||||
|
"PATTERNS" return PATTERNS;
|
||||||
|
"pat" return PAT;
|
||||||
|
"when" return WHEN;
|
||||||
|
"emit" return EMIT;
|
||||||
|
"cost" return COST;
|
||||||
|
|
||||||
|
[A-Za-z_][A-Za-z0-9_]* { yylval.string = strdup(yytext); return ID; }
|
||||||
|
[0-9]+ { yylval.n = atoi(yytext); return INT; }
|
||||||
|
[ \t\r\n]* ;
|
||||||
|
. return yytext[0];
|
||||||
|
|
||||||
|
%%
|
||||||
|
/* vim: set sw=4 ts=4 expandtab : */
|
Loading…
Reference in a new issue