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 = {
"./iburg.h",
"+lib",
"+yacc"
"+yacc",
"modules/src/data+lib",
}
}

View file

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

View file

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

View file

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

View file

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