Organize parse tree

This commit is contained in:
Augusto Gunsch 2020-12-21 20:35:41 -03:00
parent c629a01b59
commit bf61fcdd30
No known key found for this signature in database
GPG Key ID: F7EEFE29825C72DC
6 changed files with 222 additions and 199 deletions

View File

@ -26,7 +26,7 @@ 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 addsubroutdec(SCOPE* s, SUBROUTDEC* sd);
void addclass(SCOPE* s, CLASS* c);
// DEFINITIONS
@ -59,8 +59,8 @@ DEBUGINFO* getdebugvardec(OBJ* obj) {
return obj->vardec->debug;
}
DEBUGINFO* getdebugsubdec(OBJ* obj) {
return obj->subdec->debug;
DEBUGINFO* getdebugsubroutdec(OBJ* obj) {
return obj->subroutdec->debug;
}
DEBUGINFO* getdebugclass(OBJ* obj) {
@ -150,15 +150,15 @@ CLASSVARDEC* getclassvardec(SCOPE* s, char* name) {
return NULL;
}
SUBDEC* getsubdec(SCOPE* s, char* name) {
SUBDEC* curr = s->subroutines;
SUBROUTDEC* getsubroutdec(SCOPE* s, char* name) {
SUBROUTDEC* 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 getsubroutdec(s->previous, name);
return NULL;
}
@ -174,8 +174,8 @@ CLASS* getclass(SCOPE* s, char* name) {
return NULL;
}
SUBDEC* getsubdecfromclass(CLASS* c, char* name) {
SUBDEC* curr = c->subdecs;
SUBROUTDEC* getsubroutdecfromclass(CLASS* c, char* name) {
SUBROUTDEC* curr = c->subroutdecs;
while(curr != NULL) {
if(!strcmp(curr->name, name))
return curr;
@ -184,34 +184,34 @@ SUBDEC* getsubdecfromclass(CLASS* c, char* name) {
return NULL;
}
SUBDEC* getsubdecfromvar(SCOPE* s, OBJ* var, SUBROUTCALL* call) {
SUBROUTDEC* getsubroutdecfromvar(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);
return getsubroutdecfromclass(c, call->name);
}
SUBDEC* getsubdecfromparent(SCOPE* s, SUBROUTCALL* call) {
SUBDEC* sd;
SUBROUTDEC* getsubroutdecfromparent(SCOPE* s, SUBROUTCALL* call) {
SUBROUTDEC* 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);
sd = getsubroutdecfromclass(parent->class, call->name);
else
sd = getsubdecfromvar(s, parent, call);
sd = getsubroutdecfromvar(s, parent, call);
return sd;
}
SUBDEC* getsubdecfromcall(SCOPE* s, SUBROUTCALL* call) {
SUBDEC* sd;
SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call) {
SUBROUTDEC* sd;
if(call->parentname != NULL)
sd = getsubdecfromparent(s, call);
sd = getsubroutdecfromparent(s, call);
else
sd = getsubdec(s, call->name);
sd = getsubroutdec(s, call->name);
if(sd == NULL)
notdeclared(call->name, call->debug);
return sd;
@ -233,14 +233,14 @@ OBJ* getbyname(SCOPE* s, char* name) {
if(vd != NULL) {
o->vardec = vd;
o->type = vardec;
o->getdebug = getdebugsubdec;
o->getdebug = getdebugsubroutdec;
return o;
}
SUBDEC* sd = getsubdec(s, name);
SUBROUTDEC* sd = getsubroutdec(s, name);
if(sd != NULL) {
o->subdec = sd;
o->type = subdec;
o->subroutdec = sd;
o->type = subroutdec;
o->getdebug = getdebugclassvardec;
return o;
}
@ -286,9 +286,9 @@ void addvardec(SCOPE* s, VARDEC* v) {
s->vardecs = new;
}
void addsubdec(SCOPE* s, SUBDEC* sd) {
void addsubroutdec(SCOPE* s, SUBROUTDEC* sd) {
ensurenoduplicate(s, sd->name, sd->debug);
SUBDEC* new = copy(sd, sizeof(SUBDEC));
SUBROUTDEC* new = copy(sd, sizeof(SUBROUTDEC));
new->next = s->subroutines;
s->subroutines = new;
}
@ -319,11 +319,11 @@ void addvardecs(SCOPE* s, VARDEC* vs) {
}
}
void addsubdecs(SCOPE* s, SUBDEC* ss) {
SUBDEC* next;
void addsubroutdecs(SCOPE* s, SUBROUTDEC* ss) {
SUBROUTDEC* next;
while(ss != NULL) {
next = ss->next;
addsubdec(s, ss);
addsubroutdec(s, ss);
ss = next;
}
}

View File

@ -10,7 +10,7 @@
// Data types
typedef struct scope {
SUBDEC* subroutines;
SUBROUTDEC* subroutines;
CLASSVARDEC* classvardecs;
VARDEC* vardecs;
CLASS* classes;
@ -18,13 +18,13 @@ typedef struct scope {
} SCOPE;
typedef enum {
subdec, classvardec, vardec, class
subroutdec, classvardec, vardec, class
} OBJTYPE;
typedef struct object {
OBJTYPE type;
union {
SUBDEC* subdec;
SUBROUTDEC* subroutdec;
CLASSVARDEC* classvardec;
VARDEC* vardec;
CLASS* class;
@ -35,15 +35,15 @@ typedef struct object {
// Group adding
void addclassvardecs(SCOPE* s, CLASSVARDEC* 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);
// Scope handling
SCOPE* mkscope(SCOPE* prev);
// Single type getters
SUBDEC* getsubdec(SCOPE* s, char* name);
SUBDEC* getsubdecfromcall(SCOPE* s, SUBROUTCALL* call);
SUBROUTDEC* getsubroutdec(SCOPE* s, char* name);
SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call);
CLASS* getclass(SCOPE* s, char* name);
// Generic getters

View File

@ -27,7 +27,7 @@ char* dotlabel(char* n1, char* n2) {
return result;
}
char* subdecname(CLASS* c, SUBDEC* sd) {
char* subroutdecname(CLASS* c, SUBROUTDEC* sd) {
return dotlabel(c->name, sd->name);
}
@ -126,10 +126,10 @@ LINEBLOCK* compilecallln(CLASS* c, SUBROUTCALL* call) {
}
// temporary ignore list for OS functions
char* ignoresubdecs[] = {
char* ignoresubroutdecs[] = {
"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* block = compilecallln(c, call);
@ -143,13 +143,13 @@ LINEBLOCK* compilesubroutcall(SCOPE* s, CLASS* c, SUBROUTCALL* call) {
// gambiarra
char* type = NULL;
for(int i = 0; i < ignorecount; i += 2) {
if(!strcmp(call->name, ignoresubdecs[i])) {
type = ignoresubdecs[i+1];
if(!strcmp(call->name, ignoresubroutdecs[i])) {
type = ignoresubroutdecs[i+1];
break;
}
}
if(type == NULL)
type = getsubdecfromcall(s, call)->type;
type = getsubroutdecfromcall(s, call)->type;
if(!strcmp(type, "void")) {
char* tokens[] = { "pop", "temp", "0" };
appendln(block, mksimpleln(tokens, sizeof(tokens) / sizeof(char*)));
@ -162,7 +162,7 @@ LINEBLOCK* compileret(SCOPE* s, TERM* e) {
LINE* ret = onetoken("return");
LINEBLOCK* block = mklnblk(ret);
// void subdecs return 0
// void subroutdecs return 0
if(e == NULL) {
char* tokens[] = { "push", "constant", "0" };
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) {
if(st->type == dostatement)
return compilesubroutcall(s, c, st->dost);
return compilesubroutcall(s, c, st->dostatement);
else if(st->type == returnstatement)
return compileret(s, st->retst);
return compileret(s, st->retstatement);
else {
eprintf("UNSUPPORTED\n");
exit(1);
@ -198,10 +198,10 @@ LINEBLOCK* compilefunbody(SCOPE* s, CLASS* c, SUBROUTBODY* b) {
return head;
}
LINEBLOCK* compilefundec(SCOPE* s, CLASS* c, SUBDEC* f) {
LINEBLOCK* compilefundec(SCOPE* s, CLASS* c, SUBROUTDEC* f) {
LINE* label = mkline(3);
addtoken(label, ezheapstr("function"));
addtoken(label, subdecname(c, f));
addtoken(label, subroutdecname(c, f));
addtoken(label, itoa(countlocalvars(f->body->vardecs)));
label->next = NULL;
@ -214,7 +214,7 @@ LINEBLOCK* compilefundec(SCOPE* s, CLASS* c, SUBDEC* f) {
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
// Must have a 'return' at the end
// 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) {
SCOPE* topscope = mkscope(c->globalscope);
addclassvardecs(topscope, class->vardecs);
addsubdecs(topscope, class->subdecs);
addsubroutdecs(topscope, class->subroutdecs);
LINEBLOCK* output = NULL;
SUBDEC* curr = class->subdecs;
SUBROUTDEC* curr = class->subroutdecs;
while(curr != NULL) {
output = mergelnblks(output, compilesubdec(topscope, class, curr));
output = mergelnblks(output, compilesubroutdec(topscope, class, curr));
curr = curr->next;
}
return output;

144
parser-tree.h Normal file
View File

@ -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

View File

@ -20,10 +20,10 @@ const char* ops[] = {
};
const int opssize = sizeof(ops) / sizeof(char*);
const char* varclasses[] = {
const char* classvartypes[] = {
"static", "field"
};
const int varclassessize = sizeof(varclasses) / sizeof(char*);
const int classvartypessize = sizeof(classvartypes) / sizeof(char*);
const char* vardectypes[] = {
"int", "char", "boolean"
@ -290,29 +290,29 @@ STATEMENT* parsestatement(PARSER* p) {
if(!strcmp(p->current->token, "let")) {
next(p);
st->type = letstatement;
st->letst = parselet(p);
st->letstatement = parselet(p);
} else if(!strcmp(p->current->token, "if")) {
next(p);
st->type = ifstatement;
st->ifst = parseif(p);
st->ifstatement = parseif(p);
} else if(!strcmp(p->current->token, "while")) {
next(p);
st->type = whilestatement;
st->whilest = parsecond(p);
st->whilestatement = parsecond(p);
} else if(!strcmp(p->current->token, "do")) {
next(p);
st->type = dostatement;
st->dost = parsesubroutcall(p);
st->dostatement = parsesubroutcall(p);
checkcontent(p, ";");
} else if(!strcmp(p->current->token, "return")) {
next(p);
st->type = returnstatement;
if(strcmp(p->current->token, ";")) {
st->retst = parseexpressionnullified(p);
st->retstatement = parseexpressionnullified(p);
checkcontent(p, ";");
}
else {
st->retst = NULL;
st->retstatement = NULL;
next(p);
}
} else {
@ -361,8 +361,8 @@ int parsepossibilities(PARSER* p, const char** strings, int sz) {
return -1;
}
VARCLASS parsevarclass(PARSER* p) {
return parsepossibilities(p, varclasses, varclassessize);
CLASSVARTYPE parseclassvartype(PARSER* p) {
return parsepossibilities(p, classvartypes, classvartypessize);
}
SUBROUTCLASS parsesubroutclass(PARSER* p) {
@ -400,13 +400,13 @@ void parsevardeccommon(PARSER* p, VARDEC* v) {
}
CLASSVARDEC* parseclassvardec(PARSER* p) {
VARCLASS varclass = parsevarclass(p);
if(varclass == -1)
CLASSVARTYPE classvartype = parseclassvartype(p);
if(classvartype == -1)
return NULL;
next(p);
CLASSVARDEC* classvardec = (CLASSVARDEC*)malloc(sizeof(CLASSVARDEC));
classvardec->varclass = varclass;
classvardec->type = classvartype;
classvardec->base = (VARDEC*)malloc(sizeof(VARDEC));
@ -484,44 +484,44 @@ SUBROUTBODY* parsesubroutbody(PARSER* p) {
return subroutbody;
}
SUBDEC* parsesubroutdec(PARSER* p) {
SUBROUTDEC* parsesubroutdec(PARSER* p) {
SUBROUTCLASS subroutclass = parsesubroutclass(p);
if(subroutclass == -1)
return NULL;
next(p);
SUBDEC* subdec = (SUBDEC*)malloc(sizeof(SUBDEC));
subdec->subroutclass = subroutclass;
SUBROUTDEC* subroutdec = (SUBROUTDEC*)malloc(sizeof(SUBROUTDEC));
subroutdec->subroutclass = subroutclass;
subdec->typeclass = p->current->type;
subroutdec->typeclass = p->current->type;
if(!strcmp(p->current->token, "void")) {
subdec->type = p->current->token;
subroutdec->type = p->current->token;
next(p);
}
else {
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, "(");
subdec->parameters = parseparameters(p);
subroutdec->parameters = parseparameters(p);
checkcontent(p, ")");
checkcontent(p, "{");
subdec->body = parsesubroutbody(p);
subroutdec->body = parsesubroutbody(p);
checkcontent(p, "}");
return subdec;
return subroutdec;
}
SUBDEC* parsesubroutdecs(PARSER* p) {
SUBDEC* head = parsesubroutdec(p);
SUBDEC* current = head;
SUBDEC* next;
SUBROUTDEC* parsesubroutdecs(PARSER* p) {
SUBROUTDEC* head = parsesubroutdec(p);
SUBROUTDEC* current = head;
SUBROUTDEC* next;
while(next = parsesubroutdec(p), next != NULL) {
current->next = next;
current = next;
@ -544,7 +544,7 @@ CLASS* parseclass(PARSER* p) {
class->vardecs = parseclassvardecs(p);
class->subdecs = parsesubroutdecs(p);
class->subroutdecs = parsesubroutdecs(p);
checkcontent(p, "}");

123
parser.h
View File

@ -2,130 +2,9 @@
#define PARSER_H
#include <stdbool.h>
#include "tokenizer.h"
#include "parser-tree.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 {
TOKEN* tokens;
TOKEN* current;