Split parser into several files
This commit is contained in:
parent
0b1345d845
commit
351446bb6d
|
@ -10,6 +10,6 @@ typedef struct {
|
|||
} COMPILER;
|
||||
|
||||
COMPILER* mkcompiler(CLASS* classes);
|
||||
void compile();
|
||||
void compile(COMPILER* c);
|
||||
|
||||
#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 <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);
|
||||
}
|
||||
|
|
1
parser.h
1
parser.h
|
@ -1,6 +1,5 @@
|
|||
#ifndef PARSER_H
|
||||
#define PARSER_H
|
||||
#include <stdbool.h>
|
||||
#include "tokenizer.h"
|
||||
#include "parser-tree.h"
|
||||
|
||||
|
|
|
@ -238,7 +238,6 @@ TOKEN* tokenize(FILE* input) {
|
|||
if(curtype == charsymbol)
|
||||
append(tmptoken, c);
|
||||
}
|
||||
|
||||
lasttype = curtype;
|
||||
}
|
||||
|
||||
|
|
7
util.c
7
util.c
|
@ -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
3
util.h
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue