From 06087b10ec7a897ad48db83f7f33a8fc11fa9341 Mon Sep 17 00:00:00 2001 From: Alexander Pickering Date: Wed, 28 Aug 2019 17:28:55 -0400 Subject: Added break statement to templates Added a break statement that can break out of loops, also added some tests to test the functionality of the same. --- src/lexer.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 src/lexer.c (limited to 'src/lexer.c') diff --git a/src/lexer.c b/src/lexer.c new file mode 100644 index 0000000..13f80b8 --- /dev/null +++ b/src/lexer.c @@ -0,0 +1,191 @@ +#include "lexer.h" + +struct TMPL_token* TMPL_alloc_token(void); +void TMPL_free_token(struct TMPL_token* token); +enum TMPL_tagtype starts_with_token(const char* str, size_t strlen); +size_t tagtype_len(enum TMPL_tagtype t); +struct TMPL_token* scan_text( + const char* start, + size_t strlen, + size_t* consumed + ); +struct TMPL_token* scan_tag( + const char* start, + size_t strlen, + size_t* consumed + ); +void print_tokens(struct TMPL_token* head); + + +/*Allocates a token*/ +struct TMPL_token* +TMPL_alloc_token(){ + struct TMPL_token* ret = (struct TMPL_token*)malloc(sizeof(struct TMPL_token)); + ret->next = NULL; + return ret; +} + +/*Frees an allocated token*/ +void +TMPL_free_token(struct TMPL_token* token){ + struct TMPL_token* cursor = token; + while(cursor != NULL){ + struct TMPL_token* this = cursor; + cursor = cursor->next; + free(this); + } +} + +/*Check if it starts with the names of any of our tokens*/ +enum TMPL_tagtype +starts_with_token(const char* str, size_t strlen){ + /*Make sure we get TMPL_ first*/ + if(strlen < 5){ + return tag_null; + } + if(*str != 'T' + || *(str + 1) != 'M' + || *(str + 2) != 'P' + || *(str + 3) != 'L' + || *(str + 4) != '_'){ + return tag_null; + } + if(strlen > TAG_VAR_LENGTH + && *(str + 5) == 'V' + && *(str + 6) == 'A' + && *(str + 7) == 'R' + && *(str + 8) == ' '){ + return tag_var; + }else if(strlen > TAG_IF_LENGTH + && *(str + 5) == 'I' + && *(str + 6) == 'F' + && *(str + 7) == ' '){ + return tag_if; + }else if(strlen > TAG_END_LENGTH + && *(str + 5) == 'E' + && *(str + 6) == 'N' + && *(str + 7) == 'D'){ + return tag_end; + }else if(strlen > TAG_ELSE_LENGTH + && *(str + 5) == 'E'/*Check for both else and elseif*/ + && *(str + 6) == 'L' + && *(str + 7) == 'S' + && *(str + 8) == 'E'){ + if(*(str + 9) != 'I'){ + return tag_else; + }else if(strlen > TAG_ELSEIF_LENGTH + && *(str + 9) == 'I' + && *(str + 10) == 'F' + && *(str + 11) == ' '){ + return tag_elseif; + }else{ + return tag_null; + } + }else if(strlen > TAG_LOOP_LENGTH + && *(str + 5) == 'L' + && *(str + 6) == 'O' + && *(str + 7) == 'O' + && *(str + 8) == 'P' + && *(str + 9) == ' '){ + return tag_loop; + }else if(strlen > TAG_BREAK_LENGTH + && *(str + 5) == 'B' + && *(str + 6) == 'R' + && *(str + 7) == 'E' + && *(str + 8) == 'A' + && *(str + 9) == 'K'){ + return tag_break; + }else if(strlen > TAG_CONTINUE_LENGTH + && *(str + 5) == 'C' + && *(str + 6) == 'O' + && *(str + 7) == 'N' + && *(str + 8) == 'T' + && *(str + 9) == 'I' + && *(str + 10) == 'N' + && *(str + 11) == 'U' + && *(str + 12) == 'E'){ + return tag_continue; + }else{ + return tag_null; + } +} + +/*Find the lenth of a tag*/ +size_t +tagtype_len(enum TMPL_tagtype t){ + switch(t){ + case tag_null: + return TAG_NULL_LENGTH; + case tag_text: + return TAG_TEXT_LENGTH; + case tag_var: + return TAG_VAR_LENGTH; + case tag_if: + return TAG_IF_LENGTH; + case tag_end: + return TAG_END_LENGTH; + case tag_elseif: + return TAG_ELSEIF_LENGTH; + case tag_else: + return TAG_ELSE_LENGTH; + case tag_loop: + return TAG_LOOP_LENGTH; + case tag_break: + return TAG_BREAK_LENGTH; + case tag_continue: + return TAG_CONTINUE_LENGTH; + } + return 0; +} + +/*Quickly find the token*/ +struct TMPL_token* +scan_text(const char* start, size_t strlen, size_t* consumed){ + struct TMPL_token* t = TMPL_alloc_token(); + t->start = start; + enum TMPL_tagtype type = tag_null; + const char* cursor = start; + while(type == tag_null){ + int left = strlen - (cursor - start); + cursor = (const char*)memchr(cursor,'<',left); + if(cursor == NULL){ + cursor = start + (strlen > 0 ? strlen : 1); + break; + } + type = starts_with_token(cursor+1,strlen); + if(type == tag_null){ + cursor++; + } + } + t->end = cursor; + t->length = t->end - t->start; + *consumed = t->length; + return t; +} + +struct TMPL_token* +scan_tag(const char* start, size_t strlen, size_t* consumed){ + struct TMPL_token* t = TMPL_alloc_token(); + t->start = start; + char* cursor = (char*)memchr(start,'>',strlen); + t->end = cursor+1;/*Include the '>'*/ + t->length = t->end - t->start; + *consumed = t->length; + return t; +} + +void +print_tokens(struct TMPL_token* head){ + struct TMPL_token* cursor = head; + while(cursor != NULL){ + printf("char start is %p char end is %p cursor is %p type is %d\n",cursor->start, cursor->end,(void*)cursor,(int)cursor->type); + const char* i; + for(i = cursor->start; i != cursor->end; i++){ + printf("%c",*i); + } + printf("\n----\n"); + cursor = cursor->next; + } + printf("Finished printing tokens\n"); +} + -- cgit v1.2.3-70-g09d2