#include #include #include #include #include "parser.h" #include "extstring.h" struct SyntaxElement* se_init(void) { struct SyntaxElement* syntaxelement = malloc(sizeof(struct SyntaxElement)); syntaxelement->type = NONE; syntaxelement->content = NULL; syntaxelement->next = NULL; syntaxelement->top = NULL; return syntaxelement; } struct SyntaxElement* se_bottom(struct SyntaxElement* syntaxelement) { syntaxelement->content = se_init(); ((struct SyntaxElement*)syntaxelement->content)->top = syntaxelement; return ((struct SyntaxElement*)syntaxelement->content); } struct SyntaxElement* se_next(struct SyntaxElement* syntaxelement) { syntaxelement->next = se_init(); syntaxelement->next->top = syntaxelement->top; return syntaxelement->next; } void se_free(struct SyntaxElement* syntaxtree) { switch (syntaxtree->type) { case NONE: free(syntaxtree); return; case TREE: case TOPTREE: if (syntaxtree->content != NULL) { se_free((struct SyntaxElement*)syntaxtree->content); } break; default: free(syntaxtree->content); break; } if (syntaxtree->next != NULL) { se_free(syntaxtree->next); } free(syntaxtree); } void se_clean(struct SyntaxElement* syntaxtree) { if (syntaxtree->next != NULL) { switch (syntaxtree->next->type) { case NONE: free(syntaxtree->next); syntaxtree->next = NULL; break; default: se_clean(syntaxtree->next); break; } } if (syntaxtree->content != NULL && (syntaxtree->type == TOPTREE || syntaxtree->type == TREE)) { switch (((struct SyntaxElement*)syntaxtree->content)->type) { case NONE: free(syntaxtree->content); syntaxtree->content = NULL; break; default: se_clean((struct SyntaxElement*)syntaxtree->content); break; } } } struct SyntaxElement* parse(FILE* file) { struct SyntaxElement* syntaxtree = se_init(); struct SyntaxElement* syntaxtreestart = syntaxtree; syntaxtree->type = TOPTREE; char symbol; bool intree = false; bool incomment = false; bool instring = false; bool intoken = false; struct Extstring* token = NULL; struct Extstring* string = NULL; while (1) { symbol = fgetc(file); if (feof(file)) break; if (incomment) { if (symbol == '\n') incomment = false; continue; } if (instring) { if (symbol == '"') { if (string == NULL) { string = malloc(sizeof(struct Extstring)); string->next = NULL; } instring = false; syntaxtree->type = STRING; char* sstring = es_tostring(string); syntaxtree->content = sstring; es_free(string); string = NULL; syntaxtree = se_next(syntaxtree); } else { if (string == NULL) { string = malloc(sizeof(struct Extstring)); string->symbol = symbol; string->next = NULL; continue; } es_addsymbol(string, symbol); } continue; } if (intoken) { if (isspace(symbol) || symbol == '(' || symbol == ')') { intoken = false; syntaxtree->type = TOKEN; char* sstring = es_tostring(token); syntaxtree->content = sstring; es_free(token); token = NULL; syntaxtree = se_next(syntaxtree); } else { es_addsymbol(token, symbol); continue; } } if (isspace(symbol)) continue; if (intree) { switch (symbol) { case '(': syntaxtree = se_bottom(syntaxtree); break; case ')': if (syntaxtree->top->type == TOPTREE) { intree = false; syntaxtree = syntaxtree->top; syntaxtree = se_next(syntaxtree); syntaxtree->type = TOPTREE; } else { syntaxtree = syntaxtree->top; syntaxtree = se_next(syntaxtree); syntaxtree->type = TREE; } break; case ';': incomment = true; continue; case '"': instring = true; continue; default: token = malloc(sizeof(struct Extstring)); token->symbol = symbol; token->next = NULL; intoken = true; break; } continue; } else { switch (symbol) { case ')': fprintf(stderr, "Unbalanced brackets.\n"); return NULL; case ';': incomment = true; continue; case '(': intree = true; syntaxtree = se_bottom(syntaxtree); syntaxtree->type = TREE; continue; default: fprintf(stderr, "Expression outside of brackets.\n"); return NULL; } } } if (intree) { fprintf(stderr, "Unexpected EOF.\n"); return NULL; } syntaxtree = syntaxtreestart; while (1) { if (syntaxtree->next->next == NULL) { free(syntaxtree->next); syntaxtree->next = NULL; break; } syntaxtree = syntaxtree->next; } se_clean(syntaxtreestart); return syntaxtreestart; }