Add parser

This commit is contained in:
Augusto Gunsch 2020-12-14 16:12:20 -03:00
parent eb7778c267
commit 5b19ab0914
No known key found for this signature in database
GPG Key ID: F7EEFE29825C72DC
8 changed files with 1146 additions and 34 deletions

View File

@ -1,4 +1,4 @@
FILES = tokenizer.c main.c parser.c FILES = tokenizer.c main.c parser.c printer.c
INCLUDES = -I. INCLUDES = -I.
CFLAGS = -std=c99 -g CFLAGS = -std=c99 -g
OUTFILE = compiler OUTFILE = compiler

24
main.c
View File

@ -3,19 +3,8 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "tokenizer.h" #include "tokenizer.h"
#include "printer.h"
const char* types[] = { #include "parser.h"
"keyword", "symbol", "integerConstant", "stringConstant", "identifier"
};
void printtks(TOKENLIST* tks, FILE* output) {
fprintf(output, "<%s> %s </%s>\r\n", types[tks->type], tks->token, types[tks->type]);
TOKENLIST* next = tks->next;
free(tks->token);
free(tks);
if(next != NULL)
printtks(next, output);
}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if(argc < 2) { if(argc < 2) {
@ -30,11 +19,10 @@ int main(int argc, char* argv[]) {
return errno; return errno;
} }
FILE* output = fopen("out.xml", "w"); PARSER* p = mkparser(tokenize(input), argv[1]);
fprintf(output, "<tokens>\r\n"); parse(p);
printtks(tokenize(input), output);
fprintf(output, "</tokens>\r\n"); printparser(stdout, p);
fclose(output);
return 0; return 0;
} }

542
parser.c
View File

@ -0,0 +1,542 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "parser.h"
char* parseidentifier(PARSER* p);
STATEMENT* parsestatements(PARSER* p);
SUBROUTCALL* parsesubroutcall(PARSER* p);
TERM* parseexpression(PARSER* p);
TERM* parseterm(PARSER* p);
const char* keywordconstants[] = {
"true", "false", "null", "this"
};
const int keywordconstantssize = sizeof(keywordconstants) / sizeof(char*);
const char* ops[] = {
"+", "-", "*", "/", "&", "|", "<", ">", "="
};
const int opssize = sizeof(ops) / sizeof(char*);
const char* varclasses[] = {
"static", "field"
};
const int varclassessize = sizeof(varclasses) / sizeof(char*);
const char* vardectypes[] = {
"int", "char", "boolean"
};
const int vardectypessize = sizeof(vardectypes) / sizeof(char*);
const char* subroutclasses[] = {
"constructor", "function", "method"
};
const int subroutclassessize = sizeof(subroutclasses) / sizeof(char*);
const char* tokentypes[] = {
"keyword", "identifier", "symbol", "integerConstant", "stringConstant"
};
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[p->current->type], p->current->truen, 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[p->current->type], p->current->truen, 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 < keywordconstantssize; i++)
if(!strcmp(p->current->token, keywordconstants[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;
t->unaryop = p->current->token[0];
next(p);
t->expression = parseterm(p);
} 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 < opssize; i++)
if(!strcmp(t->token, ops[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 = parsetermnullified(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->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->letst = parselet(p);
} else if(!strcmp(p->current->token, "if")) {
next(p);
st->type = ifstatement;
st->ifst = parseif(p);
} else if(!strcmp(p->current->token, "while")) {
next(p);
st->type = whilestatement;
st->whilest = parsecond(p);
} else if(!strcmp(p->current->token, "do")) {
next(p);
st->type = dostatement;
st->dost = parsesubroutcall(p);
checkcontent(p, ";");
} else if(!strcmp(p->current->token, "return")) {
next(p);
st->type = returnstatement;
if(strcmp(p->current->token, ";")) {
st->retst = parseexpressionnullified(p);
checkcontent(p, ";");
}
else {
st->retst = 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) {
char* result = p->current->token;
if(p->current->type == keyword)
for(int i = 0; i < vardectypessize; i++) {
if(!strcmp(p->current->token, vardectypes[i])) {
next(p);
return result;
}
}
else if (p->current->type == identifier) {
next(p);
return result;
}
else
unexpected(p);
}
int parsepossibilities(PARSER* p, const char** strings, int sz) {
for(int i = 0; i < sz; i++)
if(!strcmp(p->current->token, strings[i]))
return i;
return -1;
}
VARCLASS parsevarclass(PARSER* p) {
return parsepossibilities(p, varclasses, varclassessize);
}
SUBROUTCLASS parsesubroutclass(PARSER* p) {
return parsepossibilities(p, subroutclasses, subroutclassessize);
}
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);
STRINGLIST* currstr = (STRINGLIST*)malloc(sizeof(STRINGLIST));
v->names = currstr;
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) {
VARCLASS varclass = parsevarclass(p);
if(varclass == -1)
return NULL;
next(p);
CLASSVARDEC* classvardec = (CLASSVARDEC*)malloc(sizeof(CLASSVARDEC));
classvardec->varclass = varclass;
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;
param->type = parsetype(p);
param->name = parseidentifier(p);
return param;
}
PARAMETER* parseparameters(PARSER* p) {
PARAMETER* head = parseparameter(p);
PARAMETER* current = head;
while(!strcmp(p->current->token, ",")) {
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;
}
SUBDEC* parsesubroutdec(PARSER* p) {
SUBROUTCLASS subroutclass = parsesubroutclass(p);
if(subroutclass == -1)
return NULL;
next(p);
SUBDEC* subdec = (SUBDEC*)malloc(sizeof(SUBDEC));
subdec->subroutclass = subroutclass;
subdec->typeclass = p->current->type;
if(!strcmp(p->current->token, "void")) {
subdec->type = p->current->token;
next(p);
}
else
subdec->type = parsetype(p);
subdec->name = parseidentifier(p);
checkcontent(p, "(");
subdec->parameters = parseparameters(p);
checkcontent(p, ")");
checkcontent(p, "{");
subdec->body = parsesubroutbody(p);
checkcontent(p, "}");
return subdec;
}
SUBDEC* parsesubroutdecs(PARSER* p) {
SUBDEC* head = parsesubroutdec(p);
SUBDEC* current= head;
SUBDEC* 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->name = parseidentifier(p);
checkcontent(p, "{");
class->vardecs = parseclassvardecs(p);
class->subdecs = parsesubroutdecs(p);
checkcontent(p, "}");
return class;
}
PARSER* mkparser(TOKEN* tokens, char* file) {
PARSER* parser = (PARSER*)malloc(sizeof(PARSER));
parser->tokens = tokens;
parser->current = tokens;
parser->file = file;
return parser;
}
void parse(PARSER* parser) {
parser->output = parseclass(parser);
}

132
parser.h
View File

@ -0,0 +1,132 @@
#ifndef PARSER_H
#define PARSER_H
#include "tokenizer.h"
struct statement;
struct explist;
typedef enum {
ifstatement, whilestatement, letstatement, dostatement, returnstatement
} STATEMENTTYPE;
typedef enum {
varname, intconstant, stringconstant, keywordconstant, arrayitem, subroutcall, innerexpression, unaryopterm
} TERMTYPE;
typedef struct {
char* parentname;
char* name;
struct explist* parameters;
} SUBROUTCALL;
typedef struct term {
TERMTYPE type;
union {
char* string;
int integer;
SUBROUTCALL* call;
struct term* expression;
};
char unaryop;
struct term* arrayexp;
char op;
struct term* next;
} TERM;
typedef struct explist {
TERM* expression;
struct explist* next;
} EXPRESSIONLIST;
typedef struct {
TERM* expression;
struct statement* statements;
} CONDSTATEMENT;
typedef struct {
CONDSTATEMENT* base;
struct statement* elsestatements;
} IFSTATEMENT;
typedef struct {
char* varname;
TERM* arrayind;
TERM* expression;
} LETSTATEMENT;
typedef struct statement {
STATEMENTTYPE type;
union {
CONDSTATEMENT* whilest;
IFSTATEMENT* ifst;
LETSTATEMENT* letst;
SUBROUTCALL* dost;
TERM* retst;
};
struct statement* next;
} STATEMENT;
typedef enum {
stat, field
} VARCLASS;
typedef struct stringlist {
char* content;
struct stringlist* next;
} STRINGLIST;
typedef struct vardec {
char* type;
TOKENTYPE typeclass;
STRINGLIST* names;
struct vardec* next;
} VARDEC;
typedef struct classvardec {
VARCLASS varclass;
VARDEC* base;
struct classvardec* next;
} CLASSVARDEC;
typedef enum {
constructor, function, method
} SUBROUTCLASS;
typedef struct parameter {
char* type;
char* name;
struct parameter* next;
} PARAMETER;
typedef struct SUBROUTBODY {
VARDEC* vardecs;
STATEMENT* statements;
} SUBROUTBODY;
typedef struct subdec {
SUBROUTCLASS subroutclass;
char* type;
TOKENTYPE typeclass;
char* name;
PARAMETER* parameters;
SUBROUTBODY* body;
struct subdec* next;
} SUBDEC;
typedef struct {
char* name;
CLASSVARDEC* vardecs;
SUBDEC* subdecs;
} CLASS;
typedef struct {
TOKEN* tokens;
TOKEN* current;
TOKEN* checkpoint;
char* file;
CLASS* output;
} PARSER;
PARSER* mkparser(TOKEN* tokens, char* file);
void parse(PARSER* parser);
#endif

443
printer.c Normal file
View File

@ -0,0 +1,443 @@
#include "printer.h"
void printexpression(TERM* e, FILE* output, int depth);
void printstatements(STATEMENT* st, FILE* output, int depth);
const char* tmpvarclasses[] = {
"static", "field"
};
const int tmpvarclassessize = sizeof(tmpvarclasses) / sizeof(char*);
const char* tmpsubroutclasses[] = {
"constructor", "function", "method"
};
const int tmpsubroutclassessize = sizeof(tmpsubroutclasses) / sizeof(char*);
const char* tmptokentypes[] = {
"keyword", "identifier"
};
void printident(FILE* output, int depth) {
for(int i = 0; i < depth; i++)
fprintf(output, " ");
}
void printstringlist(FILE* output, int depth, STRINGLIST* ls) {
printident(output, depth);
fprintf(output, "<identifier> %s </identifier>\r\n", ls->content);
if(ls->next != NULL) {
printident(output, depth);
fprintf(output, "<symbol> , </symbol>\r\n");
printstringlist(output, depth, ls->next);
}
}
void printvardec(VARDEC* vd, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<%s> %s </%s>\r\n", tmptokentypes[vd->typeclass], vd->type, tmptokentypes[vd->typeclass]);
printstringlist(output, depth, vd->names);
printident(output, depth);
fprintf(output, "<symbol> ; </symbol>\r\n");
}
void printvardecs(VARDEC* vd, FILE* output, int depth) {
VARDEC* current = vd;
while(current != NULL) {
printident(output, depth);
fprintf(output, "<varDec>\r\n");
printident(output, depth+1);
fprintf(output, "<keyword> var </keyword>\r\n");
printvardec(current, output, depth+1);
current = current->next;
printident(output, depth);
fprintf(output, "</varDec>\r\n");
}
}
void printclassvardec(CLASSVARDEC* vd, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<keyword> %s </keyword>\r\n", tmpvarclasses[vd->varclass]);
printvardec(vd->base, output, depth);
}
void printclassvardecs(CLASSVARDEC* vd, FILE* output, int depth) {
CLASSVARDEC* current = vd;
while(current != NULL) {
printident(output, depth);
fprintf(output, "<classVarDec>\r\n");
printclassvardec(current, output, depth+1);
current = current->next;
printident(output, depth);
fprintf(output, "</classVarDec>\r\n");
}
}
void printparameter(PARAMETER* p, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<keyword> %s </keyword>\r\n", p->type);
printident(output, depth);
fprintf(output, "<identifier> %s </identifier>\r\n", p->name);
if(p->next != NULL) {
printident(output, depth);
fprintf(output, "<symbol> , </symbol>\r\n");
}
}
void printparameters(PARAMETER* p, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<parameterList>\r\n");
PARAMETER* current = p;
while(current != NULL) {
printparameter(current, output, depth+1);
current = current->next;
}
printident(output, depth);
fprintf(output, "</parameterList>\r\n");
}
void printexpressionlist(EXPRESSIONLIST* list, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<expressionList>\r\n");
if(list != NULL) {
EXPRESSIONLIST* current = list;
while(current != NULL) {
printexpression(current->expression, output, depth+1);
current = current->next;
if(current != NULL) {
printident(output, depth+1);
fprintf(output, "<symbol> , </symbol>\r\n");
}
}
}
printident(output, depth);
fprintf(output, "</expressionList>\r\n");
}
void printsubroutcall(SUBROUTCALL* c, FILE* output, int depth) {
if(c->parentname != NULL) {
printident(output, depth);
fprintf(output, "<identifier> %s </identifier>\r\n", c->parentname);
printident(output, depth);
fprintf(output, "<symbol> . </symbol>\r\n");
}
printident(output, depth);
fprintf(output, "<identifier> %s </identifier>\r\n", c->name);
printident(output, depth);
fprintf(output, "<symbol> ( </symbol>\r\n");
printexpressionlist(c->parameters, output, depth);
printident(output, depth);
fprintf(output, "<symbol> ) </symbol>\r\n");
}
void printterm(TERM* e, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<term>\r\n");
if(e->type == varname) {
printident(output, depth+1);
fprintf(output, "<identifier> %s </identifier>\r\n", e->string);
} else if(e->type == subroutcall) {
printsubroutcall(e->call, output, depth+1);
} else if(e->type == stringconstant) {
printident(output, depth+1);
fprintf(output, "<stringConstant> %s </stringConstant>\r\n", e->string);
} else if(e->type == keywordconstant) {
printident(output, depth+1);
fprintf(output, "<keyword> %s </keyword>\r\n", e->string);
} else if(e->type == intconstant) {
printident(output, depth+1);
fprintf(output, "<integerConstant> %i </integerConstant>\r\n", e->integer);
} else if(e->type == arrayitem) {
printident(output, depth+1);
fprintf(output, "<identifier> %s </identifier>\r\n", e->string);
printident(output, depth+1);
fprintf(output, "<symbol> [ </symbol>\r\n");
printexpression(e->arrayexp, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> ] </symbol>\r\n");
} else if(e->type == innerexpression) {
printident(output, depth+1);
fprintf(output, "<symbol> ( </symbol>\r\n");
printexpression(e->expression, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> ) </symbol>\r\n");
} else {
printident(output, depth+1);
fprintf(output, "<symbol> %c </symbol>\r\n", e->unaryop);
printterm(e->expression, output, depth+1);
}
printident(output, depth);
fprintf(output, "</term>\r\n");
if(e->next != NULL) {
printident(output, depth);
fprintf(output, "<symbol> %c </symbol>\r\n", e->op);
}
}
void printexpression(TERM* e, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<expression>\r\n");
TERM* current = e;
while(current != NULL) {
printterm(current, output, depth+1);
current = current->next;
}
printident(output, depth);
fprintf(output, "</expression>\r\n");
}
void printcond(CONDSTATEMENT* st, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<symbol> ( </symbol>\r\n");
printexpression(st->expression, output, depth);
printident(output, depth);
fprintf(output, "<symbol> ) </symbol>\r\n");
printident(output, depth);
fprintf(output, "<symbol> { </symbol>\r\n");
printstatements(st->statements, output, depth);
printident(output, depth);
fprintf(output, "<symbol> } </symbol>\r\n");
}
void printif(IFSTATEMENT* st, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<ifStatement>\r\n");
printident(output, depth+1);
fprintf(output, "<keyword> if </keyword>\r\n");
printcond(st->base, output, depth+1);
if(st->elsestatements != NULL) {
printident(output, depth+1);
fprintf(output, "<keyword> else </keyword>\r\n");
printident(output, depth+1);
fprintf(output, "<symbol> { </symbol>\r\n");
printstatements(st->elsestatements, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> } </symbol>\r\n");
}
printident(output, depth);
fprintf(output, "</ifStatement>\r\n");
}
void printwhile(CONDSTATEMENT* st, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<whileStatement>\r\n");
printident(output, depth+1);
fprintf(output, "<keyword> while </keyword>\r\n");
printcond(st, output, depth+1);
printident(output, depth);
fprintf(output, "</whileStatement>\r\n");
}
void printlet(LETSTATEMENT* st, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<letStatement>\r\n");
printident(output, depth+1);
fprintf(output, "<keyword> let </keyword>\r\n");
printident(output, depth+1);
fprintf(output, "<identifier> %s </identifier>\r\n", st->varname);
if(st->arrayind != NULL) {
printident(output, depth+1);
fprintf(output, "<symbol> [ </symbol>\r\n");
printexpression(st->arrayind, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> ] </symbol>\r\n");
}
printident(output, depth+1);
fprintf(output, "<symbol> = </symbol>\r\n");
printexpression(st->expression, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> ; </symbol>\r\n");
printident(output, depth);
fprintf(output, "</letStatement>\r\n");
}
void printdo(SUBROUTCALL* st, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<doStatement>\r\n");
printident(output, depth+1);
fprintf(output, "<keyword> do </keyword>\r\n");
printsubroutcall(st, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> ; </symbol>\r\n");
printident(output, depth);
fprintf(output, "</doStatement>\r\n");
}
void printreturn(TERM* st, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<returnStatement>\r\n");
printident(output, depth+1);
fprintf(output, "<keyword> return </keyword>\r\n");
if(st != NULL)
printexpression(st, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> ; </symbol>\r\n");
printident(output, depth);
fprintf(output, "</returnStatement>\r\n");
}
void printstatement(STATEMENT* st, FILE* output, int depth) {
if(st->type == ifstatement)
printif(st->ifst, output, depth);
else if(st->type == letstatement)
printlet(st->letst, output, depth);
else if(st->type == whilestatement)
printwhile(st->whilest, output, depth);
else if(st->type == dostatement)
printdo(st->dost, output, depth);
else
printreturn(st->retst, output, depth);
}
void printstatements(STATEMENT* st, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<statements>\r\n");
STATEMENT* current = st;
while(current != NULL) {
printstatement(current, output, depth+1);
current = current->next;
}
printident(output, depth);
fprintf(output, "</statements>\r\n");
}
void printsubroutbody(SUBROUTBODY* bd, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<subroutineBody>\r\n");
printident(output, depth+1);
fprintf(output, "<symbol> { </symbol>\r\n");
printvardecs(bd->vardecs, output, depth+1);
printstatements(bd->statements, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> } </symbol>\r\n");
printident(output, depth);
fprintf(output, "</subroutineBody>\r\n");
}
void printsubroutdec(SUBDEC* sd, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<keyword> %s </keyword>\r\n", tmpsubroutclasses[sd->subroutclass]);
printident(output, depth);
fprintf(output, "<%s> %s </%s>\r\n", tmptokentypes[sd->typeclass], sd->type, tmptokentypes[sd->typeclass]);
printident(output, depth);
fprintf(output, "<identifier> %s </identifier>\r\n", sd->name);
printident(output, depth);
fprintf(output, "<symbol> ( </symbol>\r\n");
printparameters(sd->parameters, output, depth);
printident(output, depth);
fprintf(output, "<symbol> ) </symbol>\r\n");
printsubroutbody(sd->body, output, depth);
}
void printsubroutdecs(SUBDEC* sd, FILE* output, int depth) {
SUBDEC* current = sd;
while(current != NULL) {
printident(output, depth);
fprintf(output, "<subroutineDec>\r\n");
printsubroutdec(current, output, depth+1);
current = current->next;
printident(output, depth);
fprintf(output, "</subroutineDec>\r\n");
}
}
void printclass(CLASS* c, FILE* output, int depth) {
printident(output, depth);
fprintf(output, "<class>\r\n");
printident(output, depth+1);
fprintf(output, "<keyword> class </keyword>\r\n");
printident(output, depth+1);
fprintf(output, "<identifier> %s </identifier>\r\n", c->name);
printident(output, depth+1);
fprintf(output, "<symbol> { </symbol>\r\n");
printclassvardecs(c->vardecs, output, depth+1);
printsubroutdecs(c->subdecs, output, depth+1);
printident(output, depth+1);
fprintf(output, "<symbol> } </symbol>\r\n");
printident(output, depth);
fprintf(output, "</class>\r\n");
}
void printparser(FILE* output, PARSER* p) {
printclass(p->output, output, 0);
}

7
printer.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef PRINTER_H
#define PRINTER_H
#include "parser.h"
void printparser(FILE* output, PARSER* p);
#endif

View File

@ -15,8 +15,8 @@ typedef struct {
int count; int count;
} STRING; } STRING;
TOKENLIST* mktokenlist() { TOKEN* mktokenlist() {
return (TOKENLIST*)malloc(sizeof(TOKENLIST)); return (TOKEN*)malloc(sizeof(TOKEN));
} }
CHARTYPE getchartype(unsigned char c) { CHARTYPE getchartype(unsigned char c) {
@ -97,18 +97,18 @@ TOKENTYPE gettokentype(STRING* tk, int truen) {
exit(1); exit(1);
} }
TOKENLIST* appendtokenraw(TOKENLIST* curitem, STRING* token, int truen, TOKENTYPE type) { TOKEN* appendtokenraw(TOKEN* curitem, STRING* token, int truen, TOKENTYPE type) {
curitem->token = (char*)malloc(sizeof(char)*token->count); curitem->token = (char*)malloc(sizeof(char)*token->count);
strcpy(curitem->token, token->str); strcpy(curitem->token, token->str);
curitem->truen = truen; curitem->truen = truen;
curitem->type = type; curitem->type = type;
TOKENLIST* nextitem = mktokenlist(); TOKEN* nextitem = mktokenlist();
curitem->next = nextitem; curitem->next = nextitem;
token->count = 0; token->count = 0;
return nextitem; return nextitem;
} }
TOKENLIST* appendtoken(TOKENLIST* curitem, STRING* token, int truen) { TOKEN* appendtoken(TOKEN* curitem, STRING* token, int truen) {
append(token, '\0'); append(token, '\0');
return appendtokenraw(curitem, token, truen, gettokentype(token, truen)); return appendtokenraw(curitem, token, truen, gettokentype(token, truen));
} }
@ -168,10 +168,10 @@ void freestr(STRING* str) {
free(str); free(str);
} }
TOKENLIST* tokenize(FILE* input) { TOKEN* tokenize(FILE* input) {
TOKENLIST* head = mktokenlist(); TOKEN* head = mktokenlist();
TOKENLIST* lastitem = head; TOKEN* lastitem = head;
TOKENLIST* curitem = head; TOKEN* curitem = head;
STRING* tmptoken = mkstring(200); STRING* tmptoken = mkstring(200);
CHARTYPE lasttype = space; CHARTYPE lasttype = space;

View File

@ -3,16 +3,16 @@
#include <stdio.h> #include <stdio.h>
typedef enum { typedef enum {
keyword, symbol, integer, string, identifier keyword, identifier, symbol, integer, string
} TOKENTYPE; } TOKENTYPE;
typedef struct tklist { typedef struct token {
char* token; char* token;
TOKENTYPE type; TOKENTYPE type;
int truen; int truen;
struct tklist* next; struct token* next;
} TOKENLIST; } TOKEN;
TOKENLIST* tokenize(FILE* input); TOKEN* tokenize(FILE* input);
void freetokenlist(TOKENLIST l); void freetokenlist(TOKEN l);
#endif #endif