aboutsummaryrefslogtreecommitdiff
path: root/src/lexer.c
diff options
context:
space:
mode:
authorAlexander Pickering <alexandermpickering@gmail.com>2019-08-28 17:28:55 -0400
committerAlexander Pickering <alexandermpickering@gmail.com>2019-08-28 17:28:55 -0400
commit06087b10ec7a897ad48db83f7f33a8fc11fa9341 (patch)
tree4e6c539bf89d08deec84ffec35797fc7306022b1 /src/lexer.c
parent192115300aa8349a4c85535466386cbf99259fdd (diff)
downloadlibctemplates-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.c191
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");
+}
+