Split parser into several files
This commit is contained in:
parent
0b1345d845
commit
351446bb6d
|
@ -10,6 +10,6 @@ typedef struct {
|
||||||
} COMPILER;
|
} COMPILER;
|
||||||
|
|
||||||
COMPILER* mkcompiler(CLASS* classes);
|
COMPILER* mkcompiler(CLASS* classes);
|
||||||
void compile();
|
void compile(COMPILER* c);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
#ifndef PARSER_STATEMENTS_H
|
||||||
|
#define PARSER_STATEMENTS_H
|
||||||
|
#include "parser.h"
|
||||||
|
STATEMENT* parsestatements(PARSER* p);
|
||||||
|
#endif
|
|
@ -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;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
#ifndef PARSER_STRUCTURE_H
|
||||||
|
#define PARSER_STRUCTURE_H
|
||||||
|
#include "parser.h"
|
||||||
|
CLASS* parseclasses(PARSER* p);
|
||||||
|
#endif
|
524
parser.c
524
parser.c
|
@ -3,527 +3,9 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "parser-constants.h"
|
#include "parser-structure.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Statements
|
||||||
PARSER* mkparser(TOKEN* tokens, char* file) {
|
PARSER* mkparser(TOKEN* tokens, char* file) {
|
||||||
PARSER* parser = (PARSER*)malloc(sizeof(PARSER));
|
PARSER* parser = (PARSER*)malloc(sizeof(PARSER));
|
||||||
parser->tokens = tokens;
|
parser->tokens = tokens;
|
||||||
|
@ -533,5 +15,5 @@ PARSER* mkparser(TOKEN* tokens, char* file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse(PARSER* parser) {
|
void parse(PARSER* parser) {
|
||||||
parser->output = parseclass(parser);
|
parser->output = parseclasses(parser);
|
||||||
}
|
}
|
||||||
|
|
1
parser.h
1
parser.h
|
@ -1,6 +1,5 @@
|
||||||
#ifndef PARSER_H
|
#ifndef PARSER_H
|
||||||
#define PARSER_H
|
#define PARSER_H
|
||||||
#include <stdbool.h>
|
|
||||||
#include "tokenizer.h"
|
#include "tokenizer.h"
|
||||||
#include "parser-tree.h"
|
#include "parser-tree.h"
|
||||||
|
|
||||||
|
|
|
@ -238,7 +238,6 @@ TOKEN* tokenize(FILE* input) {
|
||||||
if(curtype == charsymbol)
|
if(curtype == charsymbol)
|
||||||
append(tmptoken, c);
|
append(tmptoken, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
lasttype = curtype;
|
lasttype = curtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
util.c
7
util.c
|
@ -66,3 +66,10 @@ void freestrlist(STRINGLIST* strlist) {
|
||||||
if(next != NULL)
|
if(next != NULL)
|
||||||
freestrlist(next);
|
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
3
util.h
|
@ -1,6 +1,7 @@
|
||||||
#ifndef UTIL_H
|
#ifndef UTIL_H
|
||||||
#define UTIL_H
|
#define UTIL_H
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
/* util
|
/* util
|
||||||
* Random utilities. */
|
* Random utilities. */
|
||||||
|
@ -29,4 +30,6 @@ void* copy(void* v, int size);
|
||||||
STRINGLIST* initstrlist(const char** strs, int count);
|
STRINGLIST* initstrlist(const char** strs, int count);
|
||||||
void printstrlist(STRINGLIST* strlist, FILE* stream);
|
void printstrlist(STRINGLIST* strlist, FILE* stream);
|
||||||
void freestrlist(STRINGLIST* strlist);
|
void freestrlist(STRINGLIST* strlist);
|
||||||
|
|
||||||
|
bool existsinarray(STRINGARRAY* arr, const char* item);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue