Add basic compiling mechanism

This commit is contained in:
Augusto Gunsch 2020-12-21 15:05:49 -03:00
parent f647a754a7
commit f26d7704a8
No known key found for this signature in database
GPG Key ID: F7EEFE29825C72DC
14 changed files with 649 additions and 917 deletions

View File

@ -1,4 +1,4 @@
FILES = tokenizer.c main.c parser.c printer.c compiler.c util.c
FILES = *.c
INCLUDES = -I.
CFLAGS = -std=c99 -g
OUTFILE = compiler

326
compiler-scopes.c Normal file
View File

@ -0,0 +1,326 @@
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "compiler-scopes.h"
// INTERNAL FUNCTIONS
// Information gathering
bool existstr(STRINGLIST* strs, char* str);
bool existclass(CLASS* c, char* name);
DEBUGINFO* getdebuginfo(OBJ* obj);
// Error messages
void doubledeclaration(char* name, DEBUGINFO* debug, OBJ* other);
void ensurenoduplicate(SCOPE* s, char* name, DEBUGINFO* debug);
// Scope handling
void popscope(SCOPE** s); // may be removed
// Single type getters
VARDEC* getvardec(SCOPE* s, char* name);
CLASSVARDEC* getclassvardec(SCOPE* s, char* name);
// Generic getters
OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, char** retname);
// Scope adding
void addclassvardec(SCOPE* s, CLASSVARDEC* v);
void addvardec(SCOPE* s, VARDEC* v);
void addsubdec(SCOPE* s, SUBDEC* sd);
void addclass(SCOPE* s, CLASS* c);
// DEFINITIONS
// Information gathering
bool existstr(STRINGLIST* strs, char* str) {
while(strs != NULL) {
if(!strcmp(strs->content, str))
return true;
strs = strs->next;
}
return false;
}
bool existclass(CLASS* c, char* name) {
while(c != NULL) {
if(!strcmp(c->name, name))
return true;
c = c->next;
}
return false;
}
// OBJ handling
DEBUGINFO* getdebugclassvardec(OBJ* obj) {
return obj->classvardec->base->debug;
}
DEBUGINFO* getdebugvardec(OBJ* obj) {
return obj->vardec->debug;
}
DEBUGINFO* getdebugsubdec(OBJ* obj) {
return obj->subdec->debug;
}
DEBUGINFO* getdebugclass(OBJ* obj) {
return obj->class->debug;
}
VARDEC* tovardec(OBJ* obj) {
if (obj->type == classvardec)
return obj->classvardec->base;
else if (obj->type == vardec)
return obj->vardec;
return NULL;
}
// Error messages
void doubledeclaration(char* name, DEBUGINFO* debug, OBJ* other) {
DEBUGINFO* debugother = other->getdebug(other);
fprintf(stderr, "Double declaration of '%s' at '%s', line %i; previously defined at '%s', line %i\n",
name, debug->file, debug->definedat, debugother->file, debugother->definedat);
exit(1);
}
void notdeclared(char* name, DEBUGINFO* debug) {
fprintf(stderr, "'%s' not declared; file '%s', line %i\n", name, debug->file, debug->definedat);
exit(1);
}
void invalidparent(SUBROUTCALL* call) {
fprintf(stderr, "Invalid subroutine parent '%s'; file '%s', line %i\n", call->parentname, call->debug->file, call->debug->definedat);
exit(1);
}
void ensurenoduplicate(SCOPE* s, char* name, DEBUGINFO* debug) {
OBJ* other = getbyname(s, name);
if(other != NULL)
doubledeclaration(name, debug, other);
}
void ensurenoduplicates(SCOPE* s, STRINGLIST* names, DEBUGINFO* debug) {
char* othername;
OBJ* other = getbynamelist(s, names, &othername);
if(other != NULL)
doubledeclaration(othername, debug, other);
}
// Scope handling
SCOPE* mkscope(SCOPE* prev) {
SCOPE* s = (SCOPE*)malloc(sizeof(SCOPE));
s->subroutines = NULL;
s->classvardecs = NULL;
s->vardecs = NULL;
s->classes = NULL;
s->previous = prev;
return s;
}
void popscope(SCOPE** s) { // might be useless
SCOPE* prev = (*s)->previous;
free(*s);
(*s) = prev;
}
// Single type getters
VARDEC* getvardec(SCOPE* s, char* name) {
VARDEC* curr = s->vardecs;
while(curr != NULL) {
if(existstr(curr->names, name))
return curr;
curr = curr->next;
}
if(s->previous != NULL)
return getvardec(s->previous, name);
return NULL;
}
CLASSVARDEC* getclassvardec(SCOPE* s, char* name) {
CLASSVARDEC* curr = s->classvardecs;
while(curr != NULL) {
if(existstr(curr->base->names, name))
return curr;
curr = curr->next;
}
if(s->previous != NULL)
return getclassvardec(s->previous, name);
return NULL;
}
SUBDEC* getsubdec(SCOPE* s, char* name) {
SUBDEC* curr = s->subroutines;
while(curr != NULL) {
if(!strcmp(curr->name, name))
return curr;
curr = curr->next;
}
if(s->previous != NULL)
return getsubdec(s->previous, name);
return NULL;
}
CLASS* getclass(SCOPE* s, char* name) {
CLASS* curr = s->classes;
while(curr != NULL) {
if(!strcmp(curr->name, name))
return curr;
curr = curr->next;
}
if(s->previous != NULL)
return getclass(s->previous, name);
return NULL;
}
SUBDEC* getsubdecfromclass(CLASS* c, char* name) {
SUBDEC* curr = c->subdecs;
while(curr != NULL) {
if(!strcmp(curr->name, name))
return curr;
curr = curr->next;
}
return NULL;
}
SUBDEC* getsubdecfromvar(SCOPE* s, OBJ* var, SUBROUTCALL* call) {
VARDEC* vd = tovardec(var);
if(vd == NULL || vd->primitive)
invalidparent(call);
CLASS* c = getclass(s, vd->type);
return getsubdecfromclass(c, call->name);
}
SUBDEC* getsubdecfromparent(SCOPE* s, SUBROUTCALL* call) {
SUBDEC* sd;
OBJ* parent = getbyname(s, call->parentname);
if(parent == NULL)
notdeclared(call->parentname, call->debug);
if(parent->type == class)
sd = getsubdecfromclass(parent->class, call->name);
else
sd = getsubdecfromvar(s, parent, call);
return sd;
}
SUBDEC* getsubdecfromcall(SCOPE* s, SUBROUTCALL* call) {
SUBDEC* sd;
if(call->parentname != NULL)
sd = getsubdecfromparent(s, call);
else
sd = getsubdec(s, call->name);
if(sd == NULL)
notdeclared(call->name, call->debug);
return sd;
}
// Generic getters
OBJ* getbyname(SCOPE* s, char* name) {
OBJ* o = (OBJ*)malloc(sizeof(OBJ));
CLASSVARDEC* cvd = getclassvardec(s, name);
if(cvd != NULL) {
o->classvardec = cvd;
o->type = classvardec;
o->getdebug = getdebugvardec;
return o;
}
VARDEC* vd = getvardec(s, name);
if(vd != NULL) {
o->vardec = vd;
o->type = vardec;
o->getdebug = getdebugsubdec;
return o;
}
SUBDEC* sd = getsubdec(s, name);
if(sd != NULL) {
o->subdec = sd;
o->type = subdec;
o->getdebug = getdebugclassvardec;
return o;
}
CLASS* c = getclass(s, name);
if(c != NULL) {
o->class = c;
o->type = class;
o->getdebug = getdebugclass;
return o;
}
free(o);
return NULL;
}
OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, char** retname) {
while(names != NULL) {
OBJ* o = getbyname(s, names->content);
if(o != NULL) {
*retname = names->content;
return o;
}
names = names->next;
}
if(s->previous != NULL)
return getbynamelist(s->previous, names, retname);
return NULL;
}
// Scope adding
void addclassvardec(SCOPE* s, CLASSVARDEC* v) {
ensurenoduplicates(s, v->base->names, v->base->debug);
v->next = s->classvardecs;
s->classvardecs = v;
}
void addvardec(SCOPE* s, VARDEC* v) {
ensurenoduplicates(s, v->names, v->debug);
v->next = s->vardecs;
s->vardecs = v;
}
void addsubdec(SCOPE* s, SUBDEC* sd) {
ensurenoduplicate(s, sd->name, sd->debug);
sd->next = s->subroutines;
s->subroutines = sd;
}
void addclass(SCOPE* s, CLASS* c) {
ensurenoduplicate(s, c->name, c->debug);
c->next = s->classes;
s->classes = c;
}
// Group adding
void addclassvardecs(SCOPE* s, CLASSVARDEC* vs) {
while(vs != NULL) {
addclassvardec(s, vs);
vs = vs->next;
}
}
void addvardecs(SCOPE* s, VARDEC* vs) {
while(vs != NULL) {
addvardec(s, vs);
vs = vs->next;
}
}
void addsubdecs(SCOPE* s, SUBDEC* ss) {
while(ss != NULL) {
addsubdec(s, ss);
ss = ss->next;
}
}
void addclasses(SCOPE* s, CLASS* c) {
while(c != NULL) {
addclass(s, c);
c = c->next;
}
}

51
compiler-scopes.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef COMPILER_SCOPES_H
#define COMPILER_SCOPES_H
#include "parser.h"
/* compiler-scopes
* Tools for dealing with scopes.
*
* They can be used to create, expand and stack scopes, as well as to enforce
* certain semantic rules. */
// Data types
typedef struct scope {
SUBDEC* subroutines;
CLASSVARDEC* classvardecs;
VARDEC* vardecs;
CLASS* classes;
struct scope* previous;
} SCOPE;
typedef enum {
subdec, classvardec, vardec, class
} OBJTYPE;
typedef struct object {
OBJTYPE type;
union {
SUBDEC* subdec;
CLASSVARDEC* classvardec;
VARDEC* vardec;
CLASS* class;
};
DEBUGINFO* (*getdebug)(struct object*);
} OBJ;
// Group adding
void addclassvardecs(SCOPE* s, CLASSVARDEC* vs);
void addvardecs(SCOPE* s, VARDEC* vs);
void addsubdecs(SCOPE* s, SUBDEC* ss);
void addclasses(SCOPE* s, CLASS* c);
// Scope handling
SCOPE* mkscope(SCOPE* prev);
// Single type getters
SUBDEC* getsubdec(SCOPE* s, char* name);
SUBDEC* getsubdecfromcall(SCOPE* s, SUBROUTCALL* call);
CLASS* getclass(SCOPE* s, char* name);
// Generic getters
OBJ* getbyname(SCOPE* s, char* name);
#endif

View File

@ -1,254 +1,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "compiler.h"
typedef enum {
subdec, classvardec, vardec, cl
} OBJTYPE;
void addtoken(LINE* l, char* token) {
l->tokens[l->tokenscount] = token;
l->tokenscount++;
}
bool existclass(CLASS* c, char* name) {
CLASS* current = c;
while(current != NULL) {
if(!strcmp(current->name, name))
return true;
current = current->next;
}
return false;
}
void doubledeclarationmsg(char* name, char* f1, int l1, char* f2, int l2) {
fprintf(stderr, "Double declaration of '%s' at '%s', line %i; previously defined at '%s', line %i\n", name, f1, l1, f2, l2);
exit(1);
}
void xtractinfo(void* obj, OBJTYPE type, char** file, int* line) {
if(type == classvardec) {
*file = ((CLASSVARDEC*)obj)->base->file;
*line = ((CLASSVARDEC*)obj)->base->definedat;
}
else if(type == vardec) {
*file = ((VARDEC*)obj)->file;
*line = ((VARDEC*)obj)->definedat;
}
else if(type == subdec) {
*file = ((SUBDEC*)obj)->file;
*line = ((SUBDEC*)obj)->definedat;
}
else if(type == cl) {
*file = ((CLASS*)obj)->file;
*line = ((CLASS*)obj)->definedat;
}
}
void doubledeclaration(char* name, void* o1, OBJTYPE t1, void* o2, OBJTYPE t2) {
char* f1;
char* f2;
int l1, l2;
xtractinfo(o1, t1, &f1, &l1);
xtractinfo(o2, t2, &f2, &l2);
doubledeclarationmsg(name, f1, l1, f2, l2);
}
SCOPE* mkscope(SCOPE* prev) {
SCOPE* s = (SCOPE*)malloc(sizeof(SCOPE));
s->subroutines = NULL;
s->classvardecs = NULL;
s->vardecs = NULL;
s->classes = NULL;
s->previous = prev;
return s;
}
void popscope(SCOPE** s) {
SCOPE* prev = (*s)->previous;
free(*s);
(*s) = prev;
}
bool existstr(STRINGLIST* strs, char* str) {
STRINGLIST* current = strs;
while(current != NULL) {
if(!strcmp(current->content, str))
return true;
current = current->next;
}
return false;
}
VARDEC* getvardec(SCOPE* s, char* name) {
VARDEC* current = s->vardecs;
while(current != NULL) {
if(existstr(current->names, name))
return current;
current = current->next;
}
if(s->previous != NULL)
return getvardec(s->previous, name);
return NULL;
}
CLASSVARDEC* getclassvardec(SCOPE* s, char* name) {
CLASSVARDEC* current = s->classvardecs;
while(current != NULL) {
if(existstr(current->base->names, name))
return current;
current = current->next;
}
if(s->previous != NULL)
return getclassvardec(s->previous, name);
return NULL;
}
SUBDEC* getsubdec(SCOPE* s, char* name) {
SUBDEC* current = s->subroutines;
while(current != NULL) {
if(!strcmp(current->name, name))
return current;
current = current->next;
}
if(s->previous != NULL)
return getsubdec(s->previous, name);
return NULL;
}
SUBDEC* getsubdecfromclass(CLASS* c, char* name) {
SUBDEC* current = c->subdecs;
while(current != NULL) {
if(!strcmp(current->name, name))
return current;
current = current->next;
}
return NULL;
}
CLASS* getclass(SCOPE* s, char* name) {
CLASS* current = s->classes;
while(current != NULL) {
if(!strcmp(current->name, name))
return current;
current = current->next;
}
if(s->previous != NULL)
return getclass(s->previous, name);
return NULL;
}
void* getbyname(SCOPE* s, OBJTYPE* t, char* name) {
SUBDEC* sd = getsubdec(s, name);
if(sd != NULL) {
*t = subdec;
return sd;
}
CLASSVARDEC* cvd = getclassvardec(s, name);
if(cvd != NULL) {
*t = classvardec;
return cvd;
}
VARDEC* vd = getvardec(s, name);
if(vd != NULL) {
*t = vardec;
return vd;
}
CLASS* c = getclass(s, name);
if(c != NULL) {
*t = cl;
return c;
}
return NULL;
}
void* getbynamelist(SCOPE* s, STRINGLIST* names, OBJTYPE* t, char** name) {
STRINGLIST* current = names;
while(current != NULL) {
void* obj = getbyname(s, t, current->content);
if(obj != NULL) {
*name = current->content;
return obj;
}
current = current->next;
}
if(s->previous != NULL)
return getbynamelist(s->previous, names, t, name);
return NULL;
}
void addclassvardec(SCOPE* s, CLASSVARDEC* v) {
OBJTYPE type;
char* name;
void* tmp = getbynamelist(s, v->base->names, &type, &name);
if(tmp != NULL)
doubledeclaration(name, v, classvardec, tmp, type);
v->next = s->classvardecs;
s->classvardecs = v;
}
void addvardec(SCOPE* s, VARDEC* v) {
OBJTYPE type;
char* name;
void* tmp = getbynamelist(s, v->names, &type, &name);
if(tmp != NULL)
doubledeclaration(name, v, vardec, tmp, type);
v->next = s->vardecs;
s->vardecs = v;
}
void addsubdec(SCOPE* s, SUBDEC* sd) {
OBJTYPE type;
void* tmp = getbyname(s, &type, sd->name);
if(tmp != NULL)
doubledeclaration(sd->name, sd, subdec, tmp, type);
sd->next = s->subroutines;
s->subroutines = sd;
}
void addclass(SCOPE* s, CLASS* c) {
OBJTYPE type;
void* tmp = getbyname(s, &type, c->name);
if(tmp != NULL)
doubledeclaration(c->name, c, cl, tmp, type);
c->next = s->classes;
s->classes = c;
}
void addclassvardecs(SCOPE* s, CLASSVARDEC* vs) {
CLASSVARDEC* current = vs;
while(current != NULL) {
addclassvardec(s, current);
current = current->next;
}
}
void addvardecs(SCOPE* s, VARDEC* vs) {
VARDEC* current = vs;
while(current != NULL) {
addvardec(s, current);
current = current->next;
}
}
void addsubdecs(SCOPE* s, SUBDEC* ss) {
SUBDEC* current = ss;
while(current != NULL) {
addsubdec(s, current);
current = current->next;
}
}
void addclasses(SCOPE* s, CLASS* c) {
CLASS* current = c;
while(current != NULL) {
addclass(s, current);
current = current->next;
}
}
int countparameters(EXPRESSIONLIST* params) {
int i = 0;
while(params != NULL) {
@ -270,7 +23,7 @@ int countlocalvars(VARDEC* decs) {
char* dotlabel(char* n1, char* n2) {
int sz = (strlen(n1) + strlen(n2) + 2) * sizeof(char);
char* result = (char*)malloc(sz);
snprintf(result, sz, "%s.%s", n1, n2);
sprintf(result, "%s.%s", n1, n2);
return result;
}
@ -278,44 +31,17 @@ char* subdecname(CLASS* c, SUBDEC* sd) {
return dotlabel(c->name, sd->name);
}
SUBDEC* getsubdecfromparent(SCOPE* s, SUBROUTCALL* call) {
SUBDEC* sd;
OBJTYPE type;
void* parent = getbyname(s, &type, call->parentname);
if(type == cl)
sd = getsubdecfromclass((CLASS*)parent, call->name);
else {
VARDEC* vd;
if (type == classvardec)
vd = ((CLASSVARDEC*)parent)->base;
else if (type == vardec)
vd = (VARDEC*)parent;
else {
fprintf(stderr, "Unexpected subroutine identifier; file '%s', line %i\n", call->file, call->definedat);
exit(1);
}
if(vd->primitive) {
fprintf(stderr, "Primitive type doesn't have methods; file '%s', line %i\n", call->file, call->definedat);
exit(1);
}
sd = getsubdecfromparent(s, call);
}
return sd;
}
LINE* onetoken(char* str) {
LINE* ln = mkline(1);
addtoken(ln, ezheapstr(str));
ln->next = NULL;
return ln;
}
LINE* mksimpleln(char** tokens) {
int count = sizeof(tokens) / sizeof(char*);
LINE* mksimpleln(char** tokens, int count) {
LINE* ln = mkline(count);
for(int i = 0; i < count; i++)
addtoken(ln, ezheapstr(tokens[i]));
return ln;
}
@ -336,115 +62,122 @@ LINE* mathopln(char op) {
return onetoken("and");
if(op == '/') {
char* tokens[] = { "call", "Math.divide", "2" };
return mksimpleln(tokens);
return mksimpleln(tokens, sizeof(tokens) / sizeof(char*));
}
if(op == '*') {
char* tokens[] = { "call", "Math.multiply", "2" };
return mksimpleln(tokens);
return mksimpleln(tokens, sizeof(tokens) / sizeof(char*));
}
}
LINE* compileexpression(SCOPE* s, TERM* e, LINE** tail) {
LINE* nexts = NULL;
LINE* nextstail;
LINE* r;
if(e->next != NULL) {
nexts = compileexpression(s, e->next, &nextstail);
LINE* op = mathopln(e->op);
nextstail->next = op;
nextstail = op;
op->next = NULL;
}
LINEBLOCK* compileexpression(SCOPE* s, TERM* e) {
LINEBLOCK* myblk;
LINEBLOCK* next = NULL;
if(e->type == intconstant) {
r = mkline(3);
addtoken(r, ezheapstr("push"));
addtoken(r, ezheapstr("constant"));
addtoken(r, itoa(e->integer));
LINE* ln = mkline(3);
addtoken(ln, ezheapstr("push"));
addtoken(ln, ezheapstr("constant"));
addtoken(ln, itoa(e->integer));
ln->next = NULL;
myblk = mklnblk(ln);
}
else if(e->type == unaryopterm) {
r = mkline(1);
addtoken(r, ezheapstr("neg"));
myblk = compileexpression(s, e->expression);
LINE* neg = onetoken("neg");
appendln(myblk, neg);
}
else if(e->type == innerexpression) {
r = compileexpression(s, e->expression, tail); // might be wrong tail
myblk = compileexpression(s, e->expression);
}
else {
fprintf(stderr, "Unsuported SHIT %i\n", e->type);
fprintf(stderr, "Unsupported term yet %i\n", e->type);
exit(1);
}
if(nexts != NULL) {
r->next = nexts;
(*tail) = nextstail;
if(e->next != NULL) {
next = compileexpression(s, e->next);
LINE* op = mathopln(e->op);
appendln(next, op);
op->next = NULL;
myblk = mergelnblks(myblk, next);
}
else {
(*tail) = r;
r->next = NULL;
}
return r;
return myblk;
}
LINE* compileparameters(SCOPE* s, EXPRESSIONLIST* ps, LINE** tail) {
LINE* head;
LINE* mytail;
if(ps != NULL)
head = compileexpression(s, ps->expression, &mytail);
LINE* currln = head;
EXPRESSIONLIST* current = ps->next;
while(current != NULL) {
LINE* newln = compileexpression(s, current->expression, &mytail);
current = current->next;
currln->next = newln;
currln = newln;
LINEBLOCK* compileparameters(SCOPE* s, EXPRESSIONLIST* params) {
LINEBLOCK* head = NULL;
while(params != NULL) {
head = mergelnblks(head, compileexpression(s, params->expression));
params = params->next;
}
(*tail) = mytail;
return head;
}
LINE* compilesubroutcall(SCOPE* s, CLASS* c, SUBROUTCALL* call) {
/* FOR NOW THERE IS NO OS SO THIS WILL CAUSE PROBLEMS
SUBDEC* sd;
LINEBLOCK* compilecallln(CLASS* c, SUBROUTCALL* call) {
LINE* ln = mkline(3);
addtoken(ln, ezheapstr("call"));
if(call->parentname != NULL)
sd = getsubdecfromparent(s, call);
addtoken(ln, dotlabel(call->parentname, call->name));
else
sd = getsubdec(s, call->name);
if(sd == NULL) {
fprintf(stderr, "Method '%s' does not exist; file '%', line %i\n", call->name, call->file, call->definedat);
exit(1);
}
*/
addtoken(ln, dotlabel(c->name, call->name));
// At the moment can only call functions
LINE* tail;
LINE* head = compileparameters(s, call->parameters, &tail);
addtoken(ln, itoa(countparameters(call->parameters)));
LINE* callvm = mkline(3);
addtoken(callvm, ezheapstr("call"));
if(call->parentname != NULL)
addtoken(callvm, dotlabel(call->parentname, call->name));
else
addtoken(callvm, dotlabel(c->name, call->name));
addtoken(callvm, itoa(countparameters(call->parameters)));
tail->next = callvm;
tail = callvm;
return head;
return mklnblk(ln);
}
LINE* compileret(SCOPE* s, TERM* e) {
// missing expression handling
// temporary ignore list for OS functions
char* ignoresubdecs[] = {
"printInt", "void"
};
int ignorecount = sizeof(ignoresubdecs) / sizeof(char*);
LINEBLOCK* compilesubroutcall(SCOPE* s, CLASS* c, SUBROUTCALL* call) {
LINEBLOCK* block = compilecallln(c, call);
if(call->parameters != NULL)
block = mergelnblks(compileparameters(s, call->parameters), block);
// void functions always return 0
// therefore must be thrown away
// gambiarra
char* type = NULL;
for(int i = 0; i < ignorecount; i += 2) {
if(!strcmp(call->name, ignoresubdecs[i])) {
type = ignoresubdecs[i+1];
break;
}
}
if(type == NULL)
type = getsubdecfromcall(s, call)->type;
if(!strcmp(type, "void")) {
char* tokens[] = { "pop", "temp", "0" };
appendln(block, mksimpleln(tokens, sizeof(tokens) / sizeof(char*)));
}
return block;
}
LINEBLOCK* compileret(SCOPE* s, TERM* e) {
LINE* ret = onetoken("return");
LINEBLOCK* block = mklnblk(ret);
// void subdecs return 0
if(e == NULL) {
LINE* r = mkline(1);
addtoken(r, ezheapstr("return"));
return r;
}
char* tokens[] = { "push", "constant", "0" };
appendlnbefore(block, mksimpleln(tokens, sizeof(tokens) / sizeof(char*)));
} else
block = mergelnblks(compileexpression(s, e), block);
return block;
}
LINE* compilestatement(SCOPE* s, CLASS* c, STATEMENT* st) {
LINEBLOCK* compilestatement(SCOPE* s, CLASS* c, STATEMENT* st) {
if(st->type == dostatement)
return compilesubroutcall(s, c, st->dost);
else if(st->type == returnstatement)
@ -455,40 +188,38 @@ LINE* compilestatement(SCOPE* s, CLASS* c, STATEMENT* st) {
}
}
LINE* compilestatements(SCOPE* s, CLASS* c, STATEMENT* sts) {
LINE* head;
LINE* curr;
if(sts != NULL) {
head = compilestatement(s, c, sts);
curr = head;
sts = sts->next;
LINEBLOCK* compilestatements(SCOPE* s, CLASS* c, STATEMENT* sts) {
LINEBLOCK* head = NULL;
while(sts != NULL) {
LINE* ln = compilestatement(s, c, sts);
curr->next = ln;
curr = ln;
head = mergelnblks(head, compilestatement(s, c, sts));
sts = sts->next;
}
}
return head;
}
LINE* compilefunbody(SCOPE* s, CLASS* c, SUBROUTBODY* b) {
LINEBLOCK* compilefunbody(SCOPE* s, CLASS* c, SUBROUTBODY* b) {
// missing scope and vardecs handling
LINE* head = compilestatements(s, c, b->statements);
LINEBLOCK* head = compilestatements(s, c, b->statements);
return head;
}
LINE* compilefundec(SCOPE* s, CLASS* c, SUBDEC* f) {
LINE* head = mkline(3);
addtoken(head, ezheapstr("function"));
addtoken(head, subdecname(c, f));
addtoken(head, itoa(countlocalvars(f->body->vardecs)));
LINEBLOCK* compilefundec(SCOPE* s, CLASS* c, SUBDEC* f) {
LINE* label = mkline(3);
addtoken(label, ezheapstr("function"));
addtoken(label, subdecname(c, f));
addtoken(label, itoa(countlocalvars(f->body->vardecs)));
label->next = NULL;
head->next = compilefunbody(s, c, f->body);
return head;
if(f->body->statements != NULL) {
LINEBLOCK* body = compilefunbody(s, c, f->body);
appendlnbefore(body, label);
return body;
}
else
return mklnblk(label);
}
LINE* compilesubdec(SCOPE* s, CLASS* c, SUBDEC* sd) {
LINEBLOCK* compilesubdec(SCOPE* s, CLASS* c, SUBDEC* sd) {
// 'this' and arguments are pushed by caller
// Must have a 'return' at the end
// Label names must have class name too (see mapping)
@ -499,24 +230,28 @@ LINE* compilesubdec(SCOPE* s, CLASS* c, SUBDEC* sd) {
return compilefundec(s, c, sd);
}
void compileclass(COMPILER* c, CLASS* class) {
LINEBLOCK* compileclass(COMPILER* c, CLASS* class) {
SCOPE* topscope = mkscope(c->globalscope);
addclassvardecs(topscope, class->vardecs);
addsubdecs(topscope, class->subdecs);
SUBDEC* current = class->subdecs;
while(current != NULL) {
compilesubdec(topscope, class, current);
current = current->next;
LINEBLOCK* output = NULL;
SUBDEC* curr = class->subdecs;
while(curr != NULL) {
output = mergelnblks(output, compilesubdec(topscope, class, curr));
curr = curr->next;
}
return output;
}
void compile(COMPILER* c) {
CLASS* current = c->globalscope->classes;
while(current != NULL) {
compileclass(c, current);
current = current->next;
LINEBLOCK* output = NULL;
CLASS* curr = c->globalscope->classes;
while(curr != NULL) {
output = mergelnblks(output, compileclass(c, curr));
curr = curr->next;
}
c->output = output;
}
COMPILER* mkcompiler(CLASS* classes) {

View File

@ -2,19 +2,12 @@
#define COMPILER_H
#include "util.h"
#include "parser.h"
typedef struct scope {
SUBDEC* subroutines;
CLASSVARDEC* classvardecs;
VARDEC* vardecs;
CLASS* classes;
struct scope* previous;
} SCOPE;
#include "vm-lines.h"
#include "compiler-scopes.h"
typedef struct {
SCOPE* globalscope;
LINE* output;
LINE* lastln;
LINEBLOCK* output;
} COMPILER;
COMPILER* mkcompiler(CLASS* classes);

18
main.c
View File

@ -2,26 +2,10 @@
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "tokenizer.h"
#include "printer.h"
#include "parser.h"
#include "compiler.h"
void println(LINE* ln) {
for(int i = 0; i < ln->tokenscount; i++) {
printf("%s", ln->tokens[i]);
if(i != ln->tokenscount-1)
printf(" ");
}
printf("\n");
}
void printcompiler(COMPILER* c) {
LINE* current = c->output;
while(current != NULL) {
println(current);
current = current->next;
}
printlns(c->output->head, stdout);
}
int main(int argc, char* argv[]) {

View File

@ -39,6 +39,13 @@ const char* tokentypes[] = {
"keyword", "identifier", "symbol", "integerConstant", "stringConstant"
};
DEBUGINFO* getdebug(PARSER* p) {
DEBUGINFO* d = (DEBUGINFO*)malloc(sizeof(DEBUGINFO));
d->file = p->file;
d->definedat = p->current->truen;
return d;
}
void next(PARSER* p) {
p->current = p->current->next;
}
@ -203,9 +210,7 @@ SUBROUTCALL* parsesubroutcall(PARSER* p) {
restorecp(p);
return NULL;
}
call->definedat = p->current->truen;
call->file = p->file;
call->debug = getdebug(p);
call->name = p->current->token;
next(p);
@ -377,8 +382,8 @@ void parsevardeccommon(PARSER* p, VARDEC* v) {
STRINGLIST* currstr = (STRINGLIST*)malloc(sizeof(STRINGLIST));
v->names = currstr;
v->file = p->file;
v->definedat = p->current->truen;
v->debug = getdebug(p);
v->names->content = parseidentifier(p);
while(!strcmp(p->current->token, ",")) {
@ -496,8 +501,7 @@ SUBDEC* parsesubroutdec(PARSER* p) {
subdec->type = parsetype(p, &dummy);
}
subdec->file = p->file;
subdec->definedat = p->current->truen;
subdec->debug = getdebug(p);
subdec->name = parseidentifier(p);
@ -530,8 +534,7 @@ CLASS* parseclass(PARSER* p) {
CLASS* class = (CLASS*)malloc(sizeof(CLASS));
class->definedat = p->current->truen;
class->file = p->file;
class->debug = getdebug(p);
class->name = parseidentifier(p);

View File

@ -2,10 +2,16 @@
#define PARSER_H
#include <stdbool.h>
#include "tokenizer.h"
#include "util.h"
struct statement;
struct explist;
typedef struct {
char* file;
int definedat;
} DEBUGINFO;
typedef enum {
ifstatement, whilestatement, letstatement, dostatement, returnstatement
} STATEMENTTYPE;
@ -17,9 +23,8 @@ typedef enum {
typedef struct {
char* parentname;
char* name;
char* file;
int definedat;
struct explist* parameters;
DEBUGINFO* debug;
} SUBROUTCALL;
typedef struct term {
@ -72,19 +77,13 @@ typedef enum {
stat, field
} VARCLASS;
typedef struct stringlist {
char* content;
struct stringlist* next;
} STRINGLIST;
typedef struct vardec {
char* file;
int definedat;
char* type;
bool primitive;
TOKENTYPE typeclass;
STRINGLIST* names;
struct vardec* next;
DEBUGINFO* debug;
} VARDEC;
typedef struct classvardec {
@ -109,14 +108,13 @@ typedef struct SUBROUTBODY {
} SUBROUTBODY;
typedef struct subdec {
char* file;
int definedat;
SUBROUTCLASS subroutclass;
char* type;
TOKENTYPE typeclass;
char* name;
PARAMETER* parameters;
SUBROUTBODY* body;
DEBUGINFO* debug;
struct subdec* next;
} SUBDEC;
@ -124,8 +122,7 @@ typedef struct cl {
char* name;
CLASSVARDEC* vardecs;
SUBDEC* subdecs;
char* file;
int definedat;
DEBUGINFO* debug;
struct cl* next;
} CLASS;

443
printer.c
View File

@ -1,443 +0,0 @@
#include "printer.h"
void printexpression(TERM* e, FILE* output, int depth);
void printstatements(STATEMENT* st, FILE* output, int depth);
const char* tmpvarclasses[] = {
"static", "field"
};
const int tmpvarclassessize = sizeof(tmpvarclasses) / sizeof(char*);
const char* tmpsubroutclasses[] = {
"constructor", "function", "method"
};
const int tmpsubroutclassessize = sizeof(tmpsubroutclasses) / sizeof(char*);
const char* tmptokentypes[] = {
"keyword", "identifier"
};
void printident(FILE* output, int depth) {
for(int i = 0; i < depth; i++)
fprintf(output, " ");
}
void printstringlist(FILE* output, int depth, STRINGLIST* ls) {
printident(output, depth);
fprintf(output, "<identifier> %s </identifier>\r\n", ls->content);
if(ls->next != NULL) {
printident(output, depth);
fprintf(output, "<symbol> , </symbol>\r\n");
printstringlist(output, depth, ls->next);
}
}
void printvardec(VARDEC* vd, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<%s> %s </%s>\r\n", tmptokentypes[vd->typeclass], vd->type, tmptokentypes[vd->typeclass]);
printstringlist(output, depth, vd->names);
printident(output, depth);
fprintf(output, "<symbol> ; </symbol>\r\n");
}
void printvardecs(VARDEC* vd, FILE* output, int depth) {
VARDEC* current = vd;
while(current != NULL) {
printident(output, depth);
fprintf(output, "<varDec>\r\n");
printident(output, depth+1);
fprintf(output, "<keyword> var </keyword>\r\n");
printvardec(current, output, depth+1);
current = current->next;
printident(output, depth);
fprintf(output, "</varDec>\r\n");
}
}
void printclassvardec(CLASSVARDEC* vd, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<keyword> %s </keyword>\r\n", tmpvarclasses[vd->varclass]);
printvardec(vd->base, output, depth);
}
void printclassvardecs(CLASSVARDEC* vd, FILE* output, int depth) {
CLASSVARDEC* current = vd;
while(current != NULL) {
printident(output, depth);
fprintf(output, "<classVarDec>\r\n");
printclassvardec(current, output, depth+1);
current = current->next;
printident(output, depth);
fprintf(output, "</classVarDec>\r\n");
}
}
void printparameter(PARAMETER* p, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<keyword> %s </keyword>\r\n", p->type);
printident(output, depth);
fprintf(output, "<identifier> %s </identifier>\r\n", p->name);
if(p->next != NULL) {
printident(output, depth);
fprintf(output, "<symbol> , </symbol>\r\n");
}
}
void printparameters(PARAMETER* p, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<parameterList>\r\n");
PARAMETER* current = p;
while(current != NULL) {
printparameter(current, output, depth+1);
current = current->next;
}
printident(output, depth);
fprintf(output, "</parameterList>\r\n");
}
void printexpressionlist(EXPRESSIONLIST* list, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<expressionList>\r\n");
if(list != NULL) {
EXPRESSIONLIST* current = list;
while(current != NULL) {
printexpression(current->expression, output, depth+1);
current = current->next;
if(current != NULL) {
printident(output, depth+1);
fprintf(output, "<symbol> , </symbol>\r\n");
}
}
}
printident(output, depth);
fprintf(output, "</expressionList>\r\n");
}
void printsubroutcall(SUBROUTCALL* c, FILE* output, int depth) {
if(c->parentname != NULL) {
printident(output, depth);
fprintf(output, "<identifier> %s </identifier>\r\n", c->parentname);
printident(output, depth);
fprintf(output, "<symbol> . </symbol>\r\n");
}
printident(output, depth);
fprintf(output, "<identifier> %s </identifier>\r\n", c->name);
printident(output, depth);
fprintf(output, "<symbol> ( </symbol>\r\n");
printexpressionlist(c->parameters, output, depth);
printident(output, depth);
fprintf(output, "<symbol> ) </symbol>\r\n");
}
void printterm(TERM* e, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<term>\r\n");
if(e->type == varname) {
printident(output, depth+1);
fprintf(output, "<identifier> %s </identifier>\r\n", e->string);
} else if(e->type == subroutcall) {
printsubroutcall(e->call, output, depth+1);
} else if(e->type == stringconstant) {
printident(output, depth+1);
fprintf(output, "<stringConstant> %s </stringConstant>\r\n", e->string);
} else if(e->type == keywordconstant) {
printident(output, depth+1);
fprintf(output, "<keyword> %s </keyword>\r\n", e->string);
} else if(e->type == intconstant) {
printident(output, depth+1);
fprintf(output, "<integerConstant> %i </integerConstant>\r\n", e->integer);
} else if(e->type == arrayitem) {
printident(output, depth+1);
fprintf(output, "<identifier> %s </identifier>\r\n", e->string);
printident(output, depth+1);
fprintf(output, "<symbol> [ </symbol>\r\n");
printexpression(e->arrayexp, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> ] </symbol>\r\n");
} else if(e->type == innerexpression) {
printident(output, depth+1);
fprintf(output, "<symbol> ( </symbol>\r\n");
printexpression(e->expression, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> ) </symbol>\r\n");
} else {
printident(output, depth+1);
fprintf(output, "<symbol> ~ </symbol>\r\n");
printterm(e->expression, output, depth+1);
}
printident(output, depth);
fprintf(output, "</term>\r\n");
if(e->next != NULL) {
printident(output, depth);
fprintf(output, "<symbol> %c </symbol>\r\n", e->op);
}
}
void printexpression(TERM* e, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<expression>\r\n");
TERM* current = e;
while(current != NULL) {
printterm(current, output, depth+1);
current = current->next;
}
printident(output, depth);
fprintf(output, "</expression>\r\n");
}
void printcond(CONDSTATEMENT* st, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<symbol> ( </symbol>\r\n");
printexpression(st->expression, output, depth);
printident(output, depth);
fprintf(output, "<symbol> ) </symbol>\r\n");
printident(output, depth);
fprintf(output, "<symbol> { </symbol>\r\n");
printstatements(st->statements, output, depth);
printident(output, depth);
fprintf(output, "<symbol> } </symbol>\r\n");
}
void printif(IFSTATEMENT* st, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<ifStatement>\r\n");
printident(output, depth+1);
fprintf(output, "<keyword> if </keyword>\r\n");
printcond(st->base, output, depth+1);
if(st->elsestatements != NULL) {
printident(output, depth+1);
fprintf(output, "<keyword> else </keyword>\r\n");
printident(output, depth+1);
fprintf(output, "<symbol> { </symbol>\r\n");
printstatements(st->elsestatements, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> } </symbol>\r\n");
}
printident(output, depth);
fprintf(output, "</ifStatement>\r\n");
}
void printwhile(CONDSTATEMENT* st, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<whileStatement>\r\n");
printident(output, depth+1);
fprintf(output, "<keyword> while </keyword>\r\n");
printcond(st, output, depth+1);
printident(output, depth);
fprintf(output, "</whileStatement>\r\n");
}
void printlet(LETSTATEMENT* st, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<letStatement>\r\n");
printident(output, depth+1);
fprintf(output, "<keyword> let </keyword>\r\n");
printident(output, depth+1);
fprintf(output, "<identifier> %s </identifier>\r\n", st->varname);
if(st->arrayind != NULL) {
printident(output, depth+1);
fprintf(output, "<symbol> [ </symbol>\r\n");
printexpression(st->arrayind, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> ] </symbol>\r\n");
}
printident(output, depth+1);
fprintf(output, "<symbol> = </symbol>\r\n");
printexpression(st->expression, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> ; </symbol>\r\n");
printident(output, depth);
fprintf(output, "</letStatement>\r\n");
}
void printdo(SUBROUTCALL* st, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<doStatement>\r\n");
printident(output, depth+1);
fprintf(output, "<keyword> do </keyword>\r\n");
printsubroutcall(st, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> ; </symbol>\r\n");
printident(output, depth);
fprintf(output, "</doStatement>\r\n");
}
void printreturn(TERM* st, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<returnStatement>\r\n");
printident(output, depth+1);
fprintf(output, "<keyword> return </keyword>\r\n");
if(st != NULL)
printexpression(st, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> ; </symbol>\r\n");
printident(output, depth);
fprintf(output, "</returnStatement>\r\n");
}
void printstatement(STATEMENT* st, FILE* output, int depth) {
if(st->type == ifstatement)
printif(st->ifst, output, depth);
else if(st->type == letstatement)
printlet(st->letst, output, depth);
else if(st->type == whilestatement)
printwhile(st->whilest, output, depth);
else if(st->type == dostatement)
printdo(st->dost, output, depth);
else
printreturn(st->retst, output, depth);
}
void printstatements(STATEMENT* st, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<statements>\r\n");
STATEMENT* current = st;
while(current != NULL) {
printstatement(current, output, depth+1);
current = current->next;
}
printident(output, depth);
fprintf(output, "</statements>\r\n");
}
void printsubroutbody(SUBROUTBODY* bd, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<subroutineBody>\r\n");
printident(output, depth+1);
fprintf(output, "<symbol> { </symbol>\r\n");
printvardecs(bd->vardecs, output, depth+1);
printstatements(bd->statements, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> } </symbol>\r\n");
printident(output, depth);
fprintf(output, "</subroutineBody>\r\n");
}
void printsubroutdec(SUBDEC* sd, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<keyword> %s </keyword>\r\n", tmpsubroutclasses[sd->subroutclass]);
printident(output, depth);
fprintf(output, "<%s> %s </%s>\r\n", tmptokentypes[sd->typeclass], sd->type, tmptokentypes[sd->typeclass]);
printident(output, depth);
fprintf(output, "<identifier> %s </identifier>\r\n", sd->name);
printident(output, depth);
fprintf(output, "<symbol> ( </symbol>\r\n");
printparameters(sd->parameters, output, depth);
printident(output, depth);
fprintf(output, "<symbol> ) </symbol>\r\n");
printsubroutbody(sd->body, output, depth);
}
void printsubroutdecs(SUBDEC* sd, FILE* output, int depth) {
SUBDEC* current = sd;
while(current != NULL) {
printident(output, depth);
fprintf(output, "<subroutineDec>\r\n");
printsubroutdec(current, output, depth+1);
current = current->next;
printident(output, depth);
fprintf(output, "</subroutineDec>\r\n");
}
}
void printclass(CLASS* c, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<class>\r\n");
printident(output, depth+1);
fprintf(output, "<keyword> class </keyword>\r\n");
printident(output, depth+1);
fprintf(output, "<identifier> %s </identifier>\r\n", c->name);
printident(output, depth+1);
fprintf(output, "<symbol> { </symbol>\r\n");
printclassvardecs(c->vardecs, output, depth+1);
printsubroutdecs(c->subdecs, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> } </symbol>\r\n");
printident(output, depth);
fprintf(output, "</class>\r\n");
}
void printparser(FILE* output, PARSER* p) {
printclass(p->output, output, 0);
}

View File

@ -1,7 +0,0 @@
#ifndef PRINTER_H
#define PRINTER_H
#include "parser.h"
void printparser(FILE* output, PARSER* p);
#endif

24
util.c
View File

@ -34,24 +34,16 @@ char* itoa(int i) {
return a;
}
void printlns(LINELIST* lns, FILE* stream) {
LINELIST* curln = lns;
while(curln != NULL) {
fprintf(stream, "%s\n", curln->content);
curln = curln->next;
void printstrlist(STRINGLIST* strlist, FILE* stream) {
while(strlist != NULL) {
fprintf(stream, "%s\n", strlist->content);
strlist = strlist->next;
}
}
void freelns(LINELIST* lns) {
LINELIST* next = lns->next;
free(lns);
void freestrlist(STRINGLIST* strlist) {
STRINGLIST* next = strlist->next;
free(strlist);
if(next != NULL)
freelns(next);
}
LINE* mkline(int count) {
LINE* l = (LINE*)malloc(sizeof(LINE));
l->tokenscount = 0;
l->tokens = (char**)malloc(sizeof(char*)*count);
return l;
freestrlist(next);
}

28
util.h
View File

@ -1,26 +1,20 @@
#ifndef UTIL_H
#define UTIL_H
#include <stdio.h>
/* util
* Random utilities. */
typedef struct stringlist {
char* content;
struct stringlist* next;
} STRINGLIST;
char* heapstr(char* str, int len);
char* ezheapstr(char* str);
int countplaces(int n);
typedef struct line {
char** tokens;
int tokenscount;
struct line* next;
} LINE;
typedef struct lnls {
char* content;
int truen;
struct lnls* next;
} LINELIST;
void printlns(LINELIST* lns, FILE* stream);
void freelns(LINELIST* lns);
LINE* mkline(int count);
char* itoa(int i);
void printstrlist(STRINGLIST* strlist, FILE* stream);
void freestrlist(STRINGLIST* strlist);
#endif

69
vm-lines.c Normal file
View File

@ -0,0 +1,69 @@
#include <stdlib.h>
#include "vm-lines.h"
LINE* mkline(int size) {
LINE* ln = (LINE*)malloc(sizeof(LINE));
ln->tokens = (char**)malloc(sizeof(char*)*size);
ln->count = 0;
return ln;
}
void addtoken(LINE* ln, char* token) {
ln->tokens[ln->count] = token;
ln->count++;
}
void println(LINE* ln, FILE* stream) {
for(int i = 0; i < ln->count; i++) {
fprintf(stream, "%s", ln->tokens[i]);
if(i + 1 < ln->count)
fprintf(stream, " ");
}
fprintf(stream, "\n");
}
void printlns(LINE* lns, FILE* stream) {
while(lns != NULL) {
println(lns, stream);
lns = lns->next;
}
}
void freeln(LINE* ln) {
for(int i = 0; i < ln->count; i++)
free(ln->tokens[i]);
free(ln);
}
void freelns(LINE* lns) {
LINE* next = lns->next;
freeln(lns);
if(next != NULL)
freelns(next);
}
LINEBLOCK* mklnblk(LINE* start) {
LINEBLOCK* blk = (LINEBLOCK*)malloc(sizeof(LINEBLOCK));
blk->head = start;
blk->tail = start;
return blk;
}
LINEBLOCK* mergelnblks(LINEBLOCK* head, LINEBLOCK* tail) {
if(head == NULL)
return tail;
head->tail->next = tail->head;
head->tail = tail->tail;
free(tail);
return head;
}
void appendln(LINEBLOCK* lnblk, LINE* ln) {
lnblk->tail->next = ln;
lnblk->tail = ln;
}
void appendlnbefore(LINEBLOCK* lnblk, LINE* ln) {
ln->next = lnblk->head;
lnblk->head = ln;
}

38
vm-lines.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef VM_LINES_H
#define VM_LINES_H
#include <stdio.h>
/* vm-lines
* Unified standard for the compiler's output and vm-translator's input.
* It is also used by vm-parser when reading .vm files. */
// Data types
typedef struct line {
char** tokens;
int count;
struct line* next;
} LINE;
typedef struct {
LINE* head;
LINE* tail;
} LINEBLOCK;
// Line manipulation
LINE* mkline(int size);
void addtoken(LINE* ln, char* token);
// Line printing
void println(LINE* ln, FILE* stream);
void printlns(LINE* lns, FILE* stream);
// Line freeing
void freeln(LINE* ln);
void freelns(LINE* lns);
// Line block manipulation
LINEBLOCK* mklnblk(LINE* start);
LINEBLOCK* mergelnblks(LINEBLOCK* head, LINEBLOCK* tail);
void appendln(LINEBLOCK* lnblk, LINE* ln);
void appendlnbefore(LINEBLOCK* lnblk, LINE* ln);
#endif