Improve compiling engine
This commit is contained in:
parent
6578c9d7eb
commit
b49d0f1868
|
@ -3,34 +3,34 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "compiler-scopes.h"
|
#include "compiler-scopes.h"
|
||||||
|
|
||||||
// Error messages
|
typedef enum { local, staticseg, arg, fieldseg } MEMSEGMENT;
|
||||||
void doubledeclaration(const char* name, OBJ* o1, OBJ* o2);
|
char* memsegnames[] = { "local", "static", "argument", "this" };
|
||||||
void ensurenoduplicate(SCOPE* s, OBJ* o);
|
|
||||||
|
|
||||||
// Generic getters
|
// Error messages
|
||||||
OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, const char** retname);
|
void doubledeclaration(const char* name, DEBUGINFO* d1, DEBUGINFO* d2);
|
||||||
OBJ* getbynamewithtype(SCOPE* s, const char* name, OBJTYPE type);
|
void ensurenoduplicate(SCOPE* s, char* name);
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
VAR* getvarinvars(VAR* vars, const char* name);
|
||||||
|
CLASS* getclass(SCOPE* s, const char* name);
|
||||||
|
SUBROUTDEC* getsubroutdecfromlist(SUBROUTDEC* start, char* name);
|
||||||
|
SUBROUTDEC* getmethod(SCOPE* s, VAR* parent, SUBROUTCALL* call);
|
||||||
|
SUBROUTDEC* getfunction(SCOPE* s, SUBROUTCALL* call);
|
||||||
|
SUBROUTDEC* getsubroutdecwithparent(SCOPE* s, SUBROUTCALL* call);
|
||||||
|
SUBROUTDEC* getsubroutdecwithoutparent(SCOPE* s, SUBROUTCALL* call);
|
||||||
|
SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name);
|
||||||
|
|
||||||
// Scope adding
|
// Scope adding
|
||||||
|
VAR* mkvar(char* type, char* name, bool primitive, DEBUGINFO* debug, MEMSEGMENT seg);
|
||||||
|
void addvar(SCOPE* s, VAR** dest, VAR* v);
|
||||||
|
void addlocalvar(SCOPE* s, VARDEC* v);
|
||||||
void addclassvardec(SCOPE* s, CLASSVARDEC* v);
|
void addclassvardec(SCOPE* s, CLASSVARDEC* v);
|
||||||
void addvardec(SCOPE* s, VARDEC* v);
|
void addparameter(SCOPE* s, PARAMETER* p);
|
||||||
void addsubroutdec(SCOPE* s, SUBROUTDEC* sd);
|
|
||||||
void addclass(SCOPE* s, CLASS* c);
|
|
||||||
|
|
||||||
// OBJ handling
|
|
||||||
|
|
||||||
VARDEC* tovardec(OBJ* obj) {
|
|
||||||
if (obj->type == classvardec)
|
|
||||||
return ((CLASSVARDEC*)(obj->pointer))->base;
|
|
||||||
else if (obj->type == vardec)
|
|
||||||
return (VARDEC*)(obj->pointer);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error messages
|
// Error messages
|
||||||
void doubledeclaration(const char* name, OBJ* o1, OBJ* o2) {
|
void doubledeclaration(const char* name, DEBUGINFO* d1, DEBUGINFO* d2) {
|
||||||
eprintf("Double declaration of '%s' at '%s', line %i; previously defined at '%s', line %i\n",
|
eprintf("Double declaration of '%s' at '%s', line %i; previously defined at '%s', line %i\n",
|
||||||
name, o1->debug->file, o1->debug->definedat, o2->debug->file, o2->debug->definedat);
|
name, d1->file, d1->definedat, d2->file, d2->definedat);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,158 +44,224 @@ void invalidparent(SUBROUTCALL* call) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ensurenoduplicate(SCOPE* s, OBJ* o) {
|
void ensurenoduplicate(SCOPE* s, char* name) {
|
||||||
const char* othername;
|
VAR* v = getvar(s, name);
|
||||||
OBJ* other = getbynamelist(s, o->names, &othername);
|
if(v != NULL)
|
||||||
if(other != NULL)
|
doubledeclaration(name, s->currdebug, v->debug);
|
||||||
doubledeclaration(othername, o, other);
|
|
||||||
|
CLASS* c = getclass(s, name);
|
||||||
|
if(c != NULL)
|
||||||
|
doubledeclaration(name, s->currdebug, c->debug);
|
||||||
|
|
||||||
|
SUBROUTDEC* sr = getsubroutdec(s, name);
|
||||||
|
if(sr != NULL)
|
||||||
|
doubledeclaration(name, s->currdebug, sr->debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scope handling
|
// Scope handling
|
||||||
|
|
||||||
SCOPE* mkscope(SCOPE* prev) {
|
SCOPE* mkscope(SCOPE* prev) {
|
||||||
SCOPE* s = (SCOPE*)malloc(sizeof(SCOPE));
|
SCOPE* s = (SCOPE*)malloc(sizeof(SCOPE));
|
||||||
s->objects = NULL;
|
|
||||||
s->previous = prev;
|
s->previous = prev;
|
||||||
s->condlabelcount = 0;
|
s->localvars = NULL;
|
||||||
|
s->fields = NULL;
|
||||||
|
s->staticvars = NULL;
|
||||||
|
s->parameters = NULL;
|
||||||
|
s->classes = NULL;
|
||||||
|
s->subroutines = NULL;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single type getters
|
// Getters
|
||||||
SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name) {
|
VAR* getvarinvars(VAR* vars, const char* name) {
|
||||||
return (SUBROUTDEC*)(getbynamewithtype(s, name, subroutdec)->pointer);
|
while(vars != NULL) {
|
||||||
|
if(!strcmp(vars->name, name))
|
||||||
|
return vars;
|
||||||
|
vars = vars->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VAR* getvar(SCOPE* s, const char* name) {
|
||||||
|
VAR* var = getvarinvars(s->localvars, name);
|
||||||
|
if(var != NULL)
|
||||||
|
return var;
|
||||||
|
var = getvarinvars(s->parameters, name);
|
||||||
|
if(var != NULL)
|
||||||
|
return var;
|
||||||
|
var = getvarinvars(s->fields, name);
|
||||||
|
if(var != NULL)
|
||||||
|
return var;
|
||||||
|
var = getvarinvars(s->staticvars, name);
|
||||||
|
if(var != NULL)
|
||||||
|
return var;
|
||||||
|
if(s->previous != NULL)
|
||||||
|
return getvar(s->previous, name);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CLASS* getclass(SCOPE* s, const char* name) {
|
CLASS* getclass(SCOPE* s, const char* name) {
|
||||||
return (CLASS*)(getbynamewithtype(s, name, class)->pointer);
|
CLASS* curr = s->classes;
|
||||||
}
|
|
||||||
|
|
||||||
SUBROUTDEC* getsubroutdecfromclass(CLASS* c, const char* name) {
|
|
||||||
SUBROUTDEC* curr = c->subroutdecs;
|
|
||||||
while(curr != NULL) {
|
while(curr != NULL) {
|
||||||
if(!strcmp(curr->name, name))
|
if(!strcmp(curr->name, name))
|
||||||
return curr;
|
return curr;
|
||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
}
|
}
|
||||||
|
if(s->previous != NULL)
|
||||||
|
return getclass(s->previous, name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBROUTDEC* getsubroutdecfromvar(SCOPE* s, OBJ* var, SUBROUTCALL* call) {
|
SUBROUTDEC* getsubroutdecfromlist(SUBROUTDEC* start, char* name) {
|
||||||
VARDEC* vd = tovardec(var);
|
while(start != NULL) {
|
||||||
if(vd == NULL || vd->primitive)
|
if(!strcmp(start->name, name))
|
||||||
invalidparent(call);
|
return start;
|
||||||
CLASS* c = getclass(s, vd->type);
|
start = start->next;
|
||||||
return getsubroutdecfromclass(c, call->name);
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBROUTDEC* getsubroutdecfromparent(SCOPE* s, SUBROUTCALL* call) {
|
SUBROUTDEC* getmethod(SCOPE* s, VAR* parent, SUBROUTCALL* call) {
|
||||||
SUBROUTDEC* sd;
|
CLASS* c = getclass(s, parent->type);
|
||||||
|
SUBROUTDEC* d = getsubroutdecfromlist(c->subroutdecs, call->name);
|
||||||
|
if(d == NULL)
|
||||||
|
notdeclared(call->name, call->debug);
|
||||||
|
if(d->subroutclass == function) {
|
||||||
|
eprintf("Calling a function as if it were a method; file '%s', line %i\n", call->debug->file, call->debug->definedat);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
OBJ* parent = getbyname(s, call->parentname);
|
SUBROUTDEC* getfunction(SCOPE* s, SUBROUTCALL* call) {
|
||||||
if(parent == NULL)
|
CLASS* c = getclass(s, call->parentname);
|
||||||
|
if(c == NULL)
|
||||||
notdeclared(call->parentname, call->debug);
|
notdeclared(call->parentname, call->debug);
|
||||||
|
SUBROUTDEC* d = getsubroutdecfromlist(c->subroutdecs, call->name);
|
||||||
|
if(d == NULL)
|
||||||
|
notdeclared(call->name, call->debug);
|
||||||
|
if(d->subroutclass == method) {
|
||||||
|
eprintf("Calling a method as if it were a function; file '%s', line %i\n", call->debug->file, call->debug->definedat);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
if(parent->type == class)
|
SUBROUTDEC* getsubroutdecwithparent(SCOPE* s, SUBROUTCALL* call) {
|
||||||
sd = getsubroutdecfromclass(parent->pointer, call->name);
|
VAR* parent = getvar(s, call->parentname);
|
||||||
else
|
if(parent != NULL)
|
||||||
sd = getsubroutdecfromvar(s, parent, call);
|
return getmethod(s, parent, call);
|
||||||
return sd;
|
else
|
||||||
|
return getfunction(s, call);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBROUTDEC* getsubroutdecwithoutparent(SCOPE* s, SUBROUTCALL* call) {
|
||||||
|
SUBROUTDEC* d = getsubroutdecfromlist(s->currclass->subroutdecs, call->name);
|
||||||
|
if(d == NULL)
|
||||||
|
notdeclared(call->name, call->debug);
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call) {
|
SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call) {
|
||||||
SUBROUTDEC* sd;
|
|
||||||
if(call->parentname != NULL)
|
if(call->parentname != NULL)
|
||||||
sd = getsubroutdecfromparent(s, call);
|
return getsubroutdecwithparent(s, call);
|
||||||
else
|
else
|
||||||
sd = getsubroutdec(s, call->name);
|
return getsubroutdecwithoutparent(s, call);
|
||||||
if(sd == NULL)
|
|
||||||
notdeclared(call->name, call->debug);
|
|
||||||
return sd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic getters
|
SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name) {
|
||||||
OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, const char** retname) {
|
SUBROUTDEC* curr = s->subroutines;
|
||||||
OBJ* curr = s->objects;
|
|
||||||
while(curr != NULL) {
|
while(curr != NULL) {
|
||||||
STRINGLIST* currn = curr->names;
|
if(!strcmp(curr->name, name))
|
||||||
while(currn != NULL) {
|
return curr;
|
||||||
STRINGLIST* currattempt = names;
|
|
||||||
while(currattempt != NULL) {
|
|
||||||
if(!strcmp(currn->content, currattempt->content)) {
|
|
||||||
*retname = currn->content;
|
|
||||||
return curr;
|
|
||||||
}
|
|
||||||
currattempt = currattempt->next;
|
|
||||||
}
|
|
||||||
currn = currn->next;
|
|
||||||
}
|
|
||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
}
|
}
|
||||||
if(s->previous != NULL)
|
if(s->previous != NULL)
|
||||||
return getbynamelist(s->previous, names, retname);
|
return getsubroutdec(s->previous, name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
OBJ* getbyname(SCOPE* s, const char* name) {
|
|
||||||
STRINGLIST* onename = onestr(name);
|
|
||||||
const char* dummy;
|
|
||||||
return getbynamelist(s, onename, &dummy);
|
|
||||||
}
|
|
||||||
|
|
||||||
OBJ* getbynamewithtype(SCOPE* s, const char* name, OBJTYPE type) {
|
|
||||||
OBJ* o = getbyname(s, name);
|
|
||||||
if(o->type != type)
|
|
||||||
notdeclared(name, o->debug);
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scope adding
|
// Scope adding
|
||||||
void addobj(SCOPE* s, OBJ* o) {
|
VAR* mkvar(char* type, char* name, bool primitive, DEBUGINFO* debug, MEMSEGMENT seg) {
|
||||||
ensurenoduplicate(s, o);
|
VAR* v = (VAR*)malloc(sizeof(VAR));
|
||||||
o->next = s->objects;
|
v->name = name;
|
||||||
s->objects = o;
|
v->type = type;
|
||||||
|
v->debug = debug;
|
||||||
|
v->memsegment = memsegnames[seg];
|
||||||
|
v->primitive = primitive;
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBJ* mkobj(void* pointer, OBJTYPE type, DEBUGINFO* debug, STRINGLIST* names) {
|
void addvar(SCOPE* s, VAR** dest, VAR* v) {
|
||||||
OBJ* o = (OBJ*)malloc(sizeof(OBJ));
|
ensurenoduplicate(s, v->name);
|
||||||
o->pointer = pointer;
|
|
||||||
o->type = type;
|
if(!v->primitive) {
|
||||||
o->debug = debug;
|
CLASS* type = getclass(s, v->type);
|
||||||
o->names = names;
|
if(type == NULL)
|
||||||
return o;
|
notdeclared(v->type, v->debug);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*dest == NULL)
|
||||||
|
v->index = 0;
|
||||||
|
else
|
||||||
|
v->index = 1+(*dest)->index;
|
||||||
|
|
||||||
|
v->next = *dest;
|
||||||
|
*dest = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addany(SCOPE* s, void* pointer, OBJTYPE type, DEBUGINFO* debug, STRINGLIST* names) {
|
void addlocalvar(SCOPE* s, VARDEC* v) {
|
||||||
addobj(s, mkobj(pointer, type, debug, names));
|
STRINGLIST* currname = v->names;
|
||||||
|
while(currname != NULL) {
|
||||||
|
addvar(s, &(s->localvars), mkvar(v->type, currname->content, v->primitive, v->debug, local));
|
||||||
|
currname = currname->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addclassvardecs(SCOPE* s, CLASSVARDEC* v) {
|
void addstaticvar(SCOPE* s, CLASSVARDEC* v) {
|
||||||
addany(s, v, classvardec, v->base->debug, v->base->names);
|
STRINGLIST* currname = v->base->names;
|
||||||
if(v->next != NULL)
|
while(currname != NULL) {
|
||||||
addclassvardecs(s, v->next);
|
addvar(s, &(s->staticvars), mkvar(v->base->type, currname->content, v->base->primitive, v->base->debug, staticseg));
|
||||||
|
currname = currname->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addvardecs(SCOPE* s, VARDEC* v) {
|
void addfield(SCOPE* s, CLASSVARDEC* v) {
|
||||||
addany(s, v, vardec, v->debug, v->names);
|
STRINGLIST* currname = v->base->names;
|
||||||
if(v->next != NULL)
|
while(currname != NULL) {
|
||||||
addvardecs(s, v->next);
|
addvar(s, &(s->fields), mkvar(v->base->type, currname->content, v->base->primitive, v->base->debug, fieldseg));
|
||||||
|
currname = currname->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addsubroutdecs(SCOPE* s, SUBROUTDEC* sd) {
|
void addclassvardec(SCOPE* s, CLASSVARDEC* v) {
|
||||||
addany(s, sd, subroutdec, sd->debug, onestr(sd->name));
|
if(v->type == staticseg)
|
||||||
if(sd->next != NULL)
|
addstaticvar(s, v);
|
||||||
addsubroutdecs(s, sd->next);
|
else
|
||||||
|
addfield(s, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addclasses(SCOPE* s, CLASS* c) {
|
void addparameter(SCOPE* s, PARAMETER* p) {
|
||||||
addany(s, c, class, c->debug, onestr(c->name));
|
addvar(s, &(s->parameters), mkvar(p->type, p->name, p->primitive, p->debug, arg));
|
||||||
if(c->next != NULL)
|
|
||||||
addclasses(s, c->next);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void addparameters(SCOPE* s, PARAMETER* p) {
|
// Group adding
|
||||||
addany(s, p, parameter, p->debug, onestr(p->name));
|
void addclassvardecs(SCOPE* s, CLASSVARDEC* classvardecs) {
|
||||||
if(p->next != NULL)
|
while(classvardecs != NULL) {
|
||||||
addparameters(s, p->next);
|
addclassvardec(s, classvardecs);
|
||||||
|
classvardecs = classvardecs->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addlocalvars(SCOPE* s, VARDEC* localvars) {
|
||||||
|
while(localvars != NULL) {
|
||||||
|
addlocalvar(s, localvars);
|
||||||
|
localvars = localvars->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addparameters(SCOPE* s, PARAMETER* params) {
|
||||||
|
while(params != NULL) {
|
||||||
|
addparameter(s, params);
|
||||||
|
params = params->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,39 +9,43 @@
|
||||||
* certain semantic rules. */
|
* certain semantic rules. */
|
||||||
|
|
||||||
// Data types
|
// Data types
|
||||||
typedef enum {
|
typedef struct var {
|
||||||
subroutdec, classvardec, vardec, class, parameter
|
|
||||||
} OBJTYPE;
|
|
||||||
|
|
||||||
typedef struct object {
|
|
||||||
void* pointer;
|
|
||||||
DEBUGINFO* debug;
|
DEBUGINFO* debug;
|
||||||
STRINGLIST* names;
|
char* memsegment;
|
||||||
OBJTYPE type;
|
char* type;
|
||||||
struct object* next;
|
char* name;
|
||||||
} OBJ;
|
int index;
|
||||||
|
bool primitive;
|
||||||
|
struct var* next;
|
||||||
|
} VAR;
|
||||||
|
|
||||||
typedef struct scope {
|
typedef struct scope {
|
||||||
OBJ* objects;
|
DEBUGINFO* currdebug;
|
||||||
int condlabelcount;
|
CLASS* currclass;
|
||||||
|
|
||||||
|
CLASS* classes;
|
||||||
|
SUBROUTDEC* subroutines;
|
||||||
|
|
||||||
|
VAR* fields;
|
||||||
|
VAR* staticvars;
|
||||||
|
VAR* localvars;
|
||||||
|
VAR* parameters;
|
||||||
|
|
||||||
struct scope* previous;
|
struct scope* previous;
|
||||||
} SCOPE;
|
} SCOPE;
|
||||||
|
|
||||||
// Group adding
|
// Group adding
|
||||||
void addclassvardecs(SCOPE* s, CLASSVARDEC* vs);
|
void addclassvardecs(SCOPE* s, CLASSVARDEC* classvardecs);
|
||||||
void addvardecs(SCOPE* s, VARDEC* vs);
|
void addlocalvars(SCOPE* s, VARDEC* localvars);
|
||||||
void addsubroutdecs(SCOPE* s, SUBROUTDEC* ss);
|
void addparameters(SCOPE* s, PARAMETER* params);
|
||||||
void addclasses(SCOPE* s, CLASS* c);
|
|
||||||
void addparameters(SCOPE* s, PARAMETER* p);
|
|
||||||
|
|
||||||
// Scope handling
|
// Scope handling
|
||||||
SCOPE* mkscope(SCOPE* prev);
|
SCOPE* mkscope(SCOPE* prev);
|
||||||
|
|
||||||
// Single type getters
|
// Single type getters
|
||||||
SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name);
|
|
||||||
SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call);
|
SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call);
|
||||||
CLASS* getclass(SCOPE* s, const char* name);
|
CLASS* getclass(SCOPE* s, const char* name);
|
||||||
|
|
||||||
// Generic getters
|
// Generic getters
|
||||||
OBJ* getbyname(SCOPE* s, const char* name);
|
VAR* getvar(SCOPE* s, const char* name);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
|
|
||||||
LINEBLOCK* compilestatements(SCOPE* s, CLASS* c, STATEMENT* sts);
|
LINEBLOCK* compilestatements(SCOPE* s, STATEMENT* sts);
|
||||||
|
LINEBLOCK* compilesubroutcall(SCOPE* s, SUBROUTCALL* call);
|
||||||
|
LINEBLOCK* compileexpression(SCOPE* s, TERM* e);
|
||||||
|
|
||||||
int countparameters(EXPRESSIONLIST* params) {
|
int countparameters(PARAMETER* params) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(params != NULL) {
|
while(params != NULL) {
|
||||||
i++;
|
i++;
|
||||||
|
@ -13,10 +15,23 @@ int countparameters(EXPRESSIONLIST* params) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int countexpressions(EXPRESSIONLIST* explist) {
|
||||||
|
int i = 0;
|
||||||
|
while(explist != NULL) {
|
||||||
|
i++;
|
||||||
|
explist = explist->next;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
int countlocalvars(VARDEC* decs) {
|
int countlocalvars(VARDEC* decs) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(decs != NULL) {
|
while(decs != NULL) {
|
||||||
i++;
|
STRINGLIST* curr = decs->names;
|
||||||
|
while(curr != NULL) {
|
||||||
|
i++;
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
decs = decs->next;
|
decs = decs->next;
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
|
@ -29,10 +44,11 @@ char* dotlabel(char* n1, char* n2) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* mkcondlabel(SCOPE* s) {
|
char* mkcondlabel(char* name, int count) {
|
||||||
char* label = dotlabel("cond-label", itoa(s->condlabelcount));
|
int sz = (strlen(name) + countplaces(count) + 1) * sizeof(char);
|
||||||
s->condlabelcount++;
|
char* result = (char*)malloc(sz);
|
||||||
return label;
|
sprintf(result, "%s%i", name, count);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
LINE* onetoken(char* str) {
|
LINE* onetoken(char* str) {
|
||||||
|
@ -75,50 +91,94 @@ LINE* mathopln(char op) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LINEBLOCK* compileexpression(SCOPE* s, TERM* e) {
|
LINEBLOCK* pushconstant(int n) {
|
||||||
LINEBLOCK* myblk;
|
char* tokens[] = { "push", "constant", itoa(n) };
|
||||||
LINEBLOCK* next = NULL;
|
return mklnblk(mksimpleln(tokens, strcount(tokens)));
|
||||||
|
|
||||||
if(e->type == intconstant) {
|
|
||||||
char* tokens[] = { "push", "constant", itoa(e->integer) };
|
|
||||||
myblk = mklnblk(mksimpleln(tokens, strcount(tokens)));
|
|
||||||
}
|
|
||||||
else if(e->type == unaryopterm) {
|
|
||||||
myblk = compileexpression(s, e->expression);
|
|
||||||
LINE* neg = onetoken("neg");
|
|
||||||
appendln(myblk, neg);
|
|
||||||
}
|
|
||||||
else if(e->type == innerexpression) {
|
|
||||||
myblk = compileexpression(s, e->expression);
|
|
||||||
}
|
|
||||||
else if(e->type == varname) {
|
|
||||||
eprintf("TO BE IMPLEMENTED\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
eprintf("Unsupported term yet %i\n", e->type);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(e->next != NULL) {
|
|
||||||
next = compileexpression(s, e->next);
|
|
||||||
appendln(next, mathopln(e->op));
|
|
||||||
myblk = mergelnblks(myblk, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
return myblk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LINEBLOCK* compileparameters(SCOPE* s, EXPRESSIONLIST* params) {
|
LINEBLOCK* pushunaryopterm(SCOPE* s, TERM* t) {
|
||||||
|
LINEBLOCK* blk = compileexpression(s, t->expression);
|
||||||
|
LINE* neg;
|
||||||
|
if(t->unaryop == '-')
|
||||||
|
neg = onetoken("neg");
|
||||||
|
else
|
||||||
|
neg = onetoken("not");
|
||||||
|
appendln(blk, neg);
|
||||||
|
return blk;
|
||||||
|
}
|
||||||
|
|
||||||
|
LINEBLOCK* opvar(SCOPE* s, char* op, const char* name) {
|
||||||
|
VAR* v = getvar(s, name);
|
||||||
|
char* tokens[] = { op, v->memsegment, itoa(v->index) };
|
||||||
|
return mklnblk(mksimpleln(tokens, strcount(tokens)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
LINEBLOCK* pushvar(SCOPE* s, const char* name) {
|
||||||
|
return opvar(s, "push", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
LINEBLOCK* popvar(SCOPE* s, const char* name) {
|
||||||
|
return opvar(s, "pop", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
LINEBLOCK* pushfalse() {
|
||||||
|
return pushconstant(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
LINEBLOCK* pushtrue() {
|
||||||
|
LINEBLOCK* blk = pushfalse();
|
||||||
|
appendln(blk, onetoken("not"));
|
||||||
|
return blk;
|
||||||
|
}
|
||||||
|
|
||||||
|
LINEBLOCK* compilekeywordconst(SCOPE* s, TERM* t) {
|
||||||
|
if(!strcmp(t->string, "true")) return pushtrue();
|
||||||
|
if(!strcmp(t->string, "false")) return pushfalse();
|
||||||
|
eprintf("Unsupported keyword '%s'\n", t->string);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
LINEBLOCK* compileterm(SCOPE* s, TERM* t) {
|
||||||
|
if(t->type == intconstant) return pushconstant(t->integer);
|
||||||
|
if(t->type == unaryopterm) return pushunaryopterm(s, t);
|
||||||
|
if(t->type == innerexpression) return compileexpression(s, t->expression);
|
||||||
|
if(t->type == varname) return pushvar(s, t->string);
|
||||||
|
if(t->type == subroutcall) return compilesubroutcall(s, t->call);
|
||||||
|
if(t->type == keywordconstant) return compilekeywordconst(s, t);
|
||||||
|
else {
|
||||||
|
eprintf("Unsupported term yet %i\n", t->type);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LINEBLOCK* compileexpression(SCOPE* s, TERM* e) {
|
||||||
|
LINEBLOCK* blk = compileterm(s, e);
|
||||||
|
TERM* curr = e->next;
|
||||||
|
if(curr != NULL) {
|
||||||
|
while(true) {
|
||||||
|
blk = mergelnblks(blk, compileterm(s, curr));
|
||||||
|
if(curr->next != NULL) {
|
||||||
|
appendln(blk, mathopln(curr->op));
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
appendln(blk, mathopln(e->op));
|
||||||
|
}
|
||||||
|
return blk;
|
||||||
|
}
|
||||||
|
|
||||||
|
LINEBLOCK* compileexplist(SCOPE* s, EXPRESSIONLIST* explist) {
|
||||||
LINEBLOCK* head = NULL;
|
LINEBLOCK* head = NULL;
|
||||||
while(params != NULL) {
|
while(explist != NULL) {
|
||||||
head = mergelnblks(head, compileexpression(s, params->expression));
|
head = mergelnblks(head, compileexpression(s, explist->expression));
|
||||||
params = params->next;
|
explist = explist->next;
|
||||||
}
|
}
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
LINEBLOCK* compilecallln(CLASS* c, SUBROUTCALL* call) {
|
LINEBLOCK* compilecallln(SCOPE* s, SUBROUTCALL* call) {
|
||||||
LINE* ln = mkline(3);
|
LINE* ln = mkline(3);
|
||||||
|
|
||||||
addtoken(ln, ezheapstr("call"));
|
addtoken(ln, ezheapstr("call"));
|
||||||
|
@ -126,24 +186,24 @@ LINEBLOCK* compilecallln(CLASS* c, SUBROUTCALL* call) {
|
||||||
if(call->parentname != NULL)
|
if(call->parentname != NULL)
|
||||||
addtoken(ln, dotlabel(call->parentname, call->name));
|
addtoken(ln, dotlabel(call->parentname, call->name));
|
||||||
else
|
else
|
||||||
addtoken(ln, dotlabel(c->name, call->name));
|
addtoken(ln, dotlabel(s->currclass->name, call->name));
|
||||||
|
|
||||||
addtoken(ln, itoa(countparameters(call->parameters)));
|
addtoken(ln, itoa(countexpressions(call->parameters)));
|
||||||
|
|
||||||
return mklnblk(ln);
|
return mklnblk(ln);
|
||||||
}
|
}
|
||||||
|
|
||||||
// temporary ignore list for OS functions
|
// temporary ignore list for OS functions
|
||||||
char* ignoresubroutdecs[] = {
|
char* ignoresubroutdecs[] = {
|
||||||
"printInt", "void", "peek", "int"
|
"printInt", "void", "peek", "int", "poke", "void"
|
||||||
};
|
};
|
||||||
int ignorecount = sizeof(ignoresubroutdecs) / sizeof(char*);
|
int ignorecount = sizeof(ignoresubroutdecs) / sizeof(char*);
|
||||||
|
|
||||||
LINEBLOCK* compilesubroutcall(SCOPE* s, CLASS* c, SUBROUTCALL* call) {
|
LINEBLOCK* compilesubroutcall(SCOPE* s, SUBROUTCALL* call) {
|
||||||
LINEBLOCK* block = compilecallln(c, call);
|
LINEBLOCK* blk = compilecallln(s, call);
|
||||||
|
|
||||||
if(call->parameters != NULL)
|
if(call->parameters != NULL)
|
||||||
block = mergelnblks(compileparameters(s, call->parameters), block);
|
blk = mergelnblks(compileexplist(s, call->parameters), blk);
|
||||||
|
|
||||||
// void functions always return 0
|
// void functions always return 0
|
||||||
// therefore must be thrown away
|
// therefore must be thrown away
|
||||||
|
@ -160,97 +220,117 @@ LINEBLOCK* compilesubroutcall(SCOPE* s, CLASS* c, SUBROUTCALL* call) {
|
||||||
type = getsubroutdecfromcall(s, call)->type;
|
type = getsubroutdecfromcall(s, call)->type;
|
||||||
if(!strcmp(type, "void")) {
|
if(!strcmp(type, "void")) {
|
||||||
char* tokens[] = { "pop", "temp", "0" };
|
char* tokens[] = { "pop", "temp", "0" };
|
||||||
appendln(block, mksimpleln(tokens, sizeof(tokens) / sizeof(char*)));
|
appendln(blk, mksimpleln(tokens, sizeof(tokens) / sizeof(char*)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return block;
|
return blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
LINEBLOCK* compileret(SCOPE* s, TERM* e) {
|
LINEBLOCK* compileret(SCOPE* s, TERM* e) {
|
||||||
LINE* ret = onetoken("return");
|
LINE* ret = onetoken("return");
|
||||||
LINEBLOCK* block = mklnblk(ret);
|
LINEBLOCK* blk = mklnblk(ret);
|
||||||
|
|
||||||
// void subroutdecs return 0
|
// void subroutdecs return 0
|
||||||
if(e == NULL) {
|
if(e == NULL) {
|
||||||
char* tokens[] = { "push", "constant", "0" };
|
char* tokens[] = { "push", "constant", "0" };
|
||||||
appendlnbefore(block, mksimpleln(tokens, strcount(tokens)));
|
appendlnbefore(blk, mksimpleln(tokens, strcount(tokens)));
|
||||||
} else
|
} else
|
||||||
block = mergelnblks(compileexpression(s, e), block);
|
blk = mergelnblks(compileexpression(s, e), blk);
|
||||||
|
|
||||||
return block;
|
return blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
LINEBLOCK* compileif(SCOPE* s, CLASS* c, IFSTATEMENT* st) {
|
LINEBLOCK* compileif(SCOPE* s, IFSTATEMENT* st) {
|
||||||
LINEBLOCK* block = compileexpression(s, st->base->expression);
|
LINEBLOCK* blk = compileexpression(s, st->base->expression);
|
||||||
appendln(block, onetoken("not"));
|
|
||||||
|
static int ifcount = 0;
|
||||||
|
int mycount = ifcount;
|
||||||
|
ifcount++;
|
||||||
|
|
||||||
char* label1 = mkcondlabel(s);
|
char* truelabel = mkcondlabel("IF_TRUE", mycount);
|
||||||
char* ifgoto[] = { "if-goto", label1 };
|
char* ifgoto[] = { "if-goto", truelabel };
|
||||||
appendln(block, mksimpleln(ifgoto, strcount(ifgoto)));
|
appendln(blk, mksimpleln(ifgoto, strcount(ifgoto)));
|
||||||
|
|
||||||
|
char* falselabel = mkcondlabel("IF_FALSE", mycount);
|
||||||
|
char* gotofalse[] = { "goto", falselabel };
|
||||||
|
appendln(blk, mksimpleln(gotofalse, strcount(gotofalse)));
|
||||||
|
|
||||||
block = mergelnblks(block, compilestatements(s, c, st->base->statements));
|
char* truelabelln[] = { "label", truelabel };
|
||||||
|
appendln(blk, mksimpleln(truelabelln, strcount(truelabelln)));
|
||||||
|
|
||||||
char* label2;
|
blk = mergelnblks(blk, compilestatements(s, st->base->statements));
|
||||||
|
|
||||||
|
char* endlabel;
|
||||||
bool haselse = st->elsestatements != NULL;
|
bool haselse = st->elsestatements != NULL;
|
||||||
if(haselse) {
|
if(haselse) {
|
||||||
char* label2 = mkcondlabel(s);
|
endlabel = mkcondlabel("IF_END", mycount);
|
||||||
char* gotoln[] = { "goto", label2 };
|
char* endgoto[] = { "goto", endlabel };
|
||||||
appendln(block, mksimpleln(gotoln, strcount(gotoln)));
|
appendln(blk, mksimpleln(endgoto, strcount(endgoto)));
|
||||||
}
|
}
|
||||||
|
|
||||||
char* label1ln[] = { "label", label1 };
|
char* falselabelln[] = { "label", falselabel};
|
||||||
appendln(block, mksimpleln(label1ln, strcount(label1ln)));
|
appendln(blk, mksimpleln(falselabelln, strcount(falselabelln)));
|
||||||
|
|
||||||
if(haselse) {
|
if(haselse) {
|
||||||
block = mergelnblks(block, compilestatements(s, c, st->elsestatements));
|
blk = mergelnblks(blk, compilestatements(s, st->elsestatements));
|
||||||
char* label2ln[] = { "label", label2 };
|
char* endlabelln[] = { "label", endlabel };
|
||||||
appendln(block, mksimpleln(label2ln, strcount(label2ln)));
|
appendln(blk, mksimpleln(endlabelln, strcount(endlabelln)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return block;
|
|
||||||
|
return blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
LINEBLOCK* compilewhile(SCOPE* s, CLASS* c, CONDSTATEMENT* w) {
|
LINEBLOCK* compilewhile(SCOPE* s, CONDSTATEMENT* w) {
|
||||||
LINEBLOCK* block = compileexpression(s, w->expression);
|
LINEBLOCK* blk = compileexpression(s, w->expression);
|
||||||
|
|
||||||
char* label1 = mkcondlabel(s);
|
static int whilecount = 0;
|
||||||
char* label1ln[] = { "label", label1 };
|
int mycount = whilecount;
|
||||||
appendlnbefore(block, mksimpleln(label1ln, strcount(label1ln)));
|
whilecount++;
|
||||||
|
|
||||||
appendln(block, onetoken("not"));
|
char* explabel = mkcondlabel("WHILE_EXP", mycount);
|
||||||
|
char* explabelln[] = { "label", explabel };
|
||||||
|
appendlnbefore(blk, mksimpleln(explabelln, strcount(explabelln)));
|
||||||
|
|
||||||
char* label2 = mkcondlabel(s);
|
appendln(blk, onetoken("not"));
|
||||||
char* ifgoto[] = { "if-goto", label2 };
|
|
||||||
appendln(block, mksimpleln(ifgoto, strcount(ifgoto)));
|
|
||||||
|
|
||||||
block = mergelnblks(block, compilestatements(s, c, w->statements));
|
char* endlabel = mkcondlabel("WHILE_END", mycount);
|
||||||
|
char* ifgoto[] = { "if-goto", endlabel };
|
||||||
|
appendln(blk, mksimpleln(ifgoto, strcount(ifgoto)));
|
||||||
|
|
||||||
char* gotoln[] = { "goto", label1 };
|
blk = mergelnblks(blk, compilestatements(s, w->statements));
|
||||||
appendln(block, mksimpleln(gotoln, strcount(gotoln)));
|
|
||||||
|
|
||||||
char* label2ln[] = { "label", label2 };
|
char* gotoln[] = { "goto", explabel };
|
||||||
appendln(block, mksimpleln(label2ln, strcount(label2ln)));
|
appendln(blk, mksimpleln(gotoln, strcount(gotoln)));
|
||||||
|
|
||||||
return block;
|
char* endlabelln[] = { "label", endlabel };
|
||||||
|
appendln(blk, mksimpleln(endlabelln, strcount(endlabelln)));
|
||||||
|
|
||||||
|
return blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
LINEBLOCK* compilelet(SCOPE* s, CLASS* c, LETSTATEMENT* l) {
|
LINEBLOCK* compilelet(SCOPE* s, LETSTATEMENT* l) {
|
||||||
|
// missing array ind
|
||||||
|
LINEBLOCK* blk = compileexpression(s, l->expression);
|
||||||
|
blk = mergelnblks(blk, popvar(s, l->varname));
|
||||||
|
return blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
LINEBLOCK* compilestatement(SCOPE* s, CLASS* c, STATEMENT* st) {
|
LINEBLOCK* compilestatement(SCOPE* s, STATEMENT* st) {
|
||||||
if(st->type == dostatement) return compilesubroutcall(s, c, st->dostatement);
|
s->currdebug = st->debug;
|
||||||
|
if(st->type == dostatement) return compilesubroutcall(s, st->dostatement);
|
||||||
if(st->type == returnstatement) return compileret(s, st->retstatement);
|
if(st->type == returnstatement) return compileret(s, st->retstatement);
|
||||||
if(st->type == ifstatement) return compileif(s, c, st->ifstatement);
|
if(st->type == ifstatement) return compileif(s, st->ifstatement);
|
||||||
if(st->type == whilestatement) return compilewhile(s, c, st->whilestatement);
|
if(st->type == whilestatement) return compilewhile(s, st->whilestatement);
|
||||||
if(st->type == letstatement) return compilelet(s, c, st->letstatement);
|
if(st->type == letstatement) return compilelet(s, st->letstatement);
|
||||||
eprintf("UNSUPPORTED type %i\n", st->type);
|
eprintf("UNSUPPORTED type %i\n", st->type);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
LINEBLOCK* compilestatements(SCOPE* s, CLASS* c, STATEMENT* sts) {
|
LINEBLOCK* compilestatements(SCOPE* s, STATEMENT* sts) {
|
||||||
LINEBLOCK* head = NULL;
|
LINEBLOCK* head = NULL;
|
||||||
while(sts != NULL) {
|
while(sts != NULL) {
|
||||||
head = mergelnblks(head, compilestatement(s, c, sts));
|
head = mergelnblks(head, compilestatement(s, sts));
|
||||||
sts = sts->next;
|
sts = sts->next;
|
||||||
}
|
}
|
||||||
return head;
|
return head;
|
||||||
|
@ -258,9 +338,10 @@ LINEBLOCK* compilestatements(SCOPE* s, CLASS* c, STATEMENT* sts) {
|
||||||
|
|
||||||
LINEBLOCK* compilefunbody(SCOPE* s, CLASS* c, SUBROUTBODY* b) {
|
LINEBLOCK* compilefunbody(SCOPE* s, CLASS* c, SUBROUTBODY* b) {
|
||||||
SCOPE* myscope = mkscope(s);
|
SCOPE* myscope = mkscope(s);
|
||||||
|
myscope->currclass = c;
|
||||||
if(b->vardecs != NULL)
|
if(b->vardecs != NULL)
|
||||||
addvardecs(s, b->vardecs);
|
addlocalvars(s, b->vardecs);
|
||||||
LINEBLOCK* head = compilestatements(myscope, c, b->statements);
|
LINEBLOCK* head = compilestatements(myscope, b->statements);
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,8 +368,11 @@ LINEBLOCK* compilesubroutdec(SCOPE* s, CLASS* c, SUBROUTDEC* sd) {
|
||||||
|
|
||||||
// types: method, function, constructor
|
// types: method, function, constructor
|
||||||
// must switch all of these
|
// must switch all of these
|
||||||
|
SCOPE* myscope = mkscope(s);
|
||||||
|
if(sd->parameters != NULL)
|
||||||
|
addparameters(myscope, sd->parameters);
|
||||||
if(sd->subroutclass == function)
|
if(sd->subroutclass == function)
|
||||||
return compilefundec(s, c, sd);
|
return compilefundec(myscope, c, sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
LINEBLOCK* compileclass(COMPILER* c, CLASS* class) {
|
LINEBLOCK* compileclass(COMPILER* c, CLASS* class) {
|
||||||
|
@ -296,7 +380,7 @@ LINEBLOCK* compileclass(COMPILER* c, CLASS* class) {
|
||||||
if(class->vardecs != NULL)
|
if(class->vardecs != NULL)
|
||||||
addclassvardecs(topscope, class->vardecs);
|
addclassvardecs(topscope, class->vardecs);
|
||||||
if(class->subroutdecs != NULL)
|
if(class->subroutdecs != NULL)
|
||||||
addsubroutdecs(topscope, class->subroutdecs);
|
topscope->subroutines = class->subroutdecs;
|
||||||
|
|
||||||
LINEBLOCK* output = NULL;
|
LINEBLOCK* output = NULL;
|
||||||
SUBROUTDEC* curr = class->subroutdecs;
|
SUBROUTDEC* curr = class->subroutdecs;
|
||||||
|
@ -320,7 +404,7 @@ void compile(COMPILER* c) {
|
||||||
COMPILER* mkcompiler(CLASS* classes) {
|
COMPILER* mkcompiler(CLASS* classes) {
|
||||||
COMPILER* c = (COMPILER*)malloc(sizeof(COMPILER));
|
COMPILER* c = (COMPILER*)malloc(sizeof(COMPILER));
|
||||||
c->globalscope = mkscope(NULL);
|
c->globalscope = mkscope(NULL);
|
||||||
addclasses(c->globalscope, classes);
|
c->globalscope->classes = classes;
|
||||||
c->classes = classes;
|
c->classes = classes;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ TERM* parsekeyword(PARSER* p) {
|
||||||
|
|
||||||
TERM* parseunaryopterm(PARSER* p) {
|
TERM* parseunaryopterm(PARSER* p) {
|
||||||
TERM* t = mkterm(unaryopterm);
|
TERM* t = mkterm(unaryopterm);
|
||||||
|
t->unaryop = p->current->token[0];
|
||||||
next(p);
|
next(p);
|
||||||
t->expression = parseterm(p);
|
t->expression = parseterm(p);
|
||||||
t->expression->next = NULL;
|
t->expression->next = NULL;
|
||||||
|
@ -92,7 +93,7 @@ TERM* parsecalltermnullified(PARSER* p) {
|
||||||
if(call == NULL)
|
if(call == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
TERM* t = mkterm(subroutcall);
|
TERM* t = mkterm(subroutcall);
|
||||||
t->call == call;
|
t->call = call;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "parser-internal.h"
|
#include "parser-internal.h"
|
||||||
#include "parser-statements.h"
|
#include "parser-statements.h"
|
||||||
|
|
||||||
STATEMENT* mkstatement(STATEMENTTYPE t);
|
STATEMENT* mkstatement(PARSER* p, STATEMENTTYPE t);
|
||||||
STATEMENT* parsestatementnullified(PARSER* p);
|
STATEMENT* parsestatementnullified(PARSER* p);
|
||||||
STATEMENT* parselet(PARSER* p);
|
STATEMENT* parselet(PARSER* p);
|
||||||
CONDSTATEMENT* parsecond(PARSER* p);
|
CONDSTATEMENT* parsecond(PARSER* p);
|
||||||
|
@ -12,9 +12,10 @@ STATEMENT* parsewhile(PARSER* p);
|
||||||
STATEMENT* parsedo(PARSER* p);
|
STATEMENT* parsedo(PARSER* p);
|
||||||
STATEMENT* parsereturn(PARSER* p);
|
STATEMENT* parsereturn(PARSER* p);
|
||||||
|
|
||||||
STATEMENT* mkstatement(STATEMENTTYPE t) {
|
STATEMENT* mkstatement(PARSER* p, STATEMENTTYPE t) {
|
||||||
STATEMENT* s = (STATEMENT*)malloc(sizeof(STATEMENT));
|
STATEMENT* s = (STATEMENT*)malloc(sizeof(STATEMENT));
|
||||||
s->type = t;
|
s->type = t;
|
||||||
|
s->debug = getdebug(p);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,8 +44,8 @@ STATEMENT* parsestatements(PARSER* p) {
|
||||||
|
|
||||||
STATEMENT* parselet(PARSER* p) {
|
STATEMENT* parselet(PARSER* p) {
|
||||||
next(p);
|
next(p);
|
||||||
STATEMENT* s = mkstatement(letstatement);
|
STATEMENT* s = mkstatement(p, letstatement);
|
||||||
LETSTATEMENT* letst= (LETSTATEMENT*)malloc(sizeof(LETSTATEMENT));
|
LETSTATEMENT* letst = (LETSTATEMENT*)malloc(sizeof(LETSTATEMENT));
|
||||||
|
|
||||||
letst->varname = parseidentifier(p);
|
letst->varname = parseidentifier(p);
|
||||||
|
|
||||||
|
@ -63,6 +64,7 @@ STATEMENT* parselet(PARSER* p) {
|
||||||
checkcontent(p, ";");
|
checkcontent(p, ";");
|
||||||
|
|
||||||
s->type = letstatement;
|
s->type = letstatement;
|
||||||
|
s->letstatement = letst;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +86,7 @@ CONDSTATEMENT* parsecond(PARSER* p) {
|
||||||
|
|
||||||
STATEMENT* parseif(PARSER* p) {
|
STATEMENT* parseif(PARSER* p) {
|
||||||
next(p);
|
next(p);
|
||||||
STATEMENT* s = mkstatement(ifstatement);
|
STATEMENT* s = mkstatement(p, ifstatement);
|
||||||
IFSTATEMENT* ifst = (IFSTATEMENT*)malloc(sizeof(IFSTATEMENT));
|
IFSTATEMENT* ifst = (IFSTATEMENT*)malloc(sizeof(IFSTATEMENT));
|
||||||
|
|
||||||
ifst->base = parsecond(p);
|
ifst->base = parsecond(p);
|
||||||
|
@ -99,12 +101,13 @@ STATEMENT* parseif(PARSER* p) {
|
||||||
ifst->elsestatements = NULL;
|
ifst->elsestatements = NULL;
|
||||||
|
|
||||||
s->type = ifstatement;
|
s->type = ifstatement;
|
||||||
|
s->ifstatement = ifst;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATEMENT* parsewhile(PARSER* p) {
|
STATEMENT* parsewhile(PARSER* p) {
|
||||||
next(p);
|
next(p);
|
||||||
STATEMENT* s = mkstatement(whilestatement);
|
STATEMENT* s = mkstatement(p, whilestatement);
|
||||||
|
|
||||||
s->whilestatement = parsecond(p);
|
s->whilestatement = parsecond(p);
|
||||||
return s;
|
return s;
|
||||||
|
@ -112,7 +115,7 @@ STATEMENT* parsewhile(PARSER* p) {
|
||||||
|
|
||||||
STATEMENT* parsedo(PARSER* p) {
|
STATEMENT* parsedo(PARSER* p) {
|
||||||
next(p);
|
next(p);
|
||||||
STATEMENT* s = mkstatement(dostatement);
|
STATEMENT* s = mkstatement(p, dostatement);
|
||||||
|
|
||||||
s->dostatement = parsesubroutcall(p);
|
s->dostatement = parsesubroutcall(p);
|
||||||
|
|
||||||
|
@ -122,7 +125,7 @@ STATEMENT* parsedo(PARSER* p) {
|
||||||
|
|
||||||
STATEMENT* parsereturn(PARSER* p) {
|
STATEMENT* parsereturn(PARSER* p) {
|
||||||
next(p);
|
next(p);
|
||||||
STATEMENT* s = mkstatement(returnstatement);
|
STATEMENT* s = mkstatement(p, returnstatement);
|
||||||
|
|
||||||
s->retstatement = parseexpressionnullified(p);
|
s->retstatement = parseexpressionnullified(p);
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ CLASS* parseclasses(PARSER* p) {
|
||||||
|
|
||||||
int parsepossibilities(PARSER* p, STRINGARRAY* poss) {
|
int parsepossibilities(PARSER* p, STRINGARRAY* poss) {
|
||||||
for(int i = 0; i < poss->size; i++)
|
for(int i = 0; i < poss->size; i++)
|
||||||
if(!strcmp(p->current->token, poss->items[i]))
|
if(equals(p, poss->items[i]))
|
||||||
return i;
|
return i;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -87,14 +87,9 @@ CLASSVARDEC* parseclassvardec(PARSER* p) {
|
||||||
|
|
||||||
CLASSVARDEC* parseclassvardecs(PARSER* p) {
|
CLASSVARDEC* parseclassvardecs(PARSER* p) {
|
||||||
CLASSVARDEC* head = parseclassvardec(p);
|
CLASSVARDEC* head = parseclassvardec(p);
|
||||||
if(head != NULL)
|
|
||||||
head->base->index = 0;
|
|
||||||
int index = 1;
|
|
||||||
CLASSVARDEC* curr = head;
|
CLASSVARDEC* curr = head;
|
||||||
CLASSVARDEC* nextc;
|
CLASSVARDEC* nextc;
|
||||||
while(nextc = parseclassvardec(p), nextc != NULL) {
|
while(nextc = parseclassvardec(p), nextc != NULL) {
|
||||||
nextc->base->index = index;
|
|
||||||
index++;
|
|
||||||
curr->next = nextc;
|
curr->next = nextc;
|
||||||
curr = nextc;
|
curr = nextc;
|
||||||
}
|
}
|
||||||
|
@ -156,6 +151,7 @@ PARAMETER* parseparameter(PARSER* p) {
|
||||||
if(equals(p, ")"))
|
if(equals(p, ")"))
|
||||||
return NULL;
|
return NULL;
|
||||||
param->debug = getdebug(p);
|
param->debug = getdebug(p);
|
||||||
|
param->primitive = isprimitive(p->current);
|
||||||
param->type = parsetype(p);
|
param->type = parsetype(p);
|
||||||
param->name = parseidentifier(p);
|
param->name = parseidentifier(p);
|
||||||
return param;
|
return param;
|
||||||
|
@ -163,9 +159,6 @@ PARAMETER* parseparameter(PARSER* p) {
|
||||||
|
|
||||||
PARAMETER* parseparameters(PARSER* p) {
|
PARAMETER* parseparameters(PARSER* p) {
|
||||||
PARAMETER* head = parseparameter(p);
|
PARAMETER* head = parseparameter(p);
|
||||||
if(head != NULL)
|
|
||||||
head->index = 0;
|
|
||||||
int index = 1;
|
|
||||||
PARAMETER* curr = head;
|
PARAMETER* curr = head;
|
||||||
PARAMETER* nextp;
|
PARAMETER* nextp;
|
||||||
while(equals(p, ",")) {
|
while(equals(p, ",")) {
|
||||||
|
@ -173,9 +166,7 @@ PARAMETER* parseparameters(PARSER* p) {
|
||||||
nextp = parseparameter(p);
|
nextp = parseparameter(p);
|
||||||
if(nextp == NULL)
|
if(nextp == NULL)
|
||||||
unexpected(p);
|
unexpected(p);
|
||||||
nextp->index = index;
|
|
||||||
curr->next = nextp;
|
curr->next = nextp;
|
||||||
index++;
|
|
||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
}
|
}
|
||||||
if(curr != NULL)
|
if(curr != NULL)
|
||||||
|
@ -199,7 +190,7 @@ bool isprimitive(TOKEN* tk) {
|
||||||
}
|
}
|
||||||
|
|
||||||
char* parsetype(PARSER* p) {
|
char* parsetype(PARSER* p) {
|
||||||
if(p->current->type != identifier)
|
if(p->current->type != identifier && p->current->type != keyword)
|
||||||
unexpected(p);
|
unexpected(p);
|
||||||
|
|
||||||
char* result = p->current->token;
|
char* result = p->current->token;
|
||||||
|
@ -246,15 +237,10 @@ VARDEC* parsevardec(PARSER* p) {
|
||||||
|
|
||||||
VARDEC* parsevardecs(PARSER* p) {
|
VARDEC* parsevardecs(PARSER* p) {
|
||||||
VARDEC* head = parsevardec(p);
|
VARDEC* head = parsevardec(p);
|
||||||
if(head != NULL)
|
|
||||||
head->index = 0;
|
|
||||||
int index = 1;
|
|
||||||
VARDEC* curr = head;
|
VARDEC* curr = head;
|
||||||
VARDEC* nextv;
|
VARDEC* nextv;
|
||||||
while(nextv = parsevardec(p), nextv != NULL) {
|
while(nextv = parsevardec(p), nextv != NULL) {
|
||||||
nextv->index = index;
|
curr->next = nextv;
|
||||||
index++;
|
|
||||||
curr->next = nextv;
|
|
||||||
curr = nextv;
|
curr = nextv;
|
||||||
}
|
}
|
||||||
if(curr != NULL)
|
if(curr != NULL)
|
||||||
|
|
|
@ -60,7 +60,7 @@ typedef struct subroutdec {
|
||||||
typedef struct parameter {
|
typedef struct parameter {
|
||||||
char* type;
|
char* type;
|
||||||
char* name;
|
char* name;
|
||||||
int index;
|
bool primitive;
|
||||||
DEBUGINFO* debug;
|
DEBUGINFO* debug;
|
||||||
struct parameter* next;
|
struct parameter* next;
|
||||||
} PARAMETER;
|
} PARAMETER;
|
||||||
|
@ -73,7 +73,6 @@ typedef struct subroutbody {
|
||||||
typedef struct vardec {
|
typedef struct vardec {
|
||||||
char* type;
|
char* type;
|
||||||
bool primitive;
|
bool primitive;
|
||||||
int index;
|
|
||||||
TOKENTYPE typeclass;
|
TOKENTYPE typeclass;
|
||||||
STRINGLIST* names;
|
STRINGLIST* names;
|
||||||
DEBUGINFO* debug;
|
DEBUGINFO* debug;
|
||||||
|
@ -94,6 +93,7 @@ typedef struct statement {
|
||||||
struct subroutcall* dostatement;
|
struct subroutcall* dostatement;
|
||||||
struct term* retstatement;
|
struct term* retstatement;
|
||||||
};
|
};
|
||||||
|
DEBUGINFO* debug;
|
||||||
struct statement* next;
|
struct statement* next;
|
||||||
} STATEMENT;
|
} STATEMENT;
|
||||||
|
|
||||||
|
@ -129,6 +129,7 @@ typedef struct term {
|
||||||
};
|
};
|
||||||
struct term* arrayexp;
|
struct term* arrayexp;
|
||||||
char op;
|
char op;
|
||||||
|
char unaryop;
|
||||||
struct term* next;
|
struct term* next;
|
||||||
} TERM;
|
} TERM;
|
||||||
|
|
||||||
|
|
2
util.h
2
util.h
|
@ -13,7 +13,7 @@
|
||||||
#define mkstrlist(name, array) STRINGARRAY name = { .items = array, .size = strcount(array) }
|
#define mkstrlist(name, array) STRINGARRAY name = { .items = array, .size = strcount(array) }
|
||||||
|
|
||||||
typedef struct stringlist {
|
typedef struct stringlist {
|
||||||
const char* content;
|
char* content;
|
||||||
struct stringlist* next;
|
struct stringlist* next;
|
||||||
} STRINGLIST;
|
} STRINGLIST;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue