diff options
| author | Alexander Pickering <alexandermpickering@gmail.com> | 2019-08-28 17:28:55 -0400 |
|---|---|---|
| committer | Alexander Pickering <alexandermpickering@gmail.com> | 2019-08-28 17:28:55 -0400 |
| commit | 06087b10ec7a897ad48db83f7f33a8fc11fa9341 (patch) | |
| tree | 4e6c539bf89d08deec84ffec35797fc7306022b1 /src/lexer.c | |
| parent | 192115300aa8349a4c85535466386cbf99259fdd (diff) | |
| download | libctemplates-06087b10ec7a897ad48db83f7f33a8fc11fa9341.tar.gz libctemplates-06087b10ec7a897ad48db83f7f33a8fc11fa9341.tar.bz2 libctemplates-06087b10ec7a897ad48db83f7f33a8fc11fa9341.zip | |
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.
Diffstat (limited to 'src/lexer.c')
| -rw-r--r-- | src/lexer.c | 191 |
1 files changed, 191 insertions, 0 deletions
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"); +} + |
