diff --git a/src/extstring.c b/src/extstring.c index ba7adcb..25c941f 100644 --- a/src/extstring.c +++ b/src/extstring.c @@ -2,53 +2,81 @@ #include "extstring.h" void es_addsymbol(tExtstring* string, char symbol) { + if (string == NULL) return; + tExtstring* ptr = string; + while (ptr->next != NULL) { ptr = ptr->next; }; + ptr->next = malloc(sizeof(tExtstring)); ptr->next->symbol = symbol; ptr->next->next = NULL; + return; + } int es_size(tExtstring* string) { + int size = 0; + tExtstring* ptr = string; + for (; ptr != NULL; size++) { ptr = ptr->next; } + return size; } void es_free(tExtstring* string) { + if (string->next == NULL) { + free(string); + return; + } + tExtstring* ptr = string; tExtstring* nextptr = ptr->next; + while (ptr->next != NULL) { + nextptr = ptr->next; free(ptr); ptr = nextptr; + } + free(ptr); + } char* es_tostring(tExtstring* string) { + tExtstring* ptr = string; + int size = es_size(string) + 1; + char* cstring = malloc(size); + for (int i = 0; i != size; i++) { + if (ptr != NULL) { cstring[i] = ptr->symbol; ptr = ptr->next; } + else cstring[i] = 0; } + return cstring; + } diff --git a/src/extstring.h b/src/extstring.h index 6c77c33..0c5dd0c 100644 --- a/src/extstring.h +++ b/src/extstring.h @@ -3,7 +3,11 @@ typedef struct Extstring { struct Extstring* next; } tExtstring; + void es_addsymbol(tExtstring* string, char symbol); + int es_size(tExtstring* string); + void es_free(tExtstring* string); + char* es_tostring(tExtstring* string); diff --git a/src/main.c b/src/main.c index 3dd83c5..82ca480 100644 --- a/src/main.c +++ b/src/main.c @@ -7,6 +7,7 @@ #include "process.h" int main(int argc, char *argv[]) { + FILE *file; if (argc != 2) { fprintf(stderr, @@ -14,23 +15,30 @@ int main(int argc, char *argv[]) { "%s FILENAME\n", argv[0]); return 1; } + file = fopen(argv[1],"r"); if (file == NULL) { fprintf(stderr,"Unable to open file.\n"); return 1; } + tSyntaxElement* code = parse(file); fclose(file); + if (code == NULL) { fprintf(stderr, "Error during parsing.\n"); return 1; } + printf("Parsed: \n"); printtree(code,1); + printf("\nProcessed: \n"); process(code, NULL); printtree(code,1); + se_free(code); code = NULL; + return 0; } diff --git a/src/parser.c b/src/parser.c index eb44a5e..a0653f2 100644 --- a/src/parser.c +++ b/src/parser.c @@ -3,130 +3,190 @@ #include #include -#ifdef DEBUG -#include "printtree.h" -#endif #include "parser.h" #include "extstring.h" +#ifdef DEBUG + #include "printtree.h" +#endif + tSyntaxElement* parse(FILE* file) { + tSyntaxElement* syntaxtree = se_create(); tSyntaxElement* syntaxtreestart = syntaxtree; syntaxtree->type = NEWTREE; + char symbol; bool intree = false; bool incomment = false; bool instring = false; bool intoken = false; + tExtstring* exttoken = NULL; tExtstring* extstring = NULL; + while (1) { symbol = fgetc(file); + #ifdef DEBUG - if (!isspace(symbol)) - printf("In parsing. Current symbol: %c\n", symbol); - else - printf("In parsing. Current symbol: %d\n", symbol); - printtree(syntaxtreestart, 1); + + if (!isspace(symbol)) + printf("In parsing. Current symbol: %c\n", symbol); + else + printf("In parsing. Current symbol: %d\n", symbol); + + printtree(syntaxtreestart, 1); + #endif + if (feof(file)) break; + if (incomment) { if (symbol == '\n') incomment = false; continue; } + if (instring) { if (symbol == '"') { + if (extstring == NULL) { extstring = malloc(sizeof(tExtstring)); extstring->next = NULL; } + instring = false; + syntaxtree->type = STRING; char* string = es_tostring(extstring); syntaxtree->content.string = string; + es_free(extstring); extstring = NULL; + } else { + if (extstring == NULL) { + extstring = malloc(sizeof(tExtstring)); extstring->symbol = symbol; extstring->next = NULL; + continue; } + es_addsymbol(extstring, symbol); } continue; } if (intoken) { if (isspace(symbol) || symbol == '(' || symbol == ')') { + intoken = false; + syntaxtree->type = TOKEN; char* string = es_tostring(exttoken); syntaxtree->content.string = string; + es_free(exttoken); exttoken = NULL; + } else { + es_addsymbol(exttoken, symbol); + continue; } } + if (isspace(symbol)) continue; + if (intree) { switch (symbol) { + case '(': + syntaxtree = se_next(syntaxtree); syntaxtree->type = TREE; + syntaxtree = se_bottom(syntaxtree); syntaxtree->type = NEWTREE; + break; + case ')': + syntaxtree = syntaxtree->top; + if (syntaxtree->top == NULL) intree = false; break; + case ';': + incomment = true; continue; + case '"': + syntaxtree = se_next(syntaxtree); instring = true; continue; + default: + syntaxtree = se_next(syntaxtree); + exttoken = malloc(sizeof(tExtstring)); exttoken->symbol = symbol; exttoken->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_next(syntaxtree); syntaxtree->type = TREE; + syntaxtree = se_bottom(syntaxtree); syntaxtree->type = NEWTREE; + continue; + default: + fprintf(stderr, "Expression outside of brackets.\n"); return NULL; } } } + if (intree) { + fprintf(stderr, "Unexpected EOF.\n"); return NULL; + } + return syntaxtreestart; } diff --git a/src/printtree.c b/src/printtree.c index 3271a71..9aab861 100644 --- a/src/printtree.c +++ b/src/printtree.c @@ -5,29 +5,47 @@ #include "printtree.h" void printtree(tSyntaxElement* syntaxtree, int depth) { + if (syntaxtree == NULL) return; + for (int i = 1; i <= depth; i++) putc(' ',stdout); + switch (syntaxtree->type) { + case TREE: + printf("TREE\n"); printtree(syntaxtree->content.syntax, depth + 1); + break; + case TOKEN: + printf("TOKEN: %s\n", syntaxtree->content.string); break; + case STRING: + printf("STRING: %s\n", syntaxtree->content.string); break; + case NONE: + printf("NONE\n"); break; + case NEWTREE: + printf("NEWTREE\n"); break; + } + if (syntaxtree->next != NULL) printtree(syntaxtree->next, depth); + return; + } diff --git a/src/printtree.h b/src/printtree.h index 27221de..3dc8798 100644 --- a/src/printtree.h +++ b/src/printtree.h @@ -1,2 +1,3 @@ #include "parser.h" + void printtree(tSyntaxElement*, int); diff --git a/src/process.c b/src/process.c index c4ec622..e7c2989 100644 --- a/src/process.c +++ b/src/process.c @@ -6,76 +6,124 @@ #include "process.h" bool replace(tSyntaxElement* tree, tProcessingData* pdata) { + tProcessingData* pd = pdata; + bool didreplace = false; + while (1) { + if (pd->data.replace.replacethis == NULL) break; + if (tree->type == TOKEN) + if (strcmp(tree->content.string, pd->data.replace.replacethis) == 0) { + didreplace = true; + free(tree->content.none); + tSyntaxElement* clone = se_clone_no_next(pd->data.replace.replacewiththis, tree); tree->content = clone->content; tree->type = clone->type; + } + if (pd->prev != NULL) pd = pd->prev; - else - break; + + else break; + } + return didreplace; + } bool process_find(tSyntaxElement* tree, tProcessingData** p_pdata) { + tProcessingData* pd = *p_pdata; + bool deffound = false; + if (se_istraversable(tree)) + if (tree->content.syntax->type == TOKEN && tree->content.syntax->next != NULL && tree->content.syntax->next->next != NULL) { + tSyntaxElement* token = tree->content.syntax; + if (strcmp(token->content.string,"def") == 0) { + char* replacethis = token->next->content.string; + tSyntaxElement* replacewiththis = token->next->next; + tProcessingData* npd = malloc(sizeof(tSyntaxElement)); + npd->type = REPLACE; npd->data.replace.replacethis = replacethis; npd->data.replace.replacewiththis = replacewiththis; npd->prev = pd; + *p_pdata = npd; + deffound = true; + } + } + return deffound; + } + void process(tSyntaxElement* tree, tProcessingData* pdata) { + tProcessingData* pd = pdata; + bool deffound = false; + tProcessingData* firstpd = NULL; + if (pd == NULL) { + pd = calloc(1,sizeof(tProcessingData)); firstpd = pd; + } + deffound = process_find(tree, &pd); + if (tree->next != NULL) { process(tree->next, pd); } + if (!deffound) { - if (se_istraversable(tree)) { + + if (se_istraversable(tree)) process(tree->content.syntax, pd); - } + switch (pd->type) { + case REPLACE: replace(tree, pd); break; - case FUNCTION: + + case FUNCTION: // TODO break; + } + } + if (pd != pdata) free(pd); + if (firstpd != pd && firstpd != NULL) free(firstpd); + } diff --git a/src/process.h b/src/process.h index 51997f2..66e10ff 100644 --- a/src/process.h +++ b/src/process.h @@ -2,33 +2,45 @@ #include "syntax.h" typedef enum { + REPLACE, FUNCTION + } tProcessingType; typedef struct { + char* replacethis; tSyntaxElement* replacewiththis; + } tProcessingReplace; typedef struct { + char** args; tSyntaxElement* body; + } tProcessingFunction; typedef union { + tProcessingReplace replace; tProcessingFunction function; + } tuProcessingData; typedef struct ProcessingData { + struct ProcessingData* prev; tProcessingType type; tuProcessingData data; + } tProcessingData; + + void process(tSyntaxElement*, tProcessingData*); diff --git a/src/syntax.c b/src/syntax.c index 673c72f..b59407b 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -4,94 +4,141 @@ #include "syntax.h" bool se_istraversable(tSyntaxElement* syntaxtree) { + return syntaxtree->type == TREE && syntaxtree->content.syntax != NULL; + } tSyntaxElement* se_create(void) { + tSyntaxElement* syntaxelement = malloc(sizeof(tSyntaxElement)); + syntaxelement->type = NONE; syntaxelement->content.none = NULL; syntaxelement->next = NULL; syntaxelement->top = NULL; + return syntaxelement; } tSyntaxElement* se_bottom(tSyntaxElement* syntaxelement) { + syntaxelement->content.syntax = se_create(); syntaxelement->content.syntax->top = syntaxelement; + return syntaxelement->content.syntax; + } tSyntaxElement* se_next(tSyntaxElement* syntaxelement) { + if (syntaxelement->type != NEWTREE) { + syntaxelement->next = se_create(); syntaxelement->next->top = syntaxelement->top; + return syntaxelement->next; - } else { + + } else return syntaxelement; - } + } void se_free(tSyntaxElement* syntaxtree) { + switch (syntaxtree->type) { + case NONE: + free(syntaxtree); return; + case TREE: + if (syntaxtree->content.syntax != NULL) { se_free(syntaxtree->content.syntax); } + break; + default: + free(syntaxtree->content.none); break; + } + if (syntaxtree->next != NULL) { se_free(syntaxtree->next); } + free(syntaxtree); + } tSyntaxElement* se_clone(tSyntaxElement* syntaxelement, tSyntaxElement* newtop) { + tSyntaxElement* clone = NULL; + switch (syntaxelement->type) { + case TREE: + clone = se_create(); clone->type = TREE; + if (syntaxelement->content.syntax != NULL) clone->content.syntax = se_clone(syntaxelement->content.syntax, clone); + if (syntaxelement->next != NULL) clone->next = se_clone(syntaxelement->next, newtop); + break; + case TOKEN: case STRING: + clone = se_create(); clone->type = syntaxelement->type; + clone->content.string = malloc(strlen(syntaxelement->content.string)); strcpy(clone->content.string, syntaxelement->content.string); + if (syntaxelement->next != NULL) clone->next = se_clone(syntaxelement->next, newtop); + break; + case NONE: case NEWTREE: + clone = se_create(); clone->type = syntaxelement->type; clone->top = newtop; + if (syntaxelement->next != NULL) clone->next = se_clone(syntaxelement->next, newtop); + break; } + return clone; } tSyntaxElement* se_clone_no_next(tSyntaxElement* syntaxelement, tSyntaxElement* newtop) { + tSyntaxElement* se = malloc(sizeof(tSyntaxElement)); + se->content = syntaxelement->content; se->top = syntaxelement->top; se->type = syntaxelement->type; se->next = NULL; + tSyntaxElement* clone = se_clone(se, newtop); + free(se); + return clone; + } diff --git a/src/syntax.h b/src/syntax.h index 74e7bf8..73e342d 100644 --- a/src/syntax.h +++ b/src/syntax.h @@ -1,34 +1,50 @@ #ifndef SYNTAX_H #define SYNTAX_H + #include enum SyntaxElementType { + NEWTREE, TREE, TOKEN, STRING, NONE + }; typedef union { + struct SyntaxElement* syntax; char* string; void* none; + } tSyntaxContent; typedef struct SyntaxElement { + enum SyntaxElementType type; tSyntaxContent content; struct SyntaxElement* next; struct SyntaxElement* top; + } tSyntaxElement; + void se_free(tSyntaxElement*); + bool se_istraversable(tSyntaxElement*); + tSyntaxElement* se_create(void); + tSyntaxElement* se_init(void); + tSyntaxElement* se_bottom(tSyntaxElement*); + tSyntaxElement* se_next(tSyntaxElement*); + tSyntaxElement* se_clone(tSyntaxElement*, tSyntaxElement*); + tSyntaxElement* se_clone_no_next(tSyntaxElement*, tSyntaxElement*); + #endif