Organize parse tree
This commit is contained in:
parent
c629a01b59
commit
bf61fcdd30
|
@ -26,7 +26,7 @@ OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, char** retname);
|
||||||
// Scope adding
|
// Scope adding
|
||||||
void addclassvardec(SCOPE* s, CLASSVARDEC* v);
|
void addclassvardec(SCOPE* s, CLASSVARDEC* v);
|
||||||
void addvardec(SCOPE* s, VARDEC* v);
|
void addvardec(SCOPE* s, VARDEC* v);
|
||||||
void addsubdec(SCOPE* s, SUBDEC* sd);
|
void addsubroutdec(SCOPE* s, SUBROUTDEC* sd);
|
||||||
void addclass(SCOPE* s, CLASS* c);
|
void addclass(SCOPE* s, CLASS* c);
|
||||||
|
|
||||||
// DEFINITIONS
|
// DEFINITIONS
|
||||||
|
@ -59,8 +59,8 @@ DEBUGINFO* getdebugvardec(OBJ* obj) {
|
||||||
return obj->vardec->debug;
|
return obj->vardec->debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUGINFO* getdebugsubdec(OBJ* obj) {
|
DEBUGINFO* getdebugsubroutdec(OBJ* obj) {
|
||||||
return obj->subdec->debug;
|
return obj->subroutdec->debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUGINFO* getdebugclass(OBJ* obj) {
|
DEBUGINFO* getdebugclass(OBJ* obj) {
|
||||||
|
@ -150,15 +150,15 @@ CLASSVARDEC* getclassvardec(SCOPE* s, char* name) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBDEC* getsubdec(SCOPE* s, char* name) {
|
SUBROUTDEC* getsubroutdec(SCOPE* s, char* name) {
|
||||||
SUBDEC* curr = s->subroutines;
|
SUBROUTDEC* curr = s->subroutines;
|
||||||
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)
|
if(s->previous != NULL)
|
||||||
return getsubdec(s->previous, name);
|
return getsubroutdec(s->previous, name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,8 +174,8 @@ CLASS* getclass(SCOPE* s, char* name) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBDEC* getsubdecfromclass(CLASS* c, char* name) {
|
SUBROUTDEC* getsubroutdecfromclass(CLASS* c, char* name) {
|
||||||
SUBDEC* curr = c->subdecs;
|
SUBROUTDEC* curr = c->subroutdecs;
|
||||||
while(curr != NULL) {
|
while(curr != NULL) {
|
||||||
if(!strcmp(curr->name, name))
|
if(!strcmp(curr->name, name))
|
||||||
return curr;
|
return curr;
|
||||||
|
@ -184,34 +184,34 @@ SUBDEC* getsubdecfromclass(CLASS* c, char* name) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBDEC* getsubdecfromvar(SCOPE* s, OBJ* var, SUBROUTCALL* call) {
|
SUBROUTDEC* getsubroutdecfromvar(SCOPE* s, OBJ* var, SUBROUTCALL* call) {
|
||||||
VARDEC* vd = tovardec(var);
|
VARDEC* vd = tovardec(var);
|
||||||
if(vd == NULL || vd->primitive)
|
if(vd == NULL || vd->primitive)
|
||||||
invalidparent(call);
|
invalidparent(call);
|
||||||
CLASS* c = getclass(s, vd->type);
|
CLASS* c = getclass(s, vd->type);
|
||||||
return getsubdecfromclass(c, call->name);
|
return getsubroutdecfromclass(c, call->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBDEC* getsubdecfromparent(SCOPE* s, SUBROUTCALL* call) {
|
SUBROUTDEC* getsubroutdecfromparent(SCOPE* s, SUBROUTCALL* call) {
|
||||||
SUBDEC* sd;
|
SUBROUTDEC* sd;
|
||||||
|
|
||||||
OBJ* parent = getbyname(s, call->parentname);
|
OBJ* parent = getbyname(s, call->parentname);
|
||||||
if(parent == NULL)
|
if(parent == NULL)
|
||||||
notdeclared(call->parentname, call->debug);
|
notdeclared(call->parentname, call->debug);
|
||||||
|
|
||||||
if(parent->type == class)
|
if(parent->type == class)
|
||||||
sd = getsubdecfromclass(parent->class, call->name);
|
sd = getsubroutdecfromclass(parent->class, call->name);
|
||||||
else
|
else
|
||||||
sd = getsubdecfromvar(s, parent, call);
|
sd = getsubroutdecfromvar(s, parent, call);
|
||||||
return sd;
|
return sd;
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBDEC* getsubdecfromcall(SCOPE* s, SUBROUTCALL* call) {
|
SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call) {
|
||||||
SUBDEC* sd;
|
SUBROUTDEC* sd;
|
||||||
if(call->parentname != NULL)
|
if(call->parentname != NULL)
|
||||||
sd = getsubdecfromparent(s, call);
|
sd = getsubroutdecfromparent(s, call);
|
||||||
else
|
else
|
||||||
sd = getsubdec(s, call->name);
|
sd = getsubroutdec(s, call->name);
|
||||||
if(sd == NULL)
|
if(sd == NULL)
|
||||||
notdeclared(call->name, call->debug);
|
notdeclared(call->name, call->debug);
|
||||||
return sd;
|
return sd;
|
||||||
|
@ -233,14 +233,14 @@ OBJ* getbyname(SCOPE* s, char* name) {
|
||||||
if(vd != NULL) {
|
if(vd != NULL) {
|
||||||
o->vardec = vd;
|
o->vardec = vd;
|
||||||
o->type = vardec;
|
o->type = vardec;
|
||||||
o->getdebug = getdebugsubdec;
|
o->getdebug = getdebugsubroutdec;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBDEC* sd = getsubdec(s, name);
|
SUBROUTDEC* sd = getsubroutdec(s, name);
|
||||||
if(sd != NULL) {
|
if(sd != NULL) {
|
||||||
o->subdec = sd;
|
o->subroutdec = sd;
|
||||||
o->type = subdec;
|
o->type = subroutdec;
|
||||||
o->getdebug = getdebugclassvardec;
|
o->getdebug = getdebugclassvardec;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
@ -286,9 +286,9 @@ void addvardec(SCOPE* s, VARDEC* v) {
|
||||||
s->vardecs = new;
|
s->vardecs = new;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addsubdec(SCOPE* s, SUBDEC* sd) {
|
void addsubroutdec(SCOPE* s, SUBROUTDEC* sd) {
|
||||||
ensurenoduplicate(s, sd->name, sd->debug);
|
ensurenoduplicate(s, sd->name, sd->debug);
|
||||||
SUBDEC* new = copy(sd, sizeof(SUBDEC));
|
SUBROUTDEC* new = copy(sd, sizeof(SUBROUTDEC));
|
||||||
new->next = s->subroutines;
|
new->next = s->subroutines;
|
||||||
s->subroutines = new;
|
s->subroutines = new;
|
||||||
}
|
}
|
||||||
|
@ -319,11 +319,11 @@ void addvardecs(SCOPE* s, VARDEC* vs) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addsubdecs(SCOPE* s, SUBDEC* ss) {
|
void addsubroutdecs(SCOPE* s, SUBROUTDEC* ss) {
|
||||||
SUBDEC* next;
|
SUBROUTDEC* next;
|
||||||
while(ss != NULL) {
|
while(ss != NULL) {
|
||||||
next = ss->next;
|
next = ss->next;
|
||||||
addsubdec(s, ss);
|
addsubroutdec(s, ss);
|
||||||
ss = next;
|
ss = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
// Data types
|
// Data types
|
||||||
typedef struct scope {
|
typedef struct scope {
|
||||||
SUBDEC* subroutines;
|
SUBROUTDEC* subroutines;
|
||||||
CLASSVARDEC* classvardecs;
|
CLASSVARDEC* classvardecs;
|
||||||
VARDEC* vardecs;
|
VARDEC* vardecs;
|
||||||
CLASS* classes;
|
CLASS* classes;
|
||||||
|
@ -18,13 +18,13 @@ typedef struct scope {
|
||||||
} SCOPE;
|
} SCOPE;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
subdec, classvardec, vardec, class
|
subroutdec, classvardec, vardec, class
|
||||||
} OBJTYPE;
|
} OBJTYPE;
|
||||||
|
|
||||||
typedef struct object {
|
typedef struct object {
|
||||||
OBJTYPE type;
|
OBJTYPE type;
|
||||||
union {
|
union {
|
||||||
SUBDEC* subdec;
|
SUBROUTDEC* subroutdec;
|
||||||
CLASSVARDEC* classvardec;
|
CLASSVARDEC* classvardec;
|
||||||
VARDEC* vardec;
|
VARDEC* vardec;
|
||||||
CLASS* class;
|
CLASS* class;
|
||||||
|
@ -35,15 +35,15 @@ typedef struct object {
|
||||||
// Group adding
|
// Group adding
|
||||||
void addclassvardecs(SCOPE* s, CLASSVARDEC* vs);
|
void addclassvardecs(SCOPE* s, CLASSVARDEC* vs);
|
||||||
void addvardecs(SCOPE* s, VARDEC* vs);
|
void addvardecs(SCOPE* s, VARDEC* vs);
|
||||||
void addsubdecs(SCOPE* s, SUBDEC* ss);
|
void addsubroutdecs(SCOPE* s, SUBROUTDEC* ss);
|
||||||
void addclasses(SCOPE* s, CLASS* c);
|
void addclasses(SCOPE* s, CLASS* c);
|
||||||
|
|
||||||
// Scope handling
|
// Scope handling
|
||||||
SCOPE* mkscope(SCOPE* prev);
|
SCOPE* mkscope(SCOPE* prev);
|
||||||
|
|
||||||
// Single type getters
|
// Single type getters
|
||||||
SUBDEC* getsubdec(SCOPE* s, char* name);
|
SUBROUTDEC* getsubroutdec(SCOPE* s, char* name);
|
||||||
SUBDEC* getsubdecfromcall(SCOPE* s, SUBROUTCALL* call);
|
SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call);
|
||||||
CLASS* getclass(SCOPE* s, char* name);
|
CLASS* getclass(SCOPE* s, char* name);
|
||||||
|
|
||||||
// Generic getters
|
// Generic getters
|
||||||
|
|
30
compiler.c
30
compiler.c
|
@ -27,7 +27,7 @@ char* dotlabel(char* n1, char* n2) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* subdecname(CLASS* c, SUBDEC* sd) {
|
char* subroutdecname(CLASS* c, SUBROUTDEC* sd) {
|
||||||
return dotlabel(c->name, sd->name);
|
return dotlabel(c->name, sd->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,10 +126,10 @@ LINEBLOCK* compilecallln(CLASS* c, SUBROUTCALL* call) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// temporary ignore list for OS functions
|
// temporary ignore list for OS functions
|
||||||
char* ignoresubdecs[] = {
|
char* ignoresubroutdecs[] = {
|
||||||
"printInt", "void", "peek", "int"
|
"printInt", "void", "peek", "int"
|
||||||
};
|
};
|
||||||
int ignorecount = sizeof(ignoresubdecs) / sizeof(char*);
|
int ignorecount = sizeof(ignoresubroutdecs) / sizeof(char*);
|
||||||
|
|
||||||
LINEBLOCK* compilesubroutcall(SCOPE* s, CLASS* c, SUBROUTCALL* call) {
|
LINEBLOCK* compilesubroutcall(SCOPE* s, CLASS* c, SUBROUTCALL* call) {
|
||||||
LINEBLOCK* block = compilecallln(c, call);
|
LINEBLOCK* block = compilecallln(c, call);
|
||||||
|
@ -143,13 +143,13 @@ LINEBLOCK* compilesubroutcall(SCOPE* s, CLASS* c, SUBROUTCALL* call) {
|
||||||
// gambiarra
|
// gambiarra
|
||||||
char* type = NULL;
|
char* type = NULL;
|
||||||
for(int i = 0; i < ignorecount; i += 2) {
|
for(int i = 0; i < ignorecount; i += 2) {
|
||||||
if(!strcmp(call->name, ignoresubdecs[i])) {
|
if(!strcmp(call->name, ignoresubroutdecs[i])) {
|
||||||
type = ignoresubdecs[i+1];
|
type = ignoresubroutdecs[i+1];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(type == NULL)
|
if(type == NULL)
|
||||||
type = getsubdecfromcall(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(block, mksimpleln(tokens, sizeof(tokens) / sizeof(char*)));
|
||||||
|
@ -162,7 +162,7 @@ LINEBLOCK* compileret(SCOPE* s, TERM* e) {
|
||||||
LINE* ret = onetoken("return");
|
LINE* ret = onetoken("return");
|
||||||
LINEBLOCK* block = mklnblk(ret);
|
LINEBLOCK* block = mklnblk(ret);
|
||||||
|
|
||||||
// void subdecs 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, sizeof(tokens) / sizeof(char*)));
|
appendlnbefore(block, mksimpleln(tokens, sizeof(tokens) / sizeof(char*)));
|
||||||
|
@ -174,9 +174,9 @@ LINEBLOCK* compileret(SCOPE* s, TERM* e) {
|
||||||
|
|
||||||
LINEBLOCK* compilestatement(SCOPE* s, CLASS* c, STATEMENT* st) {
|
LINEBLOCK* compilestatement(SCOPE* s, CLASS* c, STATEMENT* st) {
|
||||||
if(st->type == dostatement)
|
if(st->type == dostatement)
|
||||||
return compilesubroutcall(s, c, st->dost);
|
return compilesubroutcall(s, c, st->dostatement);
|
||||||
else if(st->type == returnstatement)
|
else if(st->type == returnstatement)
|
||||||
return compileret(s, st->retst);
|
return compileret(s, st->retstatement);
|
||||||
else {
|
else {
|
||||||
eprintf("UNSUPPORTED\n");
|
eprintf("UNSUPPORTED\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -198,10 +198,10 @@ LINEBLOCK* compilefunbody(SCOPE* s, CLASS* c, SUBROUTBODY* b) {
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
LINEBLOCK* compilefundec(SCOPE* s, CLASS* c, SUBDEC* f) {
|
LINEBLOCK* compilefundec(SCOPE* s, CLASS* c, SUBROUTDEC* f) {
|
||||||
LINE* label = mkline(3);
|
LINE* label = mkline(3);
|
||||||
addtoken(label, ezheapstr("function"));
|
addtoken(label, ezheapstr("function"));
|
||||||
addtoken(label, subdecname(c, f));
|
addtoken(label, subroutdecname(c, f));
|
||||||
addtoken(label, itoa(countlocalvars(f->body->vardecs)));
|
addtoken(label, itoa(countlocalvars(f->body->vardecs)));
|
||||||
label->next = NULL;
|
label->next = NULL;
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ LINEBLOCK* compilefundec(SCOPE* s, CLASS* c, SUBDEC* f) {
|
||||||
return mklnblk(label);
|
return mklnblk(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
LINEBLOCK* compilesubdec(SCOPE* s, CLASS* c, SUBDEC* sd) {
|
LINEBLOCK* compilesubroutdec(SCOPE* s, CLASS* c, SUBROUTDEC* sd) {
|
||||||
// 'this' and arguments are pushed by caller
|
// 'this' and arguments are pushed by caller
|
||||||
// Must have a 'return' at the end
|
// Must have a 'return' at the end
|
||||||
// Label names must have class name too (see mapping)
|
// Label names must have class name too (see mapping)
|
||||||
|
@ -228,12 +228,12 @@ LINEBLOCK* compilesubdec(SCOPE* s, CLASS* c, SUBDEC* sd) {
|
||||||
LINEBLOCK* compileclass(COMPILER* c, CLASS* class) {
|
LINEBLOCK* compileclass(COMPILER* c, CLASS* class) {
|
||||||
SCOPE* topscope = mkscope(c->globalscope);
|
SCOPE* topscope = mkscope(c->globalscope);
|
||||||
addclassvardecs(topscope, class->vardecs);
|
addclassvardecs(topscope, class->vardecs);
|
||||||
addsubdecs(topscope, class->subdecs);
|
addsubroutdecs(topscope, class->subroutdecs);
|
||||||
|
|
||||||
LINEBLOCK* output = NULL;
|
LINEBLOCK* output = NULL;
|
||||||
SUBDEC* curr = class->subdecs;
|
SUBROUTDEC* curr = class->subroutdecs;
|
||||||
while(curr != NULL) {
|
while(curr != NULL) {
|
||||||
output = mergelnblks(output, compilesubdec(topscope, class, curr));
|
output = mergelnblks(output, compilesubroutdec(topscope, class, curr));
|
||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
#ifndef PARSER_TREE_H
|
||||||
|
#define PARSER_TREE_H
|
||||||
|
#include "tokenizer.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
struct classvardec;
|
||||||
|
struct parameter;
|
||||||
|
struct subroutbody;
|
||||||
|
struct subroutdec;
|
||||||
|
struct vardec;
|
||||||
|
struct letstatement;
|
||||||
|
struct ifstatement;
|
||||||
|
struct condstatement;
|
||||||
|
struct subroutcall;
|
||||||
|
struct term;
|
||||||
|
struct expressionlist;
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
typedef struct {
|
||||||
|
char* file;
|
||||||
|
int definedat;
|
||||||
|
} DEBUGINFO;
|
||||||
|
|
||||||
|
// Program structure
|
||||||
|
|
||||||
|
typedef struct class {
|
||||||
|
char* name;
|
||||||
|
struct classvardec* vardecs;
|
||||||
|
struct subroutdec* subroutdecs;
|
||||||
|
DEBUGINFO* debug;
|
||||||
|
struct class* next;
|
||||||
|
} CLASS;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
stat, field
|
||||||
|
} CLASSVARTYPE;
|
||||||
|
|
||||||
|
typedef struct classvardec {
|
||||||
|
CLASSVARTYPE type;
|
||||||
|
struct vardec* base;
|
||||||
|
struct classvardec* next;
|
||||||
|
} CLASSVARDEC;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
constructor, function, method
|
||||||
|
} SUBROUTCLASS;
|
||||||
|
|
||||||
|
typedef struct subroutdec {
|
||||||
|
SUBROUTCLASS subroutclass;
|
||||||
|
char* type;
|
||||||
|
TOKENTYPE typeclass;
|
||||||
|
char* name;
|
||||||
|
struct parameter* parameters;
|
||||||
|
struct subroutbody* body;
|
||||||
|
DEBUGINFO* debug;
|
||||||
|
struct subroutdec* next;
|
||||||
|
} SUBROUTDEC;
|
||||||
|
|
||||||
|
typedef struct parameter {
|
||||||
|
char* type;
|
||||||
|
char* name;
|
||||||
|
struct parameter* next;
|
||||||
|
} PARAMETER;
|
||||||
|
|
||||||
|
typedef struct subroutbody {
|
||||||
|
struct vardec* vardecs;
|
||||||
|
struct statement* statements;
|
||||||
|
} SUBROUTBODY;
|
||||||
|
|
||||||
|
typedef struct vardec {
|
||||||
|
char* type;
|
||||||
|
bool primitive;
|
||||||
|
TOKENTYPE typeclass;
|
||||||
|
STRINGLIST* names;
|
||||||
|
struct vardec* next;
|
||||||
|
DEBUGINFO* debug;
|
||||||
|
} VARDEC;
|
||||||
|
|
||||||
|
// Statements
|
||||||
|
typedef enum {
|
||||||
|
ifstatement, whilestatement, letstatement, dostatement, returnstatement
|
||||||
|
} STATEMENTTYPE;
|
||||||
|
|
||||||
|
typedef struct statement {
|
||||||
|
STATEMENTTYPE type;
|
||||||
|
union {
|
||||||
|
struct letstatement* letstatement;
|
||||||
|
struct ifstatement* ifstatement;
|
||||||
|
struct condstatement* whilestatement;
|
||||||
|
struct subroutcall* dostatement;
|
||||||
|
struct term* retstatement;
|
||||||
|
};
|
||||||
|
struct statement* next;
|
||||||
|
} STATEMENT;
|
||||||
|
|
||||||
|
typedef struct letstatement {
|
||||||
|
char* varname;
|
||||||
|
struct term* arrayind;
|
||||||
|
struct term* expression;
|
||||||
|
} LETSTATEMENT;
|
||||||
|
|
||||||
|
typedef struct ifstatement {
|
||||||
|
struct condstatement* base;
|
||||||
|
struct statement* elsestatements;
|
||||||
|
} IFSTATEMENT;
|
||||||
|
|
||||||
|
typedef struct condstatement {
|
||||||
|
struct term* expression;
|
||||||
|
struct statement* statements;
|
||||||
|
} CONDSTATEMENT;
|
||||||
|
|
||||||
|
// Expressions
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
varname, intconstant, stringconstant, keywordconstant, arrayitem, subroutcall, innerexpression, unaryopterm
|
||||||
|
} TERMTYPE;
|
||||||
|
|
||||||
|
typedef struct term {
|
||||||
|
TERMTYPE type;
|
||||||
|
union {
|
||||||
|
char* string;
|
||||||
|
int integer;
|
||||||
|
struct subroutcall* call;
|
||||||
|
struct term* expression;
|
||||||
|
};
|
||||||
|
struct term* arrayexp;
|
||||||
|
char op;
|
||||||
|
struct term* next;
|
||||||
|
} TERM;
|
||||||
|
|
||||||
|
typedef struct subroutcall {
|
||||||
|
char* parentname;
|
||||||
|
char* name;
|
||||||
|
struct expressionlist* parameters;
|
||||||
|
DEBUGINFO* debug;
|
||||||
|
} SUBROUTCALL;
|
||||||
|
|
||||||
|
typedef struct expressionlist {
|
||||||
|
TERM* expression;
|
||||||
|
struct expressionlist* next;
|
||||||
|
} EXPRESSIONLIST;
|
||||||
|
|
||||||
|
#endif
|
58
parser.c
58
parser.c
|
@ -20,10 +20,10 @@ const char* ops[] = {
|
||||||
};
|
};
|
||||||
const int opssize = sizeof(ops) / sizeof(char*);
|
const int opssize = sizeof(ops) / sizeof(char*);
|
||||||
|
|
||||||
const char* varclasses[] = {
|
const char* classvartypes[] = {
|
||||||
"static", "field"
|
"static", "field"
|
||||||
};
|
};
|
||||||
const int varclassessize = sizeof(varclasses) / sizeof(char*);
|
const int classvartypessize = sizeof(classvartypes) / sizeof(char*);
|
||||||
|
|
||||||
const char* vardectypes[] = {
|
const char* vardectypes[] = {
|
||||||
"int", "char", "boolean"
|
"int", "char", "boolean"
|
||||||
|
@ -290,29 +290,29 @@ STATEMENT* parsestatement(PARSER* p) {
|
||||||
if(!strcmp(p->current->token, "let")) {
|
if(!strcmp(p->current->token, "let")) {
|
||||||
next(p);
|
next(p);
|
||||||
st->type = letstatement;
|
st->type = letstatement;
|
||||||
st->letst = parselet(p);
|
st->letstatement = parselet(p);
|
||||||
} else if(!strcmp(p->current->token, "if")) {
|
} else if(!strcmp(p->current->token, "if")) {
|
||||||
next(p);
|
next(p);
|
||||||
st->type = ifstatement;
|
st->type = ifstatement;
|
||||||
st->ifst = parseif(p);
|
st->ifstatement = parseif(p);
|
||||||
} else if(!strcmp(p->current->token, "while")) {
|
} else if(!strcmp(p->current->token, "while")) {
|
||||||
next(p);
|
next(p);
|
||||||
st->type = whilestatement;
|
st->type = whilestatement;
|
||||||
st->whilest = parsecond(p);
|
st->whilestatement = parsecond(p);
|
||||||
} else if(!strcmp(p->current->token, "do")) {
|
} else if(!strcmp(p->current->token, "do")) {
|
||||||
next(p);
|
next(p);
|
||||||
st->type = dostatement;
|
st->type = dostatement;
|
||||||
st->dost = parsesubroutcall(p);
|
st->dostatement = parsesubroutcall(p);
|
||||||
checkcontent(p, ";");
|
checkcontent(p, ";");
|
||||||
} else if(!strcmp(p->current->token, "return")) {
|
} else if(!strcmp(p->current->token, "return")) {
|
||||||
next(p);
|
next(p);
|
||||||
st->type = returnstatement;
|
st->type = returnstatement;
|
||||||
if(strcmp(p->current->token, ";")) {
|
if(strcmp(p->current->token, ";")) {
|
||||||
st->retst = parseexpressionnullified(p);
|
st->retstatement = parseexpressionnullified(p);
|
||||||
checkcontent(p, ";");
|
checkcontent(p, ";");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
st->retst = NULL;
|
st->retstatement = NULL;
|
||||||
next(p);
|
next(p);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -361,8 +361,8 @@ int parsepossibilities(PARSER* p, const char** strings, int sz) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
VARCLASS parsevarclass(PARSER* p) {
|
CLASSVARTYPE parseclassvartype(PARSER* p) {
|
||||||
return parsepossibilities(p, varclasses, varclassessize);
|
return parsepossibilities(p, classvartypes, classvartypessize);
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBROUTCLASS parsesubroutclass(PARSER* p) {
|
SUBROUTCLASS parsesubroutclass(PARSER* p) {
|
||||||
|
@ -400,13 +400,13 @@ void parsevardeccommon(PARSER* p, VARDEC* v) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CLASSVARDEC* parseclassvardec(PARSER* p) {
|
CLASSVARDEC* parseclassvardec(PARSER* p) {
|
||||||
VARCLASS varclass = parsevarclass(p);
|
CLASSVARTYPE classvartype = parseclassvartype(p);
|
||||||
if(varclass == -1)
|
if(classvartype == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
next(p);
|
next(p);
|
||||||
|
|
||||||
CLASSVARDEC* classvardec = (CLASSVARDEC*)malloc(sizeof(CLASSVARDEC));
|
CLASSVARDEC* classvardec = (CLASSVARDEC*)malloc(sizeof(CLASSVARDEC));
|
||||||
classvardec->varclass = varclass;
|
classvardec->type = classvartype;
|
||||||
|
|
||||||
classvardec->base = (VARDEC*)malloc(sizeof(VARDEC));
|
classvardec->base = (VARDEC*)malloc(sizeof(VARDEC));
|
||||||
|
|
||||||
|
@ -484,44 +484,44 @@ SUBROUTBODY* parsesubroutbody(PARSER* p) {
|
||||||
return subroutbody;
|
return subroutbody;
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBDEC* parsesubroutdec(PARSER* p) {
|
SUBROUTDEC* parsesubroutdec(PARSER* p) {
|
||||||
SUBROUTCLASS subroutclass = parsesubroutclass(p);
|
SUBROUTCLASS subroutclass = parsesubroutclass(p);
|
||||||
if(subroutclass == -1)
|
if(subroutclass == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
next(p);
|
next(p);
|
||||||
SUBDEC* subdec = (SUBDEC*)malloc(sizeof(SUBDEC));
|
SUBROUTDEC* subroutdec = (SUBROUTDEC*)malloc(sizeof(SUBROUTDEC));
|
||||||
subdec->subroutclass = subroutclass;
|
subroutdec->subroutclass = subroutclass;
|
||||||
|
|
||||||
subdec->typeclass = p->current->type;
|
subroutdec->typeclass = p->current->type;
|
||||||
if(!strcmp(p->current->token, "void")) {
|
if(!strcmp(p->current->token, "void")) {
|
||||||
subdec->type = p->current->token;
|
subroutdec->type = p->current->token;
|
||||||
next(p);
|
next(p);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bool dummy;
|
bool dummy;
|
||||||
subdec->type = parsetype(p, &dummy);
|
subroutdec->type = parsetype(p, &dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
subdec->debug = getdebug(p);
|
subroutdec->debug = getdebug(p);
|
||||||
|
|
||||||
subdec->name = parseidentifier(p);
|
subroutdec->name = parseidentifier(p);
|
||||||
|
|
||||||
checkcontent(p, "(");
|
checkcontent(p, "(");
|
||||||
subdec->parameters = parseparameters(p);
|
subroutdec->parameters = parseparameters(p);
|
||||||
checkcontent(p, ")");
|
checkcontent(p, ")");
|
||||||
|
|
||||||
checkcontent(p, "{");
|
checkcontent(p, "{");
|
||||||
subdec->body = parsesubroutbody(p);
|
subroutdec->body = parsesubroutbody(p);
|
||||||
checkcontent(p, "}");
|
checkcontent(p, "}");
|
||||||
|
|
||||||
return subdec;
|
return subroutdec;
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBDEC* parsesubroutdecs(PARSER* p) {
|
SUBROUTDEC* parsesubroutdecs(PARSER* p) {
|
||||||
SUBDEC* head = parsesubroutdec(p);
|
SUBROUTDEC* head = parsesubroutdec(p);
|
||||||
SUBDEC* current = head;
|
SUBROUTDEC* current = head;
|
||||||
SUBDEC* next;
|
SUBROUTDEC* next;
|
||||||
while(next = parsesubroutdec(p), next != NULL) {
|
while(next = parsesubroutdec(p), next != NULL) {
|
||||||
current->next = next;
|
current->next = next;
|
||||||
current = next;
|
current = next;
|
||||||
|
@ -544,7 +544,7 @@ CLASS* parseclass(PARSER* p) {
|
||||||
|
|
||||||
class->vardecs = parseclassvardecs(p);
|
class->vardecs = parseclassvardecs(p);
|
||||||
|
|
||||||
class->subdecs = parsesubroutdecs(p);
|
class->subroutdecs = parsesubroutdecs(p);
|
||||||
|
|
||||||
checkcontent(p, "}");
|
checkcontent(p, "}");
|
||||||
|
|
||||||
|
|
123
parser.h
123
parser.h
|
@ -2,130 +2,9 @@
|
||||||
#define PARSER_H
|
#define PARSER_H
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "tokenizer.h"
|
#include "tokenizer.h"
|
||||||
|
#include "parser-tree.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
struct statement;
|
|
||||||
struct explist;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char* file;
|
|
||||||
int definedat;
|
|
||||||
} DEBUGINFO;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
ifstatement, whilestatement, letstatement, dostatement, returnstatement
|
|
||||||
} STATEMENTTYPE;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
varname, intconstant, stringconstant, keywordconstant, arrayitem, subroutcall, innerexpression, unaryopterm
|
|
||||||
} TERMTYPE;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char* parentname;
|
|
||||||
char* name;
|
|
||||||
struct explist* parameters;
|
|
||||||
DEBUGINFO* debug;
|
|
||||||
} SUBROUTCALL;
|
|
||||||
|
|
||||||
typedef struct term {
|
|
||||||
TERMTYPE type;
|
|
||||||
union {
|
|
||||||
char* string;
|
|
||||||
int integer;
|
|
||||||
SUBROUTCALL* call;
|
|
||||||
struct term* expression;
|
|
||||||
};
|
|
||||||
struct term* arrayexp;
|
|
||||||
char op;
|
|
||||||
struct term* next;
|
|
||||||
} TERM;
|
|
||||||
|
|
||||||
typedef struct explist {
|
|
||||||
TERM* expression;
|
|
||||||
struct explist* next;
|
|
||||||
} EXPRESSIONLIST;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
TERM* expression;
|
|
||||||
struct statement* statements;
|
|
||||||
} CONDSTATEMENT;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CONDSTATEMENT* base;
|
|
||||||
struct statement* elsestatements;
|
|
||||||
} IFSTATEMENT;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char* varname;
|
|
||||||
TERM* arrayind;
|
|
||||||
TERM* expression;
|
|
||||||
} LETSTATEMENT;
|
|
||||||
|
|
||||||
typedef struct statement {
|
|
||||||
STATEMENTTYPE type;
|
|
||||||
union {
|
|
||||||
CONDSTATEMENT* whilest;
|
|
||||||
IFSTATEMENT* ifst;
|
|
||||||
LETSTATEMENT* letst;
|
|
||||||
SUBROUTCALL* dost;
|
|
||||||
TERM* retst;
|
|
||||||
};
|
|
||||||
struct statement* next;
|
|
||||||
} STATEMENT;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
stat, field
|
|
||||||
} VARCLASS;
|
|
||||||
|
|
||||||
typedef struct vardec {
|
|
||||||
char* type;
|
|
||||||
bool primitive;
|
|
||||||
TOKENTYPE typeclass;
|
|
||||||
STRINGLIST* names;
|
|
||||||
struct vardec* next;
|
|
||||||
DEBUGINFO* debug;
|
|
||||||
} VARDEC;
|
|
||||||
|
|
||||||
typedef struct classvardec {
|
|
||||||
VARCLASS varclass;
|
|
||||||
VARDEC* base;
|
|
||||||
struct classvardec* next;
|
|
||||||
} CLASSVARDEC;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
constructor, function, method
|
|
||||||
} SUBROUTCLASS;
|
|
||||||
|
|
||||||
typedef struct parameter {
|
|
||||||
char* type;
|
|
||||||
char* name;
|
|
||||||
struct parameter* next;
|
|
||||||
} PARAMETER;
|
|
||||||
|
|
||||||
typedef struct SUBROUTBODY {
|
|
||||||
VARDEC* vardecs;
|
|
||||||
STATEMENT* statements;
|
|
||||||
} SUBROUTBODY;
|
|
||||||
|
|
||||||
typedef struct subdec {
|
|
||||||
SUBROUTCLASS subroutclass;
|
|
||||||
char* type;
|
|
||||||
TOKENTYPE typeclass;
|
|
||||||
char* name;
|
|
||||||
PARAMETER* parameters;
|
|
||||||
SUBROUTBODY* body;
|
|
||||||
DEBUGINFO* debug;
|
|
||||||
struct subdec* next;
|
|
||||||
} SUBDEC;
|
|
||||||
|
|
||||||
typedef struct cl {
|
|
||||||
char* name;
|
|
||||||
CLASSVARDEC* vardecs;
|
|
||||||
SUBDEC* subdecs;
|
|
||||||
DEBUGINFO* debug;
|
|
||||||
struct cl* next;
|
|
||||||
} CLASS;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
TOKEN* tokens;
|
TOKEN* tokens;
|
||||||
TOKEN* current;
|
TOKEN* current;
|
||||||
|
|
Loading…
Reference in New Issue