Stupid stringlist is stupid. Use a proper data structure, properly abstracted

out (so other things can use it).
This commit is contained in:
David Given 2016-09-25 12:18:39 +02:00
parent 9f78e0b36b
commit bcc74ba18d
8 changed files with 146 additions and 63 deletions

View file

@ -0,0 +1,9 @@
clibrary {
name = "lib",
srcs = { "./*.c" },
hdrs = { "./*.h" },
deps = {
},
}

View file

@ -0,0 +1,43 @@
#include <stdlib.h>
#include "stringlist.h"
void stringlist_add(struct stringlist* list, const char* data)
{
struct stringfragment* f = calloc(1, sizeof *f);
f->data = data;
if (!list->last)
list->first = list->last = f;
else
{
list->last->next = f;
list->last = f;
}
}
void stringlist_addall(struct stringlist* list, struct stringlist* src)
{
struct stringfragment* f = src->first;
while (f)
{
stringlist_add(list, f->data);
f = f->next;
}
}
void stringlist_free(struct stringlist* list)
{
struct stringfragment* f = list->first;
while (f)
{
struct stringfragment* next = f->next;
free(f);
f = next;
}
}
/* vim: set sw=4 ts=4 expandtab : */

View file

@ -0,0 +1,23 @@
#ifndef STRINGLIST_H
#define STRINGLIST_H
struct stringfragment
{
const char* data;
struct stringfragment* next;
};
struct stringlist
{
struct stringfragment* first;
struct stringfragment* last;
};
extern void stringlist_add(struct stringlist* list, const char* data);
extern void stringlist_addall(struct stringlist* list, struct stringlist* src);
extern void stringlist_free(struct stringlist* list);
#endif
/* vim: set sw=4 ts=4 expandtab : */

View file

@ -43,7 +43,8 @@ cprogram {
deps = { deps = {
"./iburg.h", "./iburg.h",
"+lib", "+lib",
"+yacc" "+yacc",
"modules/src/data+lib",
} }
} }

View file

@ -1,4 +1,5 @@
%{ %{
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
@ -17,7 +18,7 @@ static int nextern = 1;
char* string; char* string;
Tree tree; Tree tree;
Rule rule; Rule rule;
Stringlist stringlist; struct stringlist* stringlist;
char* stringpair[2]; char* stringpair[2];
} }
%term TERMINAL %term TERMINAL
@ -58,7 +59,7 @@ patterns
pattern pattern
: ID '=' rhs { nonterm($1); $$ = rule($1, $3, nextern++); } : ID '=' rhs { nonterm($1); $$ = rule($1, $3, nextern++); }
| rhs { $$ = rule("stmt", $1, nextern++); } | rhs { $$ = rule("stmt", $1, nextern++); }
| pattern WHEN cfragments { $$ = $1; $$->when = $3; } | pattern WHEN cfragments { $$ = $1; stringlist_addall(&$$->when, $3); }
| pattern INS ins { $$ = $1; } | pattern INS ins { $$ = $1; }
| pattern OUTS outs { $$ = $1; } | pattern OUTS outs { $$ = $1; }
| emit { $$ = $1; } | emit { $$ = $1; }
@ -77,8 +78,8 @@ labelledid
; ;
cfragments cfragments
: /* nothing */ { $$ = NULL; } : /* nothing */ { $$ = calloc(1, sizeof *$$); }
| CFRAGMENT cfragments { $$ = pushstring($1, $2); } | cfragments CFRAGMENT { $$ = $1; stringlist_add($$, $2); }
; ;
ins ins
@ -101,13 +102,22 @@ out
; ;
emit emit
: pattern EMIT qfragments { $$ = $1; $$->code = $3; $$->is_fragment = false; } : pattern EMIT qfragments {
| pattern FRAGMENT qfragments { $$ = $1; $$->code = $3; $$->is_fragment = true; } $$ = $1;
stringlist_add($3, "\n");
stringlist_addall(&$$->code, $3);
$$->is_fragment = false;
}
| pattern FRAGMENT qfragments {
$$ = $1;
stringlist_addall(&$$->code, $3);
$$->is_fragment = true;
}
; ;
qfragments qfragments
: QFRAGMENT { $$ = pushstring($1, NULL); } : /* nothing */ { $$ = calloc(1, sizeof *$$); }
| QFRAGMENT qfragments { $$ = pushstring($1, $2); } | qfragments QFRAGMENT { $$ = $1; stringlist_add($$, $2); }
; ;
%% %%

View file

@ -365,14 +365,6 @@ Rule rule(char* id, Tree pattern, int ern)
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, ...)
{ {
@ -792,15 +784,15 @@ static void emitpredicatedefinitions(Rule r)
{ {
while (r) while (r)
{ {
Stringlist s = r->when; struct stringfragment* f = r->when.first;
if (s) if (f)
{ {
print("/* %R */\n", r); print("/* %R */\n", r);
print("static int %Ppredicate_%d(NODEPTR_TYPE n) {\n", r->ern); print("static int %Ppredicate_%d(NODEPTR_TYPE n) {\n", r->ern);
while (s) while (f)
{ {
print("%s", s->payload); print("%s", f->data);
s = s->next; f = f->next;
} }
print("\n}\n\n"); print("\n}\n\n");
} }
@ -866,32 +858,42 @@ static void emitemitters(Rule rules)
r = rules; r = rules;
while (r) while (r)
{ {
Stringlist s = r->code; struct stringfragment* f = r->code.first;
if (s) if (f)
{ {
print("/* %R */\n", r); print("/* %R */\n", r);
print("static void %Pemitter_%d(NODEPTR_TYPE node, struct %Pemitter_data* data) {\n", r->ern); print("static void %Pemitter_%d(NODEPTR_TYPE node, struct %Pemitter_data* data) {\n", r->ern);
emittreefetchers(0, r->pattern); emittreefetchers(0, r->pattern);
print("%1NODEPTR_TYPE node_%s = node;\n", r->lhs->name); print("%1NODEPTR_TYPE node_%s = node;\n", r->lhs->name);
while (s) while (f)
{ {
if (s->payload[0] == '%') switch (f->data[0])
{ {
const char* label = s->payload + 1; case '%':
Tree t = find_label(r->pattern, label);
if (!t && (strcmp(label, r->lhs->name) != 0))
{ {
yylineno = r->lineno; const char* label = f->data + 1;
yyerror("label '%s' not found", label); Tree t = find_label(r->pattern, label);
exit(1); if (!t && (strcmp(label, r->lhs->name) != 0))
{
yylineno = r->lineno;
yyerror("label '%s' not found", label);
exit(1);
}
print("%1data->emit_ir(node_%s);\n", label);
break;
} }
print("%1data->emit_ir(node_%s);\n", label);
}
else
print("%1data->emit_string(\"%s\");\n", s->payload);
s = s->next; case '\n':
assert(f->data[1] == 0);
print("%1data->emit_eoi();\n");
break;
default:
print("%1data->emit_string(\"%s\");\n", f->data);
}
f = f->next;
} }
print("}\n\n"); print("}\n\n");
@ -904,9 +906,10 @@ static void emitemitters(Rule rules)
print("%Pemitter_t* const %Pemitters[] = {\n"); print("%Pemitter_t* const %Pemitters[] = {\n");
while (r) while (r)
{ {
Stringlist s = r->code; struct stringfragment* f = r->code.first;
print("%1"); print("%1");
if (s) if (f)
print("&%Pemitter_%d,", r->ern); print("&%Pemitter_%d,", r->ern);
else else
print("NULL,"); print("NULL,");
@ -920,7 +923,7 @@ static void emitemitters(Rule rules)
/* emitcost - emit a cost calculation via a predicate */ /* emitcost - emit a cost calculation via a predicate */
static void emitcostcalc(Rule r) static void emitcostcalc(Rule r)
{ {
if (r->when) if (r->when.first)
print("!%Ppredicate_%d(node) ? %d : ", r->ern, maxcost); print("!%Ppredicate_%d(node) ? %d : ", r->ern, maxcost);
} }

View file

@ -1,16 +1,9 @@
#ifndef BURG_INCLUDED #ifndef BURG_INCLUDED
#define BURG_INCLUDED #define BURG_INCLUDED
/* $Id$ */ #include "stringlist.h"
/* iburg.c: */
extern char* stringf(char* fmt, ...);
typedef struct stringlist* Stringlist; extern char* stringf(char* fmt, ...);
struct stringlist {
const char* payload;
Stringlist next;
};
extern Stringlist pushstring(const char* data, Stringlist list);
typedef enum typedef enum
{ {
@ -56,20 +49,20 @@ extern Tree tree(const char* op, const char* label, 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 lineno; /* line number where allocated */ int lineno; /* line number where allocated */
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 */ struct stringlist when; /* C predicate string */
Stringlist code; /* compiler output code strings */ struct stringlist code; /* compiler output code strings */
bool is_fragment; /* does this rule generate an instruction fragment? */ bool is_fragment; /* does this rule generate an instruction fragment? */
}; };
extern Rule rule(char* id, Tree pattern, int ern); extern Rule rule(char* id, Tree pattern, int ern);
extern int maxcost; /* maximum cost */ extern int maxcost; /* maximum cost */

View file

@ -30,6 +30,7 @@ struct burm_emitter_data
void* user; void* user;
void (*emit_string)(const char* data); void (*emit_string)(const char* data);
void (*emit_ir)(struct ir* ir); void (*emit_ir)(struct ir* ir);
void (*emit_eoi)(void);
}; };
typedef void burm_emitter_t(struct ir* ir, struct burm_emitter_data* data); typedef void burm_emitter_t(struct ir* ir, struct burm_emitter_data* data);