Split parser into several files

This commit is contained in:
Augusto Gunsch 2020-12-22 13:18:54 -03:00
parent 0b1345d845
commit 351446bb6d
No known key found for this signature in database
GPG Key ID: F7EEFE29825C72DC
15 changed files with 713 additions and 544 deletions

View File

@ -10,6 +10,6 @@ typedef struct {
} COMPILER;
COMPILER* mkcompiler(CLASS* classes);
void compile();
void compile(COMPILER* c);
#endif

View File

@ -1,20 +0,0 @@
#ifndef PARSER_CONSTANTS_H
#define PARSER_CONSTANTS_H
#include "util.h"
const char* keywordsarr[] = { "true", "false", "null", "this" };
const char* opsarr[] = { "+", "-", "*", "/", "&", "|", "<", ">", "=" };
const char* classvartypesarr[] = { "static", "field" };
const char* vartypesarr[] = { "int", "char", "boolean" };
const char* subroutclassesarr[] = { "constructor", "function", "method" };
const char* tokentypesarr[] = { "keyword", "identifier", "symbol", "integerConstant", "stringConstant" };
#define mkstrlist(name, array) STRINGARRAY name = { .items = array, .size = strcount(array) }
mkstrlist(keywordconstants, keywordsarr);
mkstrlist(operators, opsarr);
mkstrlist(classvartypes, classvartypesarr);
mkstrlist(vartypes, vartypesarr);
mkstrlist(subroutclasses, subroutclassesarr);
mkstrlist(tokentypes, tokentypesarr);
#undef mkstrlist
#endif

238
parser-expressions.c Normal file
View File

@ -0,0 +1,238 @@
#include <stdlib.h>
#include "util.h"
#include "parser-internal.h"
#include "parser-expressions.h"
TERM* parsetermnullified(PARSER* p);
TERM* parseterm(PARSER* p);
TERM* mkterm(TERMTYPE type);
TERM* parseint(PARSER* p);
TERM* parsestr(PARSER* p);
TERM* parsekeyword(PARSER* p);
TERM* parseunaryopterm(PARSER* p);
TERM* parseinnerexpression(PARSER* p);
TERM* parsecalltermnullified(PARSER* p);
TERM* parsearrayterm(PARSER* p);
TERM* parsevarterm(PARSER* p);
TERM* parseidentifierterm(PARSER* p);
bool isop(TOKEN* t);
SUBROUTCALL* nullsubroutcall(PARSER* p, SUBROUTCALL* c);
SUBROUTCALL* parsesubroutcallnullified(PARSER* p);
const char* keywordsarr[] = { "true", "false", "null", "this" };
const char* opsarr[] = { "+", "-", "*", "/", "&", "|", "<", ">", "=" };
mkstrlist(keywordconstants, keywordsarr);
mkstrlist(operators, opsarr);
TERM* parsetermnullified(PARSER* p) {
TOKENTYPE type = p->current->type;
if(type == integer)
return parseint(p);
else if(type == string)
return parsestr(p);
else if(type == keyword)
return parsekeyword(p);
else if(type == identifier)
return parseidentifierterm(p);
else if(equals(p, "-") || equals(p, "~"))
return parseunaryopterm(p);
else if(equals(p, "("))
return parseinnerexpression(p);
return NULL;
}
TERM* parseterm(PARSER* p) {
TERM* t = parsetermnullified(p);
if(t == NULL)
unexpected(p);
return t;
}
TERM* mkterm(TERMTYPE type) {
TERM* t = (TERM*)malloc(sizeof(TERM));
t->type = type;
return t;
}
TERM* parseint(PARSER* p) {
TERM* t = mkterm(intconstant);
t->integer = atoi(p->current->token);
next(p);
return t;
}
TERM* parsestr(PARSER* p) {
TERM* t = mkterm(stringconstant);
t->string = p->current->token;
next(p);
return t;
}
TERM* parsekeyword(PARSER* p) {
TERM* t = mkterm(keywordconstant);
if(!existsinarray(&keywordconstants, p->current->token))
unexpected(p);
t->string = p->current->token;
next(p);
return t;
}
TERM* parseunaryopterm(PARSER* p) {
TERM* t = mkterm(unaryopterm);
next(p);
t->expression = parseterm(p);
t->expression->next = NULL;
return t;
}
TERM* parseinnerexpression(PARSER* p) {
TERM* t = mkterm(innerexpression);
next(p);
t->expression = parseexpression(p);
checkcontent(p, ")");
return t;
}
TERM* parsecalltermnullified(PARSER* p) {
TERM* t = mkterm(subroutcall);
SUBROUTCALL* call = parsesubroutcallnullified(p);
t->call == call;
return t;
}
TERM* parsearrayterm(PARSER* p) {
TERM* t = mkterm(arrayitem);
t->string = p->current->token;
next(p);
checkcontent(p, "[");
t->arrayexp = parseexpression(p);
checkcontent(p, "]");
return t;
}
TERM* parsevarterm(PARSER* p) {
TERM* t = mkterm(varname);
t->string = p->current->token;
next(p);
return t;
}
TERM* parseidentifierterm(PARSER* p) {
TERM* t = parsecalltermnullified(p);
if(t == NULL)
if(nextequals(p, "["))
return parsearrayterm(p);
else
return parsevarterm(p);
else
return t;
}
bool isop(TOKEN* t) {
for(int i = 0; i < operators.size; i++)
if(!strcmp(t->token, operators.items[i]))
return true;
return false;
}
TERM* parseexpressionnullified(PARSER* p) {
TERM* head = parsetermnullified(p);
TERM* current = head;
TERM* nextt;
while(isop(p->current)) {
current->op = p->current->token[0];
next(p);
nextt = parseterm(p);
current->next = nextt;
current = nextt;
}
if(current != NULL)
current->next = NULL;
return head;
}
TERM* parseexpression(PARSER* p) {
TERM* t = parseexpressionnullified(p);
if(t == NULL)
unexpected(p);
return t;
}
SUBROUTCALL* nullsubroutcall(PARSER* p, SUBROUTCALL* c) {
free(c);
rewindparser(p);
return NULL;
}
SUBROUTCALL* parsesubroutcallnullified(PARSER* p) {
if(p->current->type != identifier)
return NULL;
anchorparser(p);
SUBROUTCALL* c = (SUBROUTCALL*)malloc(sizeof(SUBROUTCALL));
c->debug = getdebug(p);
if(nextequals(p, ".")) {
c->parentname = p->current->token;
next(p);
next(p);
}
else
c->parentname = NULL;
if(p->current->type != identifier)
return nullsubroutcall(p, c);
c->name = p->current->token;
if(differs(p, "("))
return nullsubroutcall(p, c);
next(p);
c->parameters = parseexpressionlist(p);
if(differs(p, ")"))
return nullsubroutcall(p, c);
next(p);
return c;
}
SUBROUTCALL* parsesubroutcall(PARSER* p) {
SUBROUTCALL* c = (SUBROUTCALL*)malloc(sizeof(SUBROUTCALL));
c->debug = getdebug(p);
if(nextequals(p, ".")) {
c->parentname = parseidentifier(p);
next(p);
}
else
c->parentname = NULL;
c->name = parseidentifier(p);
checkcontent(p, "(");
c->parameters = parseexpressionlist(p);
checkcontent(p, ")");
return c;
}
EXPRESSIONLIST* parseexpressionlist(PARSER* p) {
if(!strcmp(p->current->token, ")"))
return NULL;
EXPRESSIONLIST* head = (EXPRESSIONLIST*)malloc(sizeof(EXPRESSIONLIST));
head->expression = parseexpressionnullified(p);
EXPRESSIONLIST* current = head;
EXPRESSIONLIST* nextls;
while(!strcmp(p->current->token, ",")) {
next(p);
nextls = (EXPRESSIONLIST*)malloc(sizeof(EXPRESSIONLIST));
nextls->expression = parseexpression(p);
current->next = nextls;
current = nextls;
}
if(current != NULL)
current->next = NULL;
return head;
}

8
parser-expressions.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef PARSER_EXPRESSIONS_H
#define PARSER_EXPRESSIONS_H
#include "parser.h"
TERM* parseexpressionnullified(PARSER* p);
TERM* parseexpression(PARSER* p);
SUBROUTCALL* parsesubroutcall(PARSER* p);
EXPRESSIONLIST* parseexpressionlist(PARSER* p);
#endif

44
parser-internal.c Normal file
View File

@ -0,0 +1,44 @@
#include <stdlib.h>
#include "parser-internal.h"
#include "util.h"
const char* tokentypesarr[] = { "keyword", "identifier", "symbol",
"integerConstant", "stringConstant" };
mkstrlist(tokentypes, tokentypesarr);
void unexpected(PARSER* p) {
eprintf("Unexpected token '%s' (of type %s); line %i, file '%s'\n",
p->current->token, tokentypes.items[p->current->type],
p->current->definedat, p->file);
exit(1);
}
void checktype(PARSER* p, TOKENTYPE type) {
if(p->current->type != type) {
eprintf("Unexpected %s; file '%s', line %i\n",
tokentypes.items[p->current->type], p->file,
p->current->definedat);
exit(1);
}
}
void checkcontent(PARSER* p, const char* content) {
if(differs(p, content))
unexpected(p);
next(p);
}
char* parseidentifier(PARSER* p) {
checktype(p, identifier);
char* result = p->current->token;
next(p);
return result;
}
DEBUGINFO* getdebug(PARSER* p) {
DEBUGINFO* d = (DEBUGINFO*)malloc(sizeof(DEBUGINFO));
d->file = p->file;
d->definedat = p->current->definedat;
return d;
}

19
parser-internal.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef PARSER_INTERNAL_H
#define PARSER_INTERNAL_H
#include <string.h>
#include "parser.h"
#define mkstrlist(name, array) STRINGARRAY name = { .items = array, .size = strcount(array) }
#define next(parser) parser->current = p->current->next
#define rewindparser(parser) p->checkpoint = p->current
#define anchorparser(parser) p->current = p->checkpoint
#define differs(parser, str) strcmp(parser->current->token, str)
#define nextdiffers(parser, str) strcmp(parser->current->next->token, str)
#define equals(parser, str) !differs(parser, str)
#define nextequals(parser, str) !nextdiffers(parser, str)
void unexpected(PARSER* p);
char* parseidentifier(PARSER* p);
void checkcontent(PARSER* p, const char* content);
DEBUGINFO* getdebug(PARSER* p);
#endif

136
parser-statements.c Normal file
View File

@ -0,0 +1,136 @@
#include <stdlib.h>
#include "parser-expressions.h"
#include "parser-internal.h"
#include "parser-statements.h"
STATEMENT* mkstatement(STATEMENTTYPE t);
STATEMENT* parsestatementnullified(PARSER* p);
STATEMENT* parselet(PARSER* p);
CONDSTATEMENT* parsecond(PARSER* p);
STATEMENT* parseif(PARSER* p);
STATEMENT* parsewhile(PARSER* p);
STATEMENT* parsedo(PARSER* p);
STATEMENT* parsereturn(PARSER* p);
STATEMENT* mkstatement(STATEMENTTYPE t) {
STATEMENT* s = (STATEMENT*)malloc(sizeof(STATEMENT));
s->type = t;
return s;
}
// Though nullified, will throw errors if the parsing was on-going
STATEMENT* parsestatementnullified(PARSER* p) {
if(equals(p, "let"))
return parselet(p);
else if(equals(p, "if"))
return parseif(p);
else if(equals(p, "while"))
return parsewhile(p);
else if(equals(p, "do"))
return parsedo(p);
else if(equals(p, "return"))
return parsereturn(p);
return NULL;
}
STATEMENT* parsestatements(PARSER* p) {
STATEMENT* head = parsestatementnullified(p);
STATEMENT* curr = head;
STATEMENT* next;
while(next = parsestatementnullified(p), next != NULL) {
curr->next = next;
curr = next;
}
if(curr != NULL)
curr->next = NULL;
return head;
}
STATEMENT* parselet(PARSER* p) {
next(p);
STATEMENT* s = mkstatement(letstatement);
LETSTATEMENT* letst= (LETSTATEMENT*)malloc(sizeof(LETSTATEMENT));
letst->varname = parseidentifier(p);
if(equals(p, "[")) {
next(p);
letst->arrayind = parseexpression(p);
checkcontent(p, "]");
}
else
letst->arrayind = NULL;
checkcontent(p, "=");
letst->expression = parseexpression(p);
checkcontent(p, ";");
s->type = letstatement;
return s;
}
CONDSTATEMENT* parsecond(PARSER* p) {
checkcontent(p, "(");
CONDSTATEMENT* st = (CONDSTATEMENT*)malloc(sizeof(CONDSTATEMENT));
st->expression = parseexpression(p);
checkcontent(p, ")");
checkcontent(p, "{");
st->statements = parsestatements(p);
checkcontent(p, "}");
return st;
}
STATEMENT* parseif(PARSER* p) {
next(p);
STATEMENT* s = mkstatement(ifstatement);
IFSTATEMENT* ifst = (IFSTATEMENT*)malloc(sizeof(IFSTATEMENT));
ifst->base = parsecond(p);
if(equals(p, "else")) {
next(p);
checkcontent(p, "{");
ifst->elsestatements = parsestatements(p);
checkcontent(p, "}");
}
else
ifst->elsestatements = NULL;
s->type = ifstatement;
return s;
}
STATEMENT* parsewhile(PARSER* p) {
next(p);
STATEMENT* s = mkstatement(whilestatement);
s->whilestatement = parsecond(p);
return s;
}
STATEMENT* parsedo(PARSER* p) {
next(p);
STATEMENT* s = mkstatement(dostatement);
s->dostatement = parsesubroutcall(p);
checkcontent(p, ";");
return s;
}
STATEMENT* parsereturn(PARSER* p) {
next(p);
STATEMENT* s = mkstatement(returnstatement);
s->retstatement = parseexpressionnullified(p);
checkcontent(p, ";");
return s;
}

5
parser-statements.h Normal file
View File

@ -0,0 +1,5 @@
#ifndef PARSER_STATEMENTS_H
#define PARSER_STATEMENTS_H
#include "parser.h"
STATEMENT* parsestatements(PARSER* p);
#endif

244
parser-structure.c Normal file
View File

@ -0,0 +1,244 @@
#include <stdlib.h>
#include "parser-internal.h"
#include "parser-structure.h"
#include "parser-statements.h"
CLASS* parseclass(PARSER* p);
int parsepossibilities(PARSER* p, STRINGARRAY* poss);
CLASSVARTYPE parseclassvartype(PARSER* p);
CLASSVARDEC* parseclassvardec(PARSER* p);
CLASSVARDEC* parseclassvardecs(PARSER* p);
SUBROUTCLASS parsesubroutclass(PARSER* p);
SUBROUTDEC* parsesubroutdec(PARSER* p);
SUBROUTDEC* parsesubroutdecs(PARSER* p);
PARAMETER* parseparameter(PARSER* p);
PARAMETER* parseparameters(PARSER* p);
SUBROUTBODY* parsesubroutbody(PARSER* p);
bool isprimitive(TOKEN* tk);
char* parsetype(PARSER* p);
void parsevardeccommon(PARSER* p, VARDEC* v);
VARDEC* parsevardec(PARSER* p);
VARDEC* parsevardecs(PARSER* p);
const char* classvartypesarr[] = { "static", "field" };
const char* vartypesarr[] = { "int", "char", "boolean" };
const char* subroutclassesarr[] = { "constructor", "function", "method" };
mkstrlist(classvartypes, classvartypesarr);
mkstrlist(vartypes, vartypesarr);
mkstrlist(subroutclasses, subroutclassesarr);
CLASS* parseclass(PARSER* p) {
checkcontent(p, "class");
CLASS* class = (CLASS*)malloc(sizeof(CLASS));
class->debug = getdebug(p);
class->name = parseidentifier(p);
checkcontent(p, "{");
class->vardecs = parseclassvardecs(p);
class->subroutdecs = parsesubroutdecs(p);
checkcontent(p, "}");
return class;
}
CLASS* parseclasses(PARSER* p) {
CLASS* head = parseclass(p);
CLASS* curr = head;
while(p->current != NULL && equals(p, "class")) {
curr->next = parseclass(p);
curr = curr->next;
}
if(curr != NULL)
curr->next = NULL;
return head;
}
int parsepossibilities(PARSER* p, STRINGARRAY* poss) {
for(int i = 0; i < poss->size; i++)
if(!strcmp(p->current->token, poss->items[i]))
return i;
return -1;
}
CLASSVARTYPE parseclassvartype(PARSER* p) {
return parsepossibilities(p, &classvartypes);
}
CLASSVARDEC* parseclassvardec(PARSER* p) {
CLASSVARTYPE classvartype = parseclassvartype(p);
if(classvartype == -1)
return NULL;
next(p);
CLASSVARDEC* classvardec = (CLASSVARDEC*)malloc(sizeof(CLASSVARDEC));
classvardec->type = classvartype;
classvardec->base = (VARDEC*)malloc(sizeof(VARDEC));
parsevardeccommon(p, classvardec->base);
return classvardec;
}
CLASSVARDEC* parseclassvardecs(PARSER* p) {
CLASSVARDEC* head = parseclassvardec(p);
CLASSVARDEC* curr = head;
CLASSVARDEC* next;
while(next = parseclassvardec(p), next != NULL) {
curr->next = next;
curr= next;
}
if(curr != NULL)
curr->next = NULL;
return head;
}
SUBROUTCLASS parsesubroutclass(PARSER* p) {
return parsepossibilities(p, &subroutclasses);
}
SUBROUTDEC* parsesubroutdec(PARSER* p) {
SUBROUTCLASS subroutclass = parsesubroutclass(p);
if(subroutclass == -1)
return NULL;
next(p);
SUBROUTDEC* subroutdec = (SUBROUTDEC*)malloc(sizeof(SUBROUTDEC));
subroutdec->subroutclass = subroutclass;
subroutdec->typeclass = p->current->type;
if(equals(p, "void")) {
subroutdec->type = p->current->token;
next(p);
}
else
subroutdec->type = parsetype(p);
subroutdec->debug = getdebug(p);
subroutdec->name = parseidentifier(p);
checkcontent(p, "(");
subroutdec->parameters = parseparameters(p);
checkcontent(p, ")");
checkcontent(p, "{");
subroutdec->body = parsesubroutbody(p);
checkcontent(p, "}");
return subroutdec;
}
SUBROUTDEC* parsesubroutdecs(PARSER* p) {
SUBROUTDEC* head = parsesubroutdec(p);
SUBROUTDEC* curr = head;
SUBROUTDEC* next;
while(next = parsesubroutdec(p), next != NULL) {
curr->next = next;
curr = next;
}
if(curr != NULL)
curr->next = NULL;
return head;
}
PARAMETER* parseparameter(PARSER* p) {
PARAMETER* param = (PARAMETER*)malloc(sizeof(PARAMETER));
if(equals(p, ")"))
return NULL;
param->type = parsetype(p);
param->name = parseidentifier(p);
return param;
}
PARAMETER* parseparameters(PARSER* p) {
PARAMETER* head = parseparameter(p);
PARAMETER* curr = head;
while(equals(p, ",")) {
next(p);
curr->next = parseparameter(p);
curr = curr->next;
}
if(curr != NULL)
curr->next = NULL;
return head;
}
SUBROUTBODY* parsesubroutbody(PARSER* p) {
SUBROUTBODY* subroutbody = (SUBROUTBODY*)malloc(sizeof(SUBROUTBODY));
subroutbody->vardecs = parsevardecs(p);
subroutbody->statements = parsestatements(p);
return subroutbody;
}
bool isprimitive(TOKEN* tk) {
if(tk->type == keyword)
if(existsinarray(&vartypes, tk->token))
return true;
return false;
}
char* parsetype(PARSER* p) {
if(p->current->type != identifier);
unexpected(p);
char* result = p->current->token;
next(p);
return result;
}
void parsevardeccommon(PARSER* p, VARDEC* v) {
v->typeclass = p->current->type;
v->primitive = isprimitive(p->current);
v->type = parsetype(p);
STRINGLIST* currstr = (STRINGLIST*)malloc(sizeof(STRINGLIST));
v->names = currstr;
v->debug = getdebug(p);
v->names->content = parseidentifier(p);
while(!strcmp(p->current->token, ",")) {
next(p);
STRINGLIST* nextstr = (STRINGLIST*)malloc(sizeof(STRINGLIST));
nextstr->content = parseidentifier(p);
currstr->next = nextstr;
currstr = nextstr;
}
currstr->next = NULL;
checkcontent(p, ";");
}
VARDEC* parsevardec(PARSER* p) {
if(strcmp(p->current->token, "var"))
return NULL;
next(p);
VARDEC* vardec = (VARDEC*)malloc(sizeof(VARDEC));
parsevardeccommon(p, vardec);
return vardec;
}
VARDEC* parsevardecs(PARSER* p) {
VARDEC* head = parsevardec(p);
VARDEC* curr = head;
VARDEC* next;
while(next = parsevardec(p), next != NULL) {
curr->next = next;
curr = next;
}
if(curr != NULL)
curr->next = NULL;
return head;
}

5
parser-structure.h Normal file
View File

@ -0,0 +1,5 @@
#ifndef PARSER_STRUCTURE_H
#define PARSER_STRUCTURE_H
#include "parser.h"
CLASS* parseclasses(PARSER* p);
#endif

524
parser.c
View File

@ -3,527 +3,9 @@
#include <stdlib.h>
#include <stdbool.h>
#include "parser.h"
#include "parser-constants.h"
char* parseidentifier(PARSER* p);
STATEMENT* parsestatements(PARSER* p);
SUBROUTCALL* parsesubroutcall(PARSER* p);
TERM* parseexpression(PARSER* p);
TERM* parseterm(PARSER* p);
DEBUGINFO* getdebug(PARSER* p) {
DEBUGINFO* d = (DEBUGINFO*)malloc(sizeof(DEBUGINFO));
d->file = p->file;
d->definedat = p->current->definedat;
return d;
}
void next(PARSER* p) {
p->current = p->current->next;
}
void checkpoint(PARSER* p) {
p->checkpoint = p->current;
}
void restorecp(PARSER* p) {
p->current = p->checkpoint;
}
void unexpectedtoken(PARSER* p) {
fprintf(stderr, "Unexpected token '%s' (of type %s); line %i, file '%s'\n", p->current->token, tokentypes.items[p->current->type], p->current->definedat, p->file);
}
void unexpected(PARSER* p) {
unexpectedtoken(p);
exit(1);
}
void checkcontent(PARSER* p, const char* content) {
if(strcmp(p->current->token, content))
unexpected(p);
next(p);
}
void checktype(PARSER* p, TOKENTYPE type) {
if(p->current->type != type) {
fprintf(stderr, "Unexpected %s; line %i, file '%s'\n", tokentypes.items[p->current->type], p->current->definedat, p->file);
exit(1);
}
}
TERM* parsetermnullified(PARSER* p) {
TERM* t = (TERM*)malloc(sizeof(TERM));
if(p->current->type == integer) {
t->type = intconstant;
t->integer = atoi(p->current->token);
next(p);
} else if(p->current->type == string) {
t->type = stringconstant;
t->string = p->current->token;
next(p);
} else if(p->current->type == keyword) {
t->type = keywordconstant;
bool valid = false;
for(int i = 0; i < keywordconstants.size; i++)
if(!strcmp(p->current->token, keywordconstants.items[i]))
valid = true;
if(!valid)
unexpected(p);
t->string = p->current->token;
next(p);
} else if(!strcmp(p->current->token, "-") || !strcmp(p->current->token, "~")) {
t->type = unaryopterm;
next(p);
t->expression = parseterm(p);
t->expression->next = NULL;
} else if(!strcmp(p->current->token, "(")) {
next(p);
t->type = innerexpression;
t->expression = parseexpression(p);
checkcontent(p, ")");
} else if(p->current->type == identifier) {
SUBROUTCALL* call = parsesubroutcall(p);
if(call == NULL) {
t->string = p->current->token;
next(p);
if(!strcmp(p->current->token, "[")) {
next(p);
t->arrayexp = parseexpression(p);
t->type = arrayitem;
checkcontent(p, "]");
} else {
t->type = varname;
}
} else {
t->type = subroutcall;
t->call = call;
}
} else {
return NULL;
}
return t;
}
bool isop(TOKEN* t) {
for(int i = 0; i < operators.size; i++)
if(!strcmp(t->token, operators.items[i]))
return true;
return false;
}
TERM* parseexpressionnullified(PARSER* p) {
TERM* head = parseterm(p);
TERM* current = head;
TERM* nextt;
while(isop(p->current)) {
current->op = p->current->token[0];
next(p);
nextt = parseterm(p);
current->next = nextt;
current = nextt;
}
if(current != NULL)
current->next = NULL;
return head;
}
TERM* parseterm(PARSER* p) {
TERM* t = parsetermnullified(p);
if(t == NULL)
unexpected(p);
return t;
}
TERM* parseexpression(PARSER* p) {
TERM* t = parseexpressionnullified(p);
if(t == NULL)
unexpected(p);
return t;
}
EXPRESSIONLIST* parseexpressionlist(PARSER* p) {
if(!strcmp(p->current->token, ")"))
return NULL;
EXPRESSIONLIST* head = (EXPRESSIONLIST*)malloc(sizeof(EXPRESSIONLIST));
head->expression = parseexpressionnullified(p);
EXPRESSIONLIST* current = head;
EXPRESSIONLIST* nextls;
while(!strcmp(p->current->token, ",")) {
next(p);
nextls = (EXPRESSIONLIST*)malloc(sizeof(EXPRESSIONLIST));
nextls->expression = parseexpression(p);
current->next = nextls;
current = nextls;
}
if(current != NULL)
current->next = NULL;
return head;
}
SUBROUTCALL* parsesubroutcall(PARSER* p) {
checkpoint(p);
SUBROUTCALL* call = (SUBROUTCALL*)malloc(sizeof(SUBROUTCALL));
if(!strcmp(p->current->next->token, ".")) {
if(p->current->type != identifier) {
free(call);
return NULL;
}
call->parentname = p->current->token;
next(p);
next(p);
}
else
call->parentname = NULL;
if(p->current->type != identifier) {
free(call);
restorecp(p);
return NULL;
}
call->debug = getdebug(p);
call->name = p->current->token;
next(p);
if(strcmp(p->current->token, "(")) {
free(call);
restorecp(p);
return NULL;
}
next(p);
call->parameters = parseexpressionlist(p);
if(strcmp(p->current->token, ")")) {
free(call);
restorecp(p);
return NULL;
}
next(p);
return call;
}
CONDSTATEMENT* parsecond(PARSER* p) {
checkcontent(p, "(");
CONDSTATEMENT* st = (CONDSTATEMENT*)malloc(sizeof(CONDSTATEMENT));
st->expression = parseexpression(p);
checkcontent(p, ")");
checkcontent(p, "{");
st->statements = parsestatements(p);
checkcontent(p, "}");
return st;
}
IFSTATEMENT* parseif(PARSER* p) {
IFSTATEMENT* ifst = (IFSTATEMENT*)malloc(sizeof(IFSTATEMENT));
ifst->base = parsecond(p);
if(!strcmp(p->current->token, "else")) {
next(p);
checkcontent(p, "{");
ifst->elsestatements = parsestatements(p);
checkcontent(p, "}");
}
else
ifst->elsestatements = NULL;
return ifst;
}
LETSTATEMENT* parselet(PARSER* p) {
LETSTATEMENT* letstatement = (LETSTATEMENT*)malloc(sizeof(LETSTATEMENT));
letstatement->varname = parseidentifier(p);
if(!strcmp(p->current->token, "[")) {
next(p);
letstatement->arrayind = parseexpression(p);
checkcontent(p, "]");
}
else
letstatement->arrayind = NULL;
checkcontent(p, "=");
letstatement->expression = parseexpression(p);
checkcontent(p, ";");
return letstatement;
}
STATEMENT* parsestatement(PARSER* p) {
STATEMENT* st = (STATEMENT*)malloc(sizeof(STATEMENT));
if(!strcmp(p->current->token, "let")) {
next(p);
st->type = letstatement;
st->letstatement = parselet(p);
} else if(!strcmp(p->current->token, "if")) {
next(p);
st->type = ifstatement;
st->ifstatement = parseif(p);
} else if(!strcmp(p->current->token, "while")) {
next(p);
st->type = whilestatement;
st->whilestatement = parsecond(p);
} else if(!strcmp(p->current->token, "do")) {
next(p);
st->type = dostatement;
st->dostatement = parsesubroutcall(p);
checkcontent(p, ";");
} else if(!strcmp(p->current->token, "return")) {
next(p);
st->type = returnstatement;
if(strcmp(p->current->token, ";")) {
st->retstatement = parseexpressionnullified(p);
checkcontent(p, ";");
}
else {
st->retstatement = NULL;
next(p);
}
} else {
free(st);
return NULL;
}
return st;
}
STATEMENT* parsestatements(PARSER* p) {
STATEMENT* head = parsestatement(p);
STATEMENT* current = head;
STATEMENT* next;
while(next = parsestatement(p), next != NULL) {
current->next = next;
current = next;
}
if(current != NULL)
current->next = NULL;
return head;
}
char* parsetype(PARSER* p, bool* primitive) {
char* result = p->current->token;
if(p->current->type == keyword)
for(int i = 0; i < vartypes.size; i++) {
if(!strcmp(p->current->token, vartypes.items[i])) {
next(p);
*primitive = true;
return result;
}
}
else if (p->current->type == identifier) {
next(p);
*primitive = false;
return result;
}
else
unexpected(p);
}
int parsepossibilities(PARSER* p, STRINGARRAY* poss) {
for(int i = 0; i < poss->size; i++)
if(!strcmp(p->current->token, poss->items[i]))
return i;
return -1;
}
CLASSVARTYPE parseclassvartype(PARSER* p) {
return parsepossibilities(p, &classvartypes);
}
SUBROUTCLASS parsesubroutclass(PARSER* p) {
return parsepossibilities(p, &subroutclasses);
}
char* parseidentifier(PARSER* p) {
checktype(p, identifier);
char* result = p->current->token;
next(p);
return result;
}
void parsevardeccommon(PARSER* p, VARDEC* v) {
v->typeclass = p->current->type;
v->type = parsetype(p, &(v->primitive));
STRINGLIST* currstr = (STRINGLIST*)malloc(sizeof(STRINGLIST));
v->names = currstr;
v->debug = getdebug(p);
v->names->content = parseidentifier(p);
while(!strcmp(p->current->token, ",")) {
next(p);
STRINGLIST* nextstr = (STRINGLIST*)malloc(sizeof(STRINGLIST));
nextstr->content = parseidentifier(p);
currstr->next = nextstr;
currstr = nextstr;
}
currstr->next = NULL;
checkcontent(p, ";");
}
CLASSVARDEC* parseclassvardec(PARSER* p) {
CLASSVARTYPE classvartype = parseclassvartype(p);
if(classvartype == -1)
return NULL;
next(p);
CLASSVARDEC* classvardec = (CLASSVARDEC*)malloc(sizeof(CLASSVARDEC));
classvardec->type = classvartype;
classvardec->base = (VARDEC*)malloc(sizeof(VARDEC));
parsevardeccommon(p, classvardec->base);
return classvardec;
}
CLASSVARDEC* parseclassvardecs(PARSER* p) {
CLASSVARDEC* head = parseclassvardec(p);
CLASSVARDEC* current = head;
CLASSVARDEC* next;
while(next = parseclassvardec(p), next != NULL) {
current->next = next;
current= next;
}
if(current != NULL)
current->next = NULL;
return head;
}
VARDEC* parsevardec(PARSER* p) {
if(strcmp(p->current->token, "var"))
return NULL;
next(p);
VARDEC* vardec = (VARDEC*)malloc(sizeof(VARDEC));
parsevardeccommon(p, vardec);
return vardec;
}
VARDEC* parsevardecs(PARSER* p) {
VARDEC* head = parsevardec(p);
VARDEC* current = head;
VARDEC* next;
while(next = parsevardec(p), next != NULL) {
current->next = next;
current = next;
}
if(current != NULL)
current->next = NULL;
return head;
}
PARAMETER* parseparameter(PARSER* p) {
PARAMETER* param = (PARAMETER*)malloc(sizeof(PARAMETER));
if(!strcmp(p->current->token, ")"))
return NULL;
bool dummy;
param->type = parsetype(p, &dummy);
param->name = parseidentifier(p);
return param;
}
PARAMETER* parseparameters(PARSER* p) {
PARAMETER* head = parseparameter(p);
PARAMETER* current = head;
while(!strcmp(p->current->token, ",")) {
next(p);
current->next = parseparameter(p);
current = current->next;
}
if(current != NULL)
current->next = NULL;
return head;
}
SUBROUTBODY* parsesubroutbody(PARSER* p) {
SUBROUTBODY* subroutbody = (SUBROUTBODY*)malloc(sizeof(SUBROUTBODY));
subroutbody->vardecs = parsevardecs(p);
subroutbody->statements = parsestatements(p);
return subroutbody;
}
SUBROUTDEC* parsesubroutdec(PARSER* p) {
SUBROUTCLASS subroutclass = parsesubroutclass(p);
if(subroutclass == -1)
return NULL;
next(p);
SUBROUTDEC* subroutdec = (SUBROUTDEC*)malloc(sizeof(SUBROUTDEC));
subroutdec->subroutclass = subroutclass;
subroutdec->typeclass = p->current->type;
if(!strcmp(p->current->token, "void")) {
subroutdec->type = p->current->token;
next(p);
}
else {
bool dummy;
subroutdec->type = parsetype(p, &dummy);
}
subroutdec->debug = getdebug(p);
subroutdec->name = parseidentifier(p);
checkcontent(p, "(");
subroutdec->parameters = parseparameters(p);
checkcontent(p, ")");
checkcontent(p, "{");
subroutdec->body = parsesubroutbody(p);
checkcontent(p, "}");
return subroutdec;
}
SUBROUTDEC* parsesubroutdecs(PARSER* p) {
SUBROUTDEC* head = parsesubroutdec(p);
SUBROUTDEC* current = head;
SUBROUTDEC* next;
while(next = parsesubroutdec(p), next != NULL) {
current->next = next;
current = next;
}
if(current != NULL)
current->next = NULL;
return head;
}
CLASS* parseclass(PARSER* p) {
checkcontent(p, "class");
CLASS* class = (CLASS*)malloc(sizeof(CLASS));
class->debug = getdebug(p);
class->name = parseidentifier(p);
checkcontent(p, "{");
class->vardecs = parseclassvardecs(p);
class->subroutdecs = parsesubroutdecs(p);
checkcontent(p, "}");
class->next = NULL;
return class;
}
#include "parser-structure.h"
// Statements
PARSER* mkparser(TOKEN* tokens, char* file) {
PARSER* parser = (PARSER*)malloc(sizeof(PARSER));
parser->tokens = tokens;
@ -533,5 +15,5 @@ PARSER* mkparser(TOKEN* tokens, char* file) {
}
void parse(PARSER* parser) {
parser->output = parseclass(parser);
parser->output = parseclasses(parser);
}

View File

@ -1,6 +1,5 @@
#ifndef PARSER_H
#define PARSER_H
#include <stdbool.h>
#include "tokenizer.h"
#include "parser-tree.h"

View File

@ -238,7 +238,6 @@ TOKEN* tokenize(FILE* input) {
if(curtype == charsymbol)
append(tmptoken, c);
}
lasttype = curtype;
}

7
util.c
View File

@ -66,3 +66,10 @@ void freestrlist(STRINGLIST* strlist) {
if(next != NULL)
freestrlist(next);
}
bool existsinarray(STRINGARRAY* arr, const char* item) {
for(int i = 0; i < arr->size; i++)
if(!strcmp(arr->items[i], item))
return true;
return false;
}

3
util.h
View File

@ -1,6 +1,7 @@
#ifndef UTIL_H
#define UTIL_H
#include <stdio.h>
#include <stdbool.h>
/* util
* Random utilities. */
@ -29,4 +30,6 @@ void* copy(void* v, int size);
STRINGLIST* initstrlist(const char** strs, int count);
void printstrlist(STRINGLIST* strlist, FILE* stream);
void freestrlist(STRINGLIST* strlist);
bool existsinarray(STRINGARRAY* arr, const char* item);
#endif