From 49c2589427e0f81bea68ccba1a95c6890e10538d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yaroslav=20de=20la=20Pe=C3=B1a=20Smirnov?= Date: Thu, 26 Jan 2023 22:39:41 +0300 Subject: Fix break tag parsing and code format auto-formatted the code with clang-format. --- .clang-format | 90 ++++++++++++++ include/ast.h | 67 +++++------ include/hmap.h | 14 +-- include/lexer.h | 2 +- include/object.h | 9 +- include/token.h | 8 +- src/ast.c | 8 +- src/hmap.c | 160 ++++++++++++------------- src/lexer.c | 56 +++++---- src/object.c | 89 +++++++------- src/parser.c | 145 ++++++++++++----------- src/roscha.c | 133 +++++++++++---------- src/tests/parser.c | 335 +++++++++++++++++++++++++++++++++++------------------ src/token.c | 132 ++++++++++----------- 14 files changed, 726 insertions(+), 522 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..53912e6 --- /dev/null +++ b/.clang-format @@ -0,0 +1,90 @@ +--- +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: Consecutive +AlignConsecutiveBitFields: Consecutive +AlignConsecutiveDeclarations: Consecutive +AlignConsecutiveMacros: Consecutive +AlignEscapedNewlines: Left +AlignOperands: AlignAfterOperator +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: false +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLoopsOnASingleLine: false +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakAfterReturnType: AllDefinitions +BinPackArguments: true +BinPackParameters: true +BitFieldColonSpacing: Both +BreakBeforeBraces: Linux +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeTernaryOperators: true +BreakStringLiterals: true + +# Actually should be 80, but clang-format is brain-dead and makes array +# initializers less readable by mangling the line breaks. +ColumnLimit: 0 + +DeriveLineEnding: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false + +ForEachMacros: + - 'vector_foreach' + - 'hmap_iter_foreach' + +IncludeBlocks: Preserve +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: false +IndentPPDirectives: None +IndentExternBlock: NoIndent +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MaxEmptyLinesToKeep: 1 + +# Taken from git's rules +PenaltyBreakAssignment: 10 +PenaltyBreakBeforeFirstCallParameter: 30 +PenaltyBreakComment: 10 +PenaltyBreakFirstLessLess: 0 +PenaltyBreakString: 10 +PenaltyExcessCharacter: 100 +PenaltyReturnTypeOnItsOwnLine: 60 + +PointerAlignment: Right +ReflowComments: true +SortIncludes: Never +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeParens: ControlStatements +SpaceAroundPointerQualifiers: Default +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +Standard: Auto +TabWidth: 4 +UseCRLF: false +UseTab: AlignWithSpaces + diff --git a/include/ast.h b/include/ast.h index fe722bf..acbc108 100644 --- a/include/ast.h +++ b/include/ast.h @@ -42,12 +42,12 @@ struct ident { struct integer { struct token token; - int64_t value; + int64_t value; }; struct boolean { struct token token; - bool value; + bool value; }; struct string { @@ -56,21 +56,21 @@ struct string { }; struct prefix { - struct token token; - struct slice operator; + struct token token; + struct slice operator; struct expression *right; }; struct infix { - struct token token; - struct slice operator; + struct token token; + struct slice operator; struct expression *left; struct expression *right; }; /* Either a map key (map.k) or an array/vector index (arr[i]) */ struct indexkey { - struct token token; + struct token token; struct expression *left; struct expression *key; }; @@ -78,13 +78,13 @@ struct indexkey { struct expression { enum expression_type type; union { - struct token token; - struct ident ident; - struct integer integer; - struct boolean boolean; - struct string string; - struct prefix prefix; - struct infix infix; + struct token token; + struct ident ident; + struct integer integer; + struct boolean boolean; + struct string string; + struct prefix prefix; + struct infix infix; struct indexkey indexkey; }; }; @@ -94,44 +94,44 @@ struct branch { struct token token; /* if condition is null it means it is an else branch */ struct expression *condition; - struct vector *subblocks; + struct vector *subblocks; /* elif or else */ struct branch *next; }; /* start of if, elif, else */ struct cond { - struct token token; + struct token token; struct branch *root; }; /* for loop */ struct loop { - struct token token; - struct ident item; + struct token token; + struct ident item; struct expression *seq; - struct vector *subblocks; + struct vector *subblocks; }; /* template block {% block ... %} */ struct tblock { - struct token token; - struct ident name; + struct token token; + struct ident name; struct vector *subblocks; }; /* {% extends ... %} */ struct parent { - struct token token; + struct token token; struct string *name; }; /* {% ... %} blocks */ struct tag { - union{ - struct token token; - struct cond cond; - struct loop loop; + union { + struct token token; + struct cond cond; + struct loop loop; struct tblock tblock; struct parent parent; }; @@ -140,7 +140,7 @@ struct tag { /* {{ ... }} blocks */ struct variable { - struct token token; + struct token token; struct expression *expression; }; @@ -151,21 +151,22 @@ struct content { /* * The template is divided into blocks or chunks which are either plain text - * content, {% %} tags or {{ }} variables. Not to be confused with + * content, {% %} tags or {{ }} variables. Not to be confused with * {% block ... %} tags. */ struct block { union { - struct token token; - struct content content; - struct tag tag; + struct token token; + struct content content; + struct tag tag; struct variable variable; }; enum block_type type; }; /* Root of the AST */ -struct template { +struct template +{ /* * The name of the template, might be a file name; used to identifiy the * template in error messages. Will be free'd by template_destroy function @@ -179,7 +180,7 @@ struct template { char *source; /* * struct that holds references to {% block ... %} tags, for easier/faster - * access to said blocks. + * access to said blocks. */ struct hmap *tblocks; /* diff --git a/include/hmap.h b/include/hmap.h index fa24982..7735c53 100644 --- a/include/hmap.h +++ b/include/hmap.h @@ -12,9 +12,9 @@ typedef void (hmap_cb)(const struct slice *key, void *value); struct hmap { - struct hnode **buckets; - size_t cap; - size_t size; + struct hnode **buckets; + size_t cap; + size_t size; }; struct hmap_iter; @@ -24,9 +24,9 @@ struct hmap *hmap_new_with_cap(size_t cap); #define hmap_new() hmap_new_with_cap(HASHMAP_CAP) -/* +/* * Inserts a key-value pair into the map. Returns NULL if map did not have key, - * old value if it did. + * old value if it did. */ void *hmap_sets(struct hmap *hm, struct slice key, void *value); @@ -39,7 +39,7 @@ void *hmap_gets(struct hmap *hm, const struct slice *key); /* Same as hmap_gets but pass a C string instead */ void *hmap_get(struct hmap *hm, const char *key); -/* +/* * Removes a key from the map, returning the value at the key if the key was * previously in the map. */ @@ -56,7 +56,7 @@ struct hmap_iter *hmap_iter_new(struct hmap *); /* Get the next key, value */ bool hmap_iter_next(struct hmap_iter *iter, const struct slice **key, - void **value); + void **value); #define hmap_iter_foreach(it, k, v) while (hmap_iter_next(it, k, v)) diff --git a/include/lexer.h b/include/lexer.h index 8491c5a..97809df 100644 --- a/include/lexer.h +++ b/include/lexer.h @@ -16,7 +16,7 @@ struct lexer { /* The current slice of the input string that will be tokenized */ struct slice word; /* The current character belongs to content and should not be tokenized */ - bool in_content; + bool in_content; size_t line; size_t column; }; diff --git a/include/object.h b/include/object.h index 71fc969..2325b15 100644 --- a/include/object.h +++ b/include/object.h @@ -58,7 +58,7 @@ struct roscha_object { sds roscha_object_string(const struct roscha_object *, sds str); /* Return the textual representation of the type */ -inline const char *roscha_type_print(enum roscha_type); +const char *roscha_type_print(enum roscha_type); /* Create a new roscha object based on its type */ struct roscha_object *roscha_object_new_int(int64_t val); @@ -77,7 +77,12 @@ struct roscha_object *roscha_object_new_hmap(struct hmap *); )(v) /* Increment reference count of object */ -void roscha_object_ref(struct roscha_object *); +static inline void +roscha_object_ref(struct roscha_object *obj) +{ + obj->refcount++; +} + /* Decrement reference count of object */ void roscha_object_unref(struct roscha_object *); diff --git a/include/token.h b/include/token.h index edff1d2..6c5eb5e 100644 --- a/include/token.h +++ b/include/token.h @@ -61,9 +61,9 @@ enum token_type { /* A token in our template */ struct token { enum token_type type; - struct slice literal; - size_t line; - size_t column; + struct slice literal; + size_t line; + size_t column; }; /* Intialize our keywords hashmap */ @@ -73,7 +73,7 @@ void token_init_keywords(void); enum token_type token_lookup_ident(const struct slice *ident); /* Return a C string with the token type name */ -inline const char *token_type_print(enum token_type); +const char *token_type_print(enum token_type); /* Concatenate this token to a sds string */ sds token_string(struct token *, sds str); diff --git a/src/ast.c b/src/ast.c index 2de718a..f1aa62c 100644 --- a/src/ast.c +++ b/src/ast.c @@ -8,9 +8,9 @@ static inline sds subblocks_string(struct vector *subblocks, sds str) { - size_t i; + size_t i; struct block *subblk; - vector_foreach(subblocks, i, subblk) { + vector_foreach (subblocks, i, subblk) { str = block_string(subblk, str); str = sdscat(str, "\n"); } @@ -255,9 +255,9 @@ expression_destroy(struct expression *expr) static inline void subblocks_destroy(struct vector *subblks) { - size_t i; + size_t i; struct block *blk; - vector_foreach(subblks, i, blk){ + vector_foreach (subblks, i, blk) { block_destroy(blk); } vector_free(subblks); diff --git a/src/hmap.c b/src/hmap.c index fb58a88..8acecd2 100644 --- a/src/hmap.c +++ b/src/hmap.c @@ -8,28 +8,28 @@ #if SIZE_MAX == 0xFFFFFFFF /* If size_t is 32bit */ -static const size_t fnv_prime = 16777619u; +static const size_t fnv_prime = 16777619u; static const size_t fnv_offsetb = 2166136261u; #elif SIZE_MAX == 0xFFFFFFFFFFFFFFFF /* If size_t is 64bit */ -static const size_t fnv_prime = 1099511628211u; +static const size_t fnv_prime = 1099511628211u; static const size_t fnv_offsetb = 14695981039346656037u; #else /* If size_t is 128bit. Maybe this is overdoing it? */ -static const size_t fnv_prime = 309485009821345068724781371u; +static const size_t fnv_prime = 309485009821345068724781371u; static const size_t fnv_offsetb = 144066263297769815596495629667062367629u; #endif struct hnode { - struct slice key; - void *value; - struct hnode *next; + struct slice key; + void *value; + struct hnode *next; }; struct hmap_iter { - struct hmap *map; - size_t index; - size_t count; + struct hmap *map; + size_t index; + size_t count; struct hnode *cur; }; @@ -38,7 +38,7 @@ static size_t hash_slice(const struct slice *slice) { size_t hash = fnv_offsetb; - size_t i = slice->start; + size_t i = slice->start; while (i < slice->end) { hash ^= slice->str[i]; hash *= fnv_prime; @@ -52,8 +52,8 @@ struct hmap * hmap_new_with_cap(size_t cap) { struct hmap *hm = malloc(sizeof *hm); - hm->cap = cap; - hm->size = 0; + hm->cap = cap; + hm->size = 0; if (hm == NULL) return NULL; hm->buckets = calloc(cap, sizeof hm->buckets); if (hm->buckets == NULL) { @@ -67,43 +67,43 @@ hmap_new_with_cap(size_t cap) void * hmap_sets(struct hmap *hm, struct slice key, void *value) { - int pos = hash_slice(&key) % hm->cap; - struct hnode *head = hm->buckets[pos]; - struct hnode *node = head; - void *old_value = NULL; - - while (node) { - if (slice_cmp(&node->key, &key) == 0) { - old_value = node->value; - node->value = value; - return old_value; - } - node = node->next; - } - - node = malloc(sizeof *node); - node->key = key; - node->value = value; - node->next = head; - hm->buckets[pos] = node; - hm->size++; - return old_value; + int pos = hash_slice(&key) % hm->cap; + struct hnode *head = hm->buckets[pos]; + struct hnode *node = head; + void *old_value = NULL; + + while (node) { + if (slice_cmp(&node->key, &key) == 0) { + old_value = node->value; + node->value = value; + return old_value; + } + node = node->next; + } + + node = malloc(sizeof *node); + node->key = key; + node->value = value; + node->next = head; + hm->buckets[pos] = node; + hm->size++; + return old_value; } void * hmap_gets(struct hmap *hm, const struct slice *key) { - size_t pos = hash_slice(key) % hm->cap; - struct hnode *node = hm->buckets[pos]; - while (node != NULL) { - if (slice_cmp(&node->key, key) == 0) { - return node->value; - } - - node = node->next; - } + size_t pos = hash_slice(key) % hm->cap; + struct hnode *node = hm->buckets[pos]; + while (node != NULL) { + if (slice_cmp(&node->key, key) == 0) { + return node->value; + } + + node = node->next; + } - return NULL; + return NULL; } void * @@ -116,29 +116,29 @@ hmap_get(struct hmap *hm, const char *k) void * hmap_removes(struct hmap *hm, const struct slice *key) { - int pos = hash_slice(key) % hm->cap; - struct hnode *node = hm->buckets[pos]; - struct hnode *prev = NULL; - void *old_value; - - while (node) { - if (slice_cmp(&node->key, key) == 0) { - if (prev) { - prev->next = node->next; - } else { - hm->buckets[pos] = node->next; - } - old_value = node->value; - free(node); - hm->size--; - return old_value; - } - - prev = node; - node = node->next; - } - - return NULL; + int pos = hash_slice(key) % hm->cap; + struct hnode *node = hm->buckets[pos]; + struct hnode *prev = NULL; + void *old_value; + + while (node) { + if (slice_cmp(&node->key, key) == 0) { + if (prev) { + prev->next = node->next; + } else { + hm->buckets[pos] = node->next; + } + old_value = node->value; + free(node); + hm->size--; + return old_value; + } + + prev = node; + node = node->next; + } + + return NULL; } void * @@ -148,16 +148,16 @@ hmap_remove(struct hmap *hm, const char *k) return hmap_removes(hm, &key); } -#define HMAP_WALK(hm, ...) \ - struct hnode *node; \ - struct hnode *next; \ +#define HMAP_WALK(hm, ...) \ + struct hnode *node; \ + struct hnode *next; \ for (size_t i = 0; i < hm->cap; i++) { \ - node = hm->buckets[i]; \ - while (node) { \ - next = node->next; \ - __VA_ARGS__; \ - node = next; \ - } \ + node = hm->buckets[i]; \ + while (node) { \ + next = node->next; \ + __VA_ARGS__; \ + node = next; \ + } \ } void @@ -170,10 +170,10 @@ struct hmap_iter * hmap_iter_new(struct hmap *hm) { struct hmap_iter *iter = malloc(sizeof(*iter)); - iter->map = hm; - iter->index = 0; - iter->count = hm->size; - iter->cur = NULL; + iter->map = hm; + iter->index = 0; + iter->count = hm->size; + iter->cur = NULL; return iter; } @@ -190,7 +190,7 @@ hmap_iter_next(struct hmap_iter *iter, const struct slice **key, void **value) } else { iter->cur = iter->cur->next; } - *key = &iter->cur->key; + *key = &iter->cur->key; *value = iter->cur->value; iter->count--; diff --git a/src/lexer.c b/src/lexer.c index 1ba9912..182b3c2 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -17,9 +17,9 @@ set_token(struct token *token, enum token_type t, const struct slice *s) { token->type = t; if (s == NULL) { - token->literal.str = ""; + token->literal.str = ""; token->literal.start = 0; - token->literal.end = 0; + token->literal.end = 0; } else { slice_cpy(&token->literal, s); } @@ -63,60 +63,58 @@ lexer_read_char(struct lexer *lexer) static void lexer_read_ident(struct lexer *lexer, struct token *token) { - size_t start = lexer->word.start; + size_t start = lexer->word.start; token->literal.str = lexer->input; - while (isidentc(lexer->input[lexer->word.start]) - || isdigit(lexer->input[lexer->word.start])) { + while (isidentc(lexer->input[lexer->word.start]) + || isdigit(lexer->input[lexer->word.start])) { lexer_read_char(lexer); } token->literal.start = start; - token->literal.end = lexer->word.start; + token->literal.end = lexer->word.start; } static void lexer_read_num(struct lexer *lexer, struct token *token) { - size_t start = lexer->word.start; + size_t start = lexer->word.start; token->literal.str = lexer->input; while (isdigit(lexer->input[lexer->word.start])) { lexer_read_char(lexer); } token->literal.start = start; - token->literal.end = lexer->word.start; + token->literal.end = lexer->word.start; } static void lexer_read_string(struct lexer *lexer, struct token *token) { - size_t start = lexer->word.start; + size_t start = lexer->word.start; token->literal.str = lexer->input; lexer_read_char(lexer); - while(lexer->input[lexer->word.start] != '"' && - lexer->input[lexer->word.start] != '\0') { + while (lexer->input[lexer->word.start] != '"' && lexer->input[lexer->word.start] != '\0') { lexer_read_char(lexer); } lexer_read_char(lexer); token->literal.start = start; - token->literal.end = lexer->word.start; + token->literal.end = lexer->word.start; } static void lexer_read_content(struct lexer *lexer, struct token *token) { - size_t start = lexer->word.start; + size_t start = lexer->word.start; token->literal.str = lexer->input; - while(lexer->input[lexer->word.start] != '{' && - lexer->input[lexer->word.start] != '\0') { + while (lexer->input[lexer->word.start] != '{' && lexer->input[lexer->word.start] != '\0') { lexer_read_char(lexer); } token->literal.start = start; - token->literal.end = lexer->word.start; + token->literal.end = lexer->word.start; } static void lexer_eatspace(struct lexer *lexer) { - while(isspace(lexer->input[lexer->word.start])) { + while (isspace(lexer->input[lexer->word.start])) { lexer_read_char(lexer); } } @@ -125,14 +123,14 @@ struct lexer * lexer_new(const char *input) { struct lexer *lexer = malloc(sizeof(*lexer)); - lexer->input = input; - lexer->len = strlen(lexer->input); - lexer->word.str = lexer->input; - lexer->word.start = 0; - lexer->word.end = 0; - lexer->in_content = true; - lexer->line = 1; - lexer->column = 0; + lexer->input = input; + lexer->len = strlen(lexer->input); + lexer->word.str = lexer->input; + lexer->word.start = 0; + lexer->word.end = 0; + lexer->in_content = true; + lexer->line = 1; + lexer->column = 0; lexer_read_char(lexer); return lexer; @@ -141,8 +139,8 @@ lexer_new(const char *input) struct token lexer_next_token(struct lexer *lexer) { - struct token token = { .line = lexer->line, .column = lexer->column }; - char c = lexer->input[lexer->word.start]; + struct token token = {.line = lexer->line, .column = lexer->column}; + char c = lexer->input[lexer->word.start]; if (c == '\0') { set_token(&token, TOKEN_EOF, NULL); @@ -224,14 +222,14 @@ lexer_next_token(struct lexer *lexer) lexer->in_content = false; set_token(&token, TOKEN_LBRACE, &lexer->word); break; - case '}':{ + case '}': { char prevc = lexer_peek_prev_char(lexer); if (prevc == '}' || prevc == '%') { lexer->in_content = true; } set_token(&token, TOKEN_RBRACE, &lexer->word); break; - } + } case '%': set_token(&token, TOKEN_PERCENT, &lexer->word); break; diff --git a/src/object.c b/src/object.c index e7311b5..8972020 100644 --- a/src/object.c +++ b/src/object.c @@ -1,14 +1,21 @@ #include "object.h" static const char *roscha_types[] = { - "null", - "int", - "bool", - "string", - "vector", - "hashmap", + [ROSCHA_NULL] = "null", + [ROSCHA_INT] = "int", + [ROSCHA_BOOL] = "bool", + [ROSCHA_STRING] = "string", + [ROSCHA_SLICE] = "slice", + [ROSCHA_VECTOR] = "vector", + [ROSCHA_HMAP] = "hashmap", }; +extern inline const char * +roscha_type_print(enum roscha_type type) +{ + return roscha_types[type]; +} + static void roscha_object_destroy_hmap_cb(const struct slice *key, void *val) { @@ -16,12 +23,6 @@ roscha_object_destroy_hmap_cb(const struct slice *key, void *val) roscha_object_unref(obj); } -extern inline const char * -roscha_type_print(enum roscha_type type) -{ - return roscha_types[type]; -} - static inline sds bool_string(bool val, sds str) { @@ -32,10 +33,10 @@ bool_string(bool val, sds str) static inline sds vector_string(struct vector *vec, sds str) { - size_t i; + size_t i; struct roscha_object *obj; str = sdscat(str, "[ "); - vector_foreach(vec, i, obj) { + vector_foreach (vec, i, obj) { str = roscha_object_string(obj, str); str = sdscat(str, ", "); } @@ -48,13 +49,13 @@ hmap_string(struct hmap *map, sds str) { str = sdscat(str, "{ "); const struct slice *key; - void *val; - struct hmap_iter *iter = hmap_iter_new(map); - hmap_iter_foreach(iter, &key, &val) { - str = sdscatfmt(str, "\"%s\": ", key->str); + void *val; + struct hmap_iter *iter = hmap_iter_new(map); + hmap_iter_foreach (iter, &key, &val) { + str = sdscatfmt(str, "\"%s\": ", key->str); const struct roscha_object *obj = val; - str = roscha_object_string(obj, str); - str = sdscat(str, ", "); + str = roscha_object_string(obj, str); + str = sdscat(str, ", "); } str = sdscat(str, "}"); @@ -87,9 +88,9 @@ struct roscha_object * roscha_object_new_int(int64_t val) { struct roscha_object *obj = malloc(sizeof(*obj)); - obj->type = ROSCHA_INT; - obj->refcount = 1; - obj->integer = val; + obj->type = ROSCHA_INT; + obj->refcount = 1; + obj->integer = val; return obj; } @@ -97,9 +98,9 @@ struct roscha_object * roscha_object_new_slice(struct slice s) { struct roscha_object *obj = malloc(sizeof(*obj)); - obj->type = ROSCHA_SLICE; - obj->refcount = 1; - obj->slice = s; + obj->type = ROSCHA_SLICE; + obj->refcount = 1; + obj->slice = s; return obj; } @@ -107,9 +108,9 @@ struct roscha_object * roscha_object_new_string(sds str) { struct roscha_object *obj = malloc(sizeof(*obj)); - obj->type = ROSCHA_STRING; - obj->refcount = 1; - obj->string = str; + obj->type = ROSCHA_STRING; + obj->refcount = 1; + obj->string = str; return obj; } @@ -117,9 +118,9 @@ struct roscha_object * roscha_object_new_vector(struct vector *vec) { struct roscha_object *obj = malloc(sizeof(*obj)); - obj->type = ROSCHA_VECTOR; - obj->refcount = 1; - obj->vector = vec; + obj->type = ROSCHA_VECTOR; + obj->refcount = 1; + obj->vector = vec; return obj; } @@ -127,29 +128,23 @@ struct roscha_object * roscha_object_new_hmap(struct hmap *map) { struct roscha_object *obj = malloc(sizeof(*obj)); - obj->type = ROSCHA_HMAP; - obj->refcount = 1; - obj->hmap = map; + obj->type = ROSCHA_HMAP; + obj->refcount = 1; + obj->hmap = map; return obj; } static inline void roscha_object_vector_destroy(struct roscha_object *obj) { - size_t i; + size_t i; struct roscha_object *subobj; - vector_foreach(obj->vector, i, subobj) { + vector_foreach (obj->vector, i, subobj) { roscha_object_unref(subobj); } vector_free(obj->vector); } -inline void -roscha_object_ref(struct roscha_object *obj) -{ - obj->refcount++; -} - void roscha_object_unref(struct roscha_object *obj) { @@ -188,7 +183,7 @@ roscha_vector_pop(struct roscha_object *vec) struct roscha_object * roscha_hmap_sets(struct roscha_object *hmap, struct slice key, - struct roscha_object *value) + struct roscha_object *value) { roscha_object_ref(value); return hmap_sets(hmap->hmap, key, value); @@ -196,7 +191,7 @@ roscha_hmap_sets(struct roscha_object *hmap, struct slice key, struct roscha_object * roscha_hmap_setstr(struct roscha_object *hmap, const char *key, - struct roscha_object *value) + struct roscha_object *value) { roscha_object_ref(value); return hmap_set(hmap->hmap, key, value); @@ -221,8 +216,8 @@ roscha_hmap_pops(struct roscha_object *hmap, const struct slice *key) } struct roscha_object * -roscha_hmap_popstr(struct roscha_object *hmap, - const char *key) +roscha_hmap_popstr(struct roscha_object *hmap, + const char *key) { return (struct roscha_object *)hmap_remove(hmap->hmap, key); } diff --git a/src/parser.c b/src/parser.c index 0e331d9..b207fe6 100644 --- a/src/parser.c +++ b/src/parser.c @@ -29,8 +29,8 @@ static enum precedence precedence_values[] = { PRE_INDEX, }; -static struct hmap *prefix_fns = NULL; -static struct hmap *infix_fns = NULL; +static struct hmap *prefix_fns = NULL; +static struct hmap *infix_fns = NULL; static struct hmap *precedences = NULL; static struct block *parser_parse_block(struct parser *, struct block *opening); @@ -76,7 +76,7 @@ parser_get_precedence(struct parser *parser, enum token_type t) static inline void parser_next_token(struct parser *parser) { - parser->cur_token = parser->peek_token; + parser->cur_token = parser->peek_token; parser->peek_token = lexer_next_token(parser->lexer); } @@ -104,16 +104,16 @@ parser_cur_precedence(struct parser *parser) return parser_get_precedence(parser, parser->cur_token.type); } -#define parser_error(p, t, fmt, ...) \ - sds err = sdscatfmt(sdsempty(), "%s:%U:%U: "fmt, parser->name, \ - t.line, t.column, __VA_ARGS__); \ +#define parser_error(p, t, fmt, ...) \ + sds err = sdscatfmt(sdsempty(), "%s:%U:%U: " fmt, parser->name, \ + t.line, t.column, __VA_ARGS__); \ vector_push(p->errors, err) static inline void parser_peek_error(struct parser *parser, enum token_type t) { parser_error(parser, parser->peek_token, "expected token %s, got %s", - token_type_print(t), token_type_print(parser->peek_token.type)); + token_type_print(t), token_type_print(parser->peek_token.type)); } static inline bool @@ -131,7 +131,7 @@ static inline void parser_no_prefix_fn_error(struct parser *parser, enum token_type t) { parser_error(parser, parser->cur_token, "%s not recognized as prefix", - token_type_print(t)); + token_type_print(t)); } static struct expression * @@ -148,7 +148,9 @@ parser_parse_expression(struct parser *parser, enum precedence pre) && !parser_peek_token_is(parser, TOKEN_PERCENT) && !parser_peek_token_is(parser, TOKEN_RBRACE)) { infix_parse_f infix = parser_get_infix(parser, parser->peek_token.type); - if (!infix) { return lexpr; } + if (!infix) { + return lexpr; + } parser_next_token(parser); lexpr = infix(parser, lexpr); @@ -161,8 +163,8 @@ static struct expression * parser_parse_identifier(struct parser *parser) { struct expression *expr = malloc(sizeof(*expr)); - expr->type = EXPRESSION_IDENT; - expr->token = parser->cur_token; + expr->type = EXPRESSION_IDENT; + expr->token = parser->cur_token; return expr; } @@ -171,8 +173,8 @@ static struct expression * parser_parse_integer(struct parser *parser) { struct expression *expr = malloc(sizeof(*expr)); - expr->type = EXPRESSION_INT; - expr->token = parser->cur_token; + expr->type = EXPRESSION_INT; + expr->token = parser->cur_token; char *end; expr->integer.value = @@ -181,7 +183,7 @@ parser_parse_integer(struct parser *parser) && (expr->token.literal.str + expr->token.literal.end) < end) { sds istr = slice_string(&expr->token.literal, sdsempty()); parser_error(parser, parser->cur_token, "%s is not a valid integer", - istr); + istr); sdsfree(istr); free(expr); return NULL; @@ -194,9 +196,9 @@ static struct expression * parser_parse_boolean(struct parser *parser) { struct expression *expr = malloc(sizeof(*expr)); - expr->type = EXPRESSION_BOOL; - expr->token = parser->cur_token; - expr->boolean.value = expr->token.type == TOKEN_TRUE; + expr->type = EXPRESSION_BOOL; + expr->token = parser->cur_token; + expr->boolean.value = expr->token.type == TOKEN_TRUE; return expr; } @@ -205,9 +207,9 @@ static struct expression * parser_parse_string(struct parser *parser) { struct expression *expr = malloc(sizeof(*expr)); - expr->type = EXPRESSION_STRING; - expr->token = parser->cur_token; - expr->string.value = parser->cur_token.literal; + expr->type = EXPRESSION_STRING; + expr->token = parser->cur_token; + expr->string.value = parser->cur_token.literal; expr->string.value.start++; expr->string.value.end--; @@ -219,7 +221,9 @@ parser_parse_grouped(struct parser *parser) { parser_next_token(parser); struct expression *expr = parser_parse_expression(parser, PRE_LOWEST); - if (!parser_expect_peek(parser, TOKEN_RPAREN)) { return NULL; } + if (!parser_expect_peek(parser, TOKEN_RPAREN)) { + return NULL; + } return expr; } @@ -228,8 +232,8 @@ static struct expression * parser_parse_prefix(struct parser *parser) { struct expression *expr = malloc(sizeof(*expr)); - expr->type = EXPRESSION_PREFIX; - expr->token = parser->cur_token; + expr->type = EXPRESSION_PREFIX; + expr->token = parser->cur_token; expr->prefix.operator= parser->cur_token.literal; parser_next_token(parser); @@ -242,8 +246,8 @@ static struct expression * parser_parse_infix(struct parser *parser, struct expression *lexpr) { struct expression *expr = malloc(sizeof(*expr)); - expr->type = EXPRESSION_INFIX; - expr->token = parser->cur_token; + expr->type = EXPRESSION_INFIX; + expr->token = parser->cur_token; expr->infix.operator= parser->cur_token.literal; expr->infix.left = lexpr; @@ -257,26 +261,26 @@ parser_parse_infix(struct parser *parser, struct expression *lexpr) static struct expression * parser_parse_mapkey(struct parser *parser, struct expression *lexpr) { - if (lexpr->type != EXPRESSION_IDENT - && lexpr->type != EXPRESSION_MAPKEY - && lexpr->type != EXPRESSION_INDEX) { + if (lexpr->type != EXPRESSION_IDENT + && lexpr->type != EXPRESSION_MAPKEY + && lexpr->type != EXPRESSION_INDEX) { sds got = expression_string(lexpr, sdsempty()); parser_error(parser, parser->cur_token, - "expected a map identifier, key or index; got %s", got); + "expected a map identifier, key or index; got %s", got); sdsfree(got); return NULL; } struct expression *expr = malloc(sizeof(*expr)); - expr->type = EXPRESSION_MAPKEY; - expr->token = parser->cur_token; - expr->indexkey.left = lexpr; + expr->type = EXPRESSION_MAPKEY; + expr->token = parser->cur_token; + expr->indexkey.left = lexpr; parser_next_token(parser); expr->indexkey.key = parser_parse_expression(parser, PRE_INDEX); if (expr->indexkey.key->type != EXPRESSION_IDENT) { sds got = expression_string(expr->indexkey.key, sdsempty()); parser_error(parser, parser->cur_token, - "expected a map key identifier, got %s", got); + "expected a map key identifier, got %s", got); sdsfree(got); expression_destroy(expr); return NULL; @@ -289,18 +293,18 @@ static struct expression * parser_parse_index(struct parser *parser, struct expression *lexpr) { if (lexpr->type != EXPRESSION_IDENT - && lexpr->type != EXPRESSION_MAPKEY - && lexpr->type != EXPRESSION_INDEX) { + && lexpr->type != EXPRESSION_MAPKEY + && lexpr->type != EXPRESSION_INDEX) { sds got = expression_string(lexpr, sdsempty()); parser_error(parser, parser->cur_token, - "expected a vector identifier, key or index; got %s", got); + "expected a vector identifier, key or index; got %s", got); sdsfree(got); return NULL; } struct expression *expr = malloc(sizeof(*expr)); - expr->type = EXPRESSION_INDEX; - expr->token = parser->cur_token; - expr->indexkey.left = lexpr; + expr->type = EXPRESSION_INDEX; + expr->token = parser->cur_token; + expr->indexkey.left = lexpr; parser_next_token(parser); expr->indexkey.key = parser_parse_expression(parser, PRE_LOWEST); @@ -348,7 +352,7 @@ static inline struct branch * parser_parse_branch(struct parser *parser, struct block *opening) { struct branch *brnch = calloc(1, sizeof(*brnch)); - brnch->token = parser->cur_token; + brnch->token = parser->cur_token; if (brnch->token.type == TOKEN_IF || brnch->token.type == TOKEN_ELIF) { parser_next_token(parser); @@ -384,7 +388,7 @@ parser_parse_branch(struct parser *parser, struct block *opening) static inline bool parser_parse_cond(struct parser *parser, struct block *blk) { - blk->tag.type = TAG_IF; + blk->tag.type = TAG_IF; blk->tag.cond.root = parser_parse_branch(parser, blk); if (!blk->tag.cond.root) { return false; @@ -395,15 +399,15 @@ parser_parse_cond(struct parser *parser, struct block *blk) static inline bool parser_parse_cond_alt(struct parser *parser, struct block *blk, - struct block *opening) + struct block *opening) { if (opening == NULL || opening->type != BLOCK_TAG - || opening->tag.type != TAG_IF) { + || opening->tag.type != TAG_IF) { parser_error(parser, parser->cur_token, "unexpected token %s", - token_type_print(parser->cur_token.type)); + token_type_print(parser->cur_token.type)); return false; } - blk->tag.type = TAG_IF; + blk->tag.type = TAG_IF; blk->tag.cond.root = parser_parse_branch(parser, blk); if (!blk->tag.cond.root) { return false; @@ -418,7 +422,7 @@ parser_parse_parent(struct parser *parser, struct block *blk) blk->tag.type = TAG_EXTENDS; if (!parser_expect_peek(parser, TOKEN_STRING)) return false; - blk->tag.parent.name = malloc(sizeof(*blk->tag.parent.name)); + blk->tag.parent.name = malloc(sizeof(*blk->tag.parent.name)); blk->tag.parent.name->token = parser->cur_token; blk->tag.parent.name->value = parser->cur_token.literal; blk->tag.parent.name->value.start++; @@ -463,13 +467,13 @@ static inline struct block * parser_parse_tag(struct parser *parser, struct block *opening) { struct block *blk = malloc(sizeof(*blk)); - blk->type = BLOCK_TAG; + blk->type = BLOCK_TAG; parser_next_token(parser); parser_next_token(parser); blk->token = parser->cur_token; - + bool res = true; switch (parser->cur_token.type) { case TOKEN_FOR: @@ -477,7 +481,9 @@ parser_parse_tag(struct parser *parser, struct block *opening) break; case TOKEN_BREAK: blk->tag.type = TAG_BREAK; - goto onetoken; + if (!parser_expect_peek(parser, TOKEN_PERCENT)) goto fail; + if (!parser_expect_peek(parser, TOKEN_RBRACE)) goto fail; + break; case TOKEN_IF: res = parser_parse_cond(parser, blk); break; @@ -505,7 +511,7 @@ parser_parse_tag(struct parser *parser, struct block *opening) goto closing; default:; parser_error(parser, parser->cur_token, "expected keyword, got %s", - token_type_print(parser->cur_token.type)); + token_type_print(parser->cur_token.type)); return NULL; } @@ -517,13 +523,12 @@ parser_parse_tag(struct parser *parser, struct block *opening) return blk; closing: blk->tag.type = TAG_CLOSE; -onetoken: if (!parser_expect_peek(parser, TOKEN_PERCENT)) goto fail; if (!parser_peek_token_is(parser, TOKEN_RBRACE)) goto fail; return blk; noopening:; parser_error(parser, parser->cur_token, "unexpected closing tag %s", - token_type_print(parser->cur_token.type)); + token_type_print(parser->cur_token.type)); fail: free(blk); return NULL; @@ -533,8 +538,8 @@ static inline struct block * parser_parse_variable(struct parser *parser) { struct block *blk = malloc(sizeof(*blk)); - blk->type = BLOCK_VARIABLE; - blk->token = parser->peek_token; + blk->type = BLOCK_VARIABLE; + blk->token = parser->peek_token; parser_next_token(parser); parser_next_token(parser); @@ -554,8 +559,8 @@ static inline struct block * parser_parse_content(struct parser *parser) { struct block *blk = malloc(sizeof(*blk)); - blk->type = BLOCK_CONTENT; - blk->token = parser->cur_token; + blk->type = BLOCK_CONTENT; + blk->token = parser->cur_token; return blk; } @@ -570,12 +575,12 @@ parser_parse_block(struct parser *parser, struct block *opening) return parser_parse_variable(parser); case TOKEN_PERCENT: return parser_parse_tag(parser, opening); - default:{ + default: { parser_error(parser, parser->cur_token, - "expected token %s or %s, got %s", - token_type_print(TOKEN_LBRACE), - token_type_print(TOKEN_PERCENT), - token_type_print(parser->peek_token.type)); + "expected token %s or %s, got %s", + token_type_print(TOKEN_LBRACE), + token_type_print(TOKEN_PERCENT), + token_type_print(parser->peek_token.type)); return NULL; } } @@ -589,10 +594,10 @@ struct parser * parser_new(char *name, char *input) { struct parser *parser = calloc(1, sizeof(*parser)); - parser->name = name; + parser->name = name; struct lexer *lex = lexer_new(input); - parser->lexer = lex; + parser->lexer = lex; parser->errors = vector_new(); @@ -606,11 +611,11 @@ struct template * parser_parse_template(struct parser *parser) { struct template *tmpl = malloc(sizeof(*tmpl)); - tmpl->name = parser->name; - tmpl->source = (char *)parser->lexer->input; - parser->tblocks = hmap_new(); - tmpl->child = NULL; - tmpl->blocks = vector_new(); + tmpl->name = parser->name; + tmpl->source = (char *)parser->lexer->input; + parser->tblocks = hmap_new(); + tmpl->child = NULL; + tmpl->blocks = vector_new(); while (!parser_cur_token_is(parser, TOKEN_EOF)) { struct block *blk = parser_parse_block(parser, NULL); @@ -630,8 +635,8 @@ void parser_destroy(struct parser *parser) { size_t i; - char *val; - vector_foreach(parser->errors, i, val) { + char *val; + vector_foreach (parser->errors, i, val) { sdsfree(val); } vector_free(parser->errors); diff --git a/src/roscha.c b/src/roscha.c index 3f315ce..75f42a0 100644 --- a/src/roscha.c +++ b/src/roscha.c @@ -55,15 +55,15 @@ roscha_env_destroy_templates_cb(const struct slice *key, void *val) template_destroy(tmpl); } -#define eval_error(e, t, fmt, ...) \ - sds err = sdscatfmt(sdsempty(), "%s:%U:%U: "fmt, \ - e->internal->eval_tmpl->name, t.line, t.column, __VA_ARGS__); \ +#define eval_error(e, t, fmt, ...) \ + sds err = sdscatfmt(sdsempty(), "%s:%U:%U: " fmt, \ + e->internal->eval_tmpl->name, t.line, t.column, __VA_ARGS__); \ vector_push(e->errors, err) #define THERES_ERRORS env->errors->len > 0 static inline struct roscha_object *eval_expression(struct roscha_env *, - struct expression *); + struct expression *); static inline struct roscha_object * eval_prefix(struct roscha_env *env, struct prefix *pref) @@ -81,15 +81,15 @@ eval_prefix(struct roscha_env *env, struct prefix *pref) case TOKEN_MINUS: if (right->type != ROSCHA_INT) { eval_error(env, pref->token, - "operator '%s' can only be used with integer types", - token_type_print(pref->token.type)); + "operator '%s' can only be used with integer types", + token_type_print(pref->token.type)); } else { res = roscha_object_new(-right->integer); } break; - default:{ - eval_error(env, pref->token, "invalid prefix operator '%s'", - token_type_print(pref->token.type)); + default: { + eval_error(env, pref->token, "invalid prefix operator '%s'", + token_type_print(pref->token.type)); res = NULL; } } @@ -100,7 +100,7 @@ eval_prefix(struct roscha_env *env, struct prefix *pref) static inline struct roscha_object * eval_boolean_infix(struct roscha_env *env, struct token *op, - struct roscha_object *left, struct roscha_object *right) + struct roscha_object *left, struct roscha_object *right) { struct roscha_object *res = NULL; switch (op->type) { @@ -131,13 +131,13 @@ eval_boolean_infix(struct roscha_env *env, struct token *op, default: if (left->type != right->type) { eval_error(env, (*op), "types mismatch: %s %s %s", - roscha_type_print(left->type), token_type_print(op->type), - roscha_type_print(right->type)); + roscha_type_print(left->type), token_type_print(op->type), + roscha_type_print(right->type)); break; } eval_error(env, (*op), "bad operator: %s %s %s", - roscha_type_print(left->type), token_type_print(op->type), - roscha_type_print(right->type)); + roscha_type_print(left->type), token_type_print(op->type), + roscha_type_print(right->type)); break; } roscha_object_unref(left); @@ -148,7 +148,7 @@ eval_boolean_infix(struct roscha_env *env, struct token *op, static inline struct roscha_object * eval_integer_infix(struct roscha_env *env, struct token *op, - struct roscha_object *left, struct roscha_object *right) + struct roscha_object *left, struct roscha_object *right) { struct roscha_object *res; switch (op->type) { @@ -185,8 +185,7 @@ eval_infix(struct roscha_env *env, struct infix *inf) roscha_object_unref(left); return NULL; } - if (left->type == ROSCHA_INT && right->type == ROSCHA_INT) - { + if (left->type == ROSCHA_INT && right->type == ROSCHA_INT) { return eval_integer_infix(env, &inf->token, left, right); } @@ -201,13 +200,13 @@ eval_mapkey(struct roscha_env *env, struct indexkey *mkey) if (!map) return NULL; if (map->type != ROSCHA_HMAP) { eval_error(env, mkey->token, "expected %s type got %s", - roscha_type_print(ROSCHA_HMAP), - roscha_type_print(map->type)); + roscha_type_print(ROSCHA_HMAP), + roscha_type_print(map->type)); goto out; } if (mkey->key->type != EXPRESSION_IDENT) { eval_error(env, mkey->key->token, "bad map key '%s'", - token_type_print(mkey->key->token.type)); + token_type_print(mkey->key->token.type)); goto out; } res = hmap_gets(map->hmap, &mkey->key->token.literal); @@ -230,14 +229,14 @@ eval_index(struct roscha_env *env, struct indexkey *index) if (!vec) return NULL; if (vec->type != ROSCHA_VECTOR) { eval_error(env, index->token, "expected %s type got %s", - roscha_type_print(ROSCHA_VECTOR), - roscha_type_print(vec->type)); + roscha_type_print(ROSCHA_VECTOR), + roscha_type_print(vec->type)); goto out; } struct roscha_object *i = eval_expression(env, index->key); if (i->type != ROSCHA_INT) { eval_error(env, index->key->token, "bad vector key type %s", - roscha_type_print(ROSCHA_INT)); + roscha_type_print(ROSCHA_INT)); goto out2; } if (i->integer > (vec->vector->len - 1)) { @@ -307,7 +306,7 @@ eval_variable(struct roscha_env *env, sds r, struct variable *var) } static inline sds eval_subblocks(struct roscha_env *, sds r, - struct vector *blks); + struct vector *blks); static inline sds eval_branch(struct roscha_env *env, sds r, struct branch *br) @@ -329,18 +328,18 @@ eval_branch(struct roscha_env *env, sds r, struct branch *br) static inline sds eval_loop(struct roscha_env *env, sds r, struct loop *loop) { - struct roscha_object *loopv = roscha_object_new(hmap_new()); + struct roscha_object *loopv = roscha_object_new(hmap_new()); struct roscha_object *indexv = roscha_object_new(0); roscha_hmap_set(loopv, "index", indexv); - struct slice loopk = slice_whole("loop"); + struct slice loopk = slice_whole("loop"); struct roscha_object *outerloop = roscha_hmap_set(env->vars, "loop", loopv); - struct slice it = loop->item.token.literal; + struct slice it = loop->item.token.literal; struct roscha_object *outeritem = roscha_hmap_get(env->vars, &it); - struct roscha_object *seq = eval_expression(env, loop->seq); + struct roscha_object *seq = eval_expression(env, loop->seq); if (!seq) return r; if (seq->type == ROSCHA_VECTOR) { struct roscha_object *item; - vector_foreach(seq->vector, indexv->integer, item) { + vector_foreach (seq->vector, indexv->integer, item) { roscha_hmap_set(env->vars, it, item); r = eval_subblocks(env, r, loop->subblocks); roscha_hmap_unset(env->vars, &it); @@ -350,11 +349,11 @@ eval_loop(struct roscha_env *env, sds r, struct loop *loop) break; } } - } else if(seq->type == ROSCHA_HMAP) { - struct hmap_iter *iter = hmap_iter_new(seq->hmap); + } else if (seq->type == ROSCHA_HMAP) { + struct hmap_iter *iter = hmap_iter_new(seq->hmap); const struct slice *key; - void *val; - hmap_iter_foreach(iter, &key, &val) { + void *val; + hmap_iter_foreach (iter, &key, &val) { struct roscha_object *item = val; indexv->integer++; roscha_hmap_set(env->vars, it, item); @@ -368,9 +367,9 @@ eval_loop(struct roscha_env *env, sds r, struct loop *loop) } } else { eval_error(env, loop->seq->token, - "sequence should be of type %s or %s, got %s", - roscha_type_print(ROSCHA_VECTOR), - roscha_type_print(ROSCHA_HMAP), roscha_type_print(seq->type)); + "sequence should be of type %s or %s, got %s", + roscha_type_print(ROSCHA_VECTOR), + roscha_type_print(ROSCHA_HMAP), roscha_type_print(seq->type)); } if (outerloop) { @@ -393,7 +392,7 @@ eval_loop(struct roscha_env *env, sds r, struct loop *loop) static inline struct tblock * get_child_tblock(struct roscha_env *env, struct slice *name, - const struct template *tmpl) + const struct template *tmpl) { struct tblock *tblk = NULL; if (tmpl->child) { @@ -410,7 +409,7 @@ static inline sds eval_tblock(struct roscha_env *env, sds r, struct tblock *tblk) { struct tblock *child = get_child_tblock(env, &tblk->name.token.literal, - env->internal->eval_tmpl); + env->internal->eval_tmpl); if (child) { tblk = child; } @@ -428,9 +427,9 @@ eval_tag(struct roscha_env *env, sds r, struct tag *tag) return eval_loop(env, r, &tag->loop); case TAG_BLOCK: return eval_tblock(env, r, &tag->tblock); - case TAG_EXTENDS:{ + case TAG_EXTENDS: { eval_error(env, tag->token, "extends tag can only be the first tag", - tag->token); + tag->token); break; } case TAG_BREAK: @@ -447,19 +446,19 @@ static inline sds eval_block(struct roscha_env *env, sds r, struct block *blk) { switch (blk->type) { - case BLOCK_CONTENT: - return slice_string(&blk->token.literal, r); - case BLOCK_VARIABLE: - return eval_variable(env, r, &blk->variable); - case BLOCK_TAG: - return eval_tag(env, r, &blk->tag); + case BLOCK_CONTENT: + return slice_string(&blk->token.literal, r); + case BLOCK_VARIABLE: + return eval_variable(env, r, &blk->variable); + case BLOCK_TAG: + return eval_tag(env, r, &blk->tag); } } static inline sds eval_subblocks(struct roscha_env *env, sds r, struct vector *blks) { - size_t i; + size_t i; struct block *blk; vector_foreach (blks, i, blk) { r = eval_block(env, r, blk); @@ -472,18 +471,18 @@ eval_subblocks(struct roscha_env *env, sds r, struct vector *blks) static inline sds eval_template(struct roscha_env *env, const struct slice *name, - struct template *child) + struct template *child) { struct template *tmpl = hmap_gets(env->internal->templates, name); if (!tmpl) { sds errmsg = sdscat(sdsempty(), "template \""); - errmsg = slice_string(name, errmsg); - errmsg = sdscat(errmsg, "\" not found"); + errmsg = slice_string(name, errmsg); + errmsg = sdscat(errmsg, "\" not found"); vector_push(env->errors, errmsg); return NULL; } - tmpl->child = child; + tmpl->child = child; env->internal->eval_tmpl = tmpl; struct block *blk = tmpl->blocks->values[0]; @@ -493,7 +492,7 @@ eval_template(struct roscha_env *env, const struct slice *name, } sds r = sdsempty(); - r = eval_subblocks(env, r, tmpl->blocks); + r = eval_subblocks(env, r, tmpl->blocks); env->internal->eval_tmpl = NULL; @@ -515,11 +514,11 @@ roscha_deinit(void) struct roscha_env * roscha_env_new(void) { - struct roscha_env *env = calloc(1, sizeof(*env)); - env->internal = calloc(1, sizeof(*env->internal)); - env->vars = roscha_object_new(hmap_new()); + struct roscha_env *env = calloc(1, sizeof(*env)); + env->internal = calloc(1, sizeof(*env->internal)); + env->vars = roscha_object_new(hmap_new()); env->internal->templates = hmap_new(); - env->errors = vector_new(); + env->errors = vector_new(); return env; } @@ -527,8 +526,8 @@ roscha_env_new(void) bool roscha_env_add_template(struct roscha_env *env, char *name, char *body) { - struct parser *parser = parser_new(name, body); - struct template *tmpl = parser_parse_template(parser); + struct parser *parser = parser_new(name, body); + struct template *tmpl = parser_parse_template(parser); if (parser->errors->len > 0) { sds errmsg = NULL; while ((errmsg = vector_pop(parser->errors)) != NULL) { @@ -549,7 +548,7 @@ roscha_env_load_dir(struct roscha_env *env, const char *path) DIR *dir = opendir(path); if (!dir) { sds errmsg = sdscatfmt(sdsempty(), "unable to open dir %s, error %s", - path, strerror(errno)); + path, strerror(errno)); vector_push(env->errors, errmsg); return false; } @@ -560,10 +559,10 @@ roscha_env_load_dir(struct roscha_env *env, const char *path) } struct stat fstats; - sds fpath = sdscatfmt(sdsempty(), "%s/%s", path, ent->d_name); + sds fpath = sdscatfmt(sdsempty(), "%s/%s", path, ent->d_name); if (stat(fpath, &fstats)) { sds errmsg = sdscatfmt(sdsempty(), - "unable to stat file %s, error %s", fpath, strerror(errno)); + "unable to stat file %s, error %s", fpath, strerror(errno)); vector_push(env->errors, errmsg); closedir(dir); return false; @@ -573,18 +572,18 @@ roscha_env_load_dir(struct roscha_env *env, const char *path) char *name = malloc(strlen(ent->d_name) + 1); strcpy(name, ent->d_name); - int fd = open(fpath, O_RDONLY); - char buf[BUFSIZE]; - sds body = sdsempty(); + int fd = open(fpath, O_RDONLY); + char buf[BUFSIZE]; + sds body = sdsempty(); size_t nread; while ((nread = read(fd, buf, BUFSIZE)) > 0) { buf[nread] = '\0'; - body = sdscat(body, buf); + body = sdscat(body, buf); } close(fd); if (nread < 0) { sds errmsg = sdscatfmt(sdsempty(), - "unable to read file %s, error %s", fpath, strerror(errno)); + "unable to read file %s, error %s", fpath, strerror(errno)); vector_push(env->errors, errmsg); goto fileerr; } @@ -620,7 +619,7 @@ void roscha_env_destroy(struct roscha_env *env) { size_t i; - sds errmsg; + sds errmsg; vector_foreach (env->errors, i, errmsg) { sdsfree(errmsg); } diff --git a/src/tests/parser.c b/src/tests/parser.c index eb5c2a1..c8bdcc0 100644 --- a/src/tests/parser.c +++ b/src/tests/parser.c @@ -18,20 +18,20 @@ struct value { union { struct slice ident; struct slice string; - int64_t integer; - bool boolean; + int64_t integer; + bool boolean; }; enum value_type type; }; static void check_parser_errors(struct parser *parser, const char *file, int line, - const char *func) + const char *func) { if (parser->errors->len > 0) { printf("\n"); size_t i; - sds val; + sds val; vector_foreach (parser->errors, i, val) { printf("parser error %lu: %s\n", i, val); } @@ -48,7 +48,7 @@ check_parser_errors(struct parser *parser, const char *file, int line, static void test_integer_literal(struct expression *expr, int64_t val) { - char buf[128]; + char buf[128]; struct slice sval; asserteq(expr->type, EXPRESSION_INT); asserteq(expr->integer.value, val); @@ -67,7 +67,7 @@ test_identifier(struct expression *expr, struct slice *ident) static void test_boolean_literal(struct expression *expr, bool val) { - char *str = val ? "true" : "false"; + char *str = val ? "true" : "false"; struct slice sval = slice_whole(str); asserteq(expr->type, EXPRESSION_BOOL); asserteq(expr->boolean.value, val); @@ -81,41 +81,52 @@ test_string_literal(struct expression *expr, const struct slice *val) asserteq(slice_cmp(&expr->string.value, val), 0); } - static inline void test_expected(struct expression *expr, struct value v) { - switch(v.type) { - case VALUE_IDENT: - test_identifier(expr, &v.ident); - break; - case VALUE_INT: - test_integer_literal(expr, v.integer); - break; - case VALUE_BOOL: - test_boolean_literal(expr, v.boolean); - break; - case VALUE_STRING: - test_string_literal(expr, &v.string); - break; + switch (v.type) { + case VALUE_IDENT: + test_identifier(expr, &v.ident); + break; + case VALUE_INT: + test_integer_literal(expr, v.integer); + break; + case VALUE_BOOL: + test_boolean_literal(expr, v.boolean); + break; + case VALUE_STRING: + test_string_literal(expr, &v.string); + break; } } -#define VIDENT(v) \ - (struct value){ .type = VALUE_IDENT, .ident = slice_whole(v) } +#define VIDENT(v) \ + (struct value) \ + { \ + .type = VALUE_IDENT, .ident = slice_whole(v) \ + } -#define VINT(v) \ - (struct value){ .type = VALUE_INT, .integer = v } +#define VINT(v) \ + (struct value) \ + { \ + .type = VALUE_INT, .integer = v \ + } -#define VBOOL(v) \ - (struct value){ .type = VALUE_BOOL, .boolean = v } +#define VBOOL(v) \ + (struct value) \ + { \ + .type = VALUE_BOOL, .boolean = v \ + } -#define VSTR(v) \ - (struct value){ .type = VALUE_STRING, .string = slice_whole(v) } +#define VSTR(v) \ + (struct value) \ + { \ + .type = VALUE_STRING, .string = slice_whole(v) \ + } static inline void test_infix(struct infix *expr, struct value lval, struct slice *op, - struct value rval) + struct value rval) { test_expected(expr->left, lval); asserteq(slice_cmp(&expr->operator, op), 0); @@ -126,18 +137,30 @@ static inline void test_literal_variables(void) { struct { - char *input; + char *input; struct value val; } tests[] = { - { "{{ foo }}", VIDENT("foo"), }, - { "{{ 20 }}", VINT(20), }, - { "{{ true }}", VBOOL(true), }, - { "{{ false }}", VBOOL(false), }, - { 0 }, + { + "{{ foo }}", + VIDENT("foo"), + }, + { + "{{ 20 }}", + VINT(20), + }, + { + "{{ true }}", + VBOOL(true), + }, + { + "{{ false }}", + VBOOL(false), + }, + {0}, }; for (size_t i = 0; tests[i].input != NULL; i++) { - struct parser *parser = parser_new(strdup("test"), tests[i].input); - struct template *tmpl = parser_parse_template(parser); + struct parser *parser = parser_new(strdup("test"), tests[i].input); + struct template *tmpl = parser_parse_template(parser); check_parser_errors(parser); assertneq(tmpl, NULL); asserteq(tmpl->blocks->len, 1); @@ -153,21 +176,45 @@ static inline void test_prefix_variables(void) { struct { - char *input; + char *input; struct slice operator; struct value val; } tests[] = { - { "{{ !foo }}", slice_whole("!"), VIDENT("foo"), }, - { "{{ -bar }}", slice_whole("-"), VIDENT("bar"), }, - { "{{ -20 }}", slice_whole("-"), VINT(20), }, - { "{{ !true }}", slice_whole("!"), VBOOL(true), }, - { "{{ !false }}", slice_whole("!"), VBOOL(false), }, - { "{{ not false }}", slice_whole("not"), VBOOL(false), }, - { 0 }, + { + "{{ !foo }}", + slice_whole("!"), + VIDENT("foo"), + }, + { + "{{ -bar }}", + slice_whole("-"), + VIDENT("bar"), + }, + { + "{{ -20 }}", + slice_whole("-"), + VINT(20), + }, + { + "{{ !true }}", + slice_whole("!"), + VBOOL(true), + }, + { + "{{ !false }}", + slice_whole("!"), + VBOOL(false), + }, + { + "{{ not false }}", + slice_whole("not"), + VBOOL(false), + }, + {0}, }; for (size_t i = 0; tests[i].input != NULL; i++) { - struct parser *parser = parser_new(strdup("test"), tests[i].input); - struct template *tmpl = parser_parse_template(parser); + struct parser *parser = parser_new(strdup("test"), tests[i].input); + struct template *tmpl = parser_parse_template(parser); check_parser_errors(parser); assertneq(tmpl, NULL); asserteq(tmpl->blocks->len, 1); @@ -175,7 +222,7 @@ test_prefix_variables(void) asserteq(blk->type, BLOCK_VARIABLE); asserteq(blk->variable.expression->type, EXPRESSION_PREFIX); struct expression *pref = blk->variable.expression; - asserteq(slice_cmp(&pref->prefix.operator, &tests[i].operator), 0); + asserteq(slice_cmp(&pref->prefix.operator, & tests[i].operator), 0); test_expected(pref->prefix.right, tests[i].val); parser_destroy(parser); template_destroy(tmpl); @@ -186,28 +233,88 @@ static inline void test_infix_variables(void) { struct { - char *input; + char *input; struct value left; struct slice operator; struct value right; } tests[] = { - { "{{ foo + bar }}", VIDENT("foo"), slice_whole("+"), VIDENT("bar"), }, - { "{{ 6 - 9 }}", VINT(6),slice_whole("-"), VINT(9), }, - { "{{ 4 * 20 }}", VINT(4), slice_whole("*"), VINT(20), }, - { "{{ foo / 20 }}", VIDENT("foo"), slice_whole("/"), VINT(20), }, - { "{{ \"str\" == \"str\" }}", VSTR("str"), slice_whole("=="), VSTR("str"), }, - { "{{ true != false }}", VBOOL(true), slice_whole("!="), VBOOL(false), }, - { "{{ 4 < 20 }}", VINT(4), slice_whole("<"), VINT(20), }, - { "{{ 4 <= 20 }}", VINT(4), slice_whole("<="), VINT(20), }, - { "{{ 100 > 20 }}", VINT(100), slice_whole(">"), VINT(20), }, - { "{{ 100 >= 20 }}", VINT(100), slice_whole(">="), VINT(20), }, - { "{{ true and true }}", VBOOL(true), slice_whole("and"), VBOOL(true), }, - { "{{ true or false }}", VBOOL(true), slice_whole("or"), VBOOL(false), }, - { 0 }, + { + "{{ foo + bar }}", + VIDENT("foo"), + slice_whole("+"), + VIDENT("bar"), + }, + { + "{{ 6 - 9 }}", + VINT(6), + slice_whole("-"), + VINT(9), + }, + { + "{{ 4 * 20 }}", + VINT(4), + slice_whole("*"), + VINT(20), + }, + { + "{{ foo / 20 }}", + VIDENT("foo"), + slice_whole("/"), + VINT(20), + }, + { + "{{ \"str\" == \"str\" }}", + VSTR("str"), + slice_whole("=="), + VSTR("str"), + }, + { + "{{ true != false }}", + VBOOL(true), + slice_whole("!="), + VBOOL(false), + }, + { + "{{ 4 < 20 }}", + VINT(4), + slice_whole("<"), + VINT(20), + }, + { + "{{ 4 <= 20 }}", + VINT(4), + slice_whole("<="), + VINT(20), + }, + { + "{{ 100 > 20 }}", + VINT(100), + slice_whole(">"), + VINT(20), + }, + { + "{{ 100 >= 20 }}", + VINT(100), + slice_whole(">="), + VINT(20), + }, + { + "{{ true and true }}", + VBOOL(true), + slice_whole("and"), + VBOOL(true), + }, + { + "{{ true or false }}", + VBOOL(true), + slice_whole("or"), + VBOOL(false), + }, + {0}, }; for (size_t i = 0; tests[i].input != NULL; i++) { - struct parser *parser = parser_new(strdup("test"), tests[i].input); - struct template *tmpl = parser_parse_template(parser); + struct parser *parser = parser_new(strdup("test"), tests[i].input); + struct template *tmpl = parser_parse_template(parser); check_parser_errors(parser); assertneq(tmpl, NULL); asserteq(tmpl->blocks->len, 1); @@ -215,7 +322,7 @@ test_infix_variables(void) asserteq(blk->type, BLOCK_VARIABLE); asserteq(blk->variable.expression->type, EXPRESSION_INFIX); test_infix(&blk->variable.expression->infix, - tests[i].left, &tests[i].operator, tests[i].right); + tests[i].left, &tests[i].operator, tests[i].right); parser_destroy(parser); template_destroy(tmpl); } @@ -224,11 +331,11 @@ test_infix_variables(void) static inline void test_map_variables(void) { - char *input = "{{ map.key }}"; - struct value left = VIDENT("map"); - struct value key = VIDENT("key"); - struct parser *parser = parser_new(strdup("test"), input); - struct template *tmpl = parser_parse_template(parser); + char *input = "{{ map.key }}"; + struct value left = VIDENT("map"); + struct value key = VIDENT("key"); + struct parser *parser = parser_new(strdup("test"), input); + struct template *tmpl = parser_parse_template(parser); check_parser_errors(parser); assertneq(tmpl, NULL); asserteq(tmpl->blocks->len, 1); @@ -245,13 +352,13 @@ test_map_variables(void) static inline void test_index_variables(void) { - char *input = "{{ arr[1 + 2] }}"; - struct value left = VIDENT("arr"); - struct value ileft = VINT(1); - struct slice iop = slice_whole("+"); - struct value iright = VINT(2); - struct parser *parser = parser_new(strdup("test"), input); - struct template *tmpl = parser_parse_template(parser); + char *input = "{{ arr[1 + 2] }}"; + struct value left = VIDENT("arr"); + struct value ileft = VINT(1); + struct slice iop = slice_whole("+"); + struct value iright = VINT(2); + struct parser *parser = parser_new(strdup("test"), input); + struct template *tmpl = parser_parse_template(parser); check_parser_errors(parser); assertneq(tmpl, NULL); @@ -350,11 +457,11 @@ test_operator_precedence(void) "{{ foo.bar + bar[0].baz * foo.bar.baz }}", "{{ (foo.bar + (bar[0].baz * foo.bar.baz)) }}", }, - { 0 }, + {0}, }; for (size_t i = 0; tests[i].input != NULL; i++) { - struct parser *parser = parser_new(strdup("test"), tests[i].input); - struct template *tmpl = parser_parse_template(parser); + struct parser *parser = parser_new(strdup("test"), tests[i].input); + struct template *tmpl = parser_parse_template(parser); check_parser_errors(parser); assertneq(tmpl, NULL); asserteq(tmpl->blocks->len, 1); @@ -371,17 +478,18 @@ test_operator_precedence(void) static inline void test_loop_tag(void) { - char *input = "{% for v in seq %}" - "{% break %}" - "{% endfor %}"; - struct slice item = slice_whole("v"); - struct slice seq = slice_whole("seq"); - struct parser *parser = parser_new(strdup("test"), input); - struct template *tmpl = parser_parse_template(parser); + char *input = "{% for v in seq %}" + "{% break %}" + "{% endfor %}" + "{{ foo }}"; + struct slice item = slice_whole("v"); + struct slice seq = slice_whole("seq"); + struct parser *parser = parser_new(strdup("test"), input); + struct template *tmpl = parser_parse_template(parser); check_parser_errors(parser); assertneq(tmpl, NULL); - asserteq(tmpl->blocks->len, 1); + asserteq(tmpl->blocks->len, 2); struct block *blk = tmpl->blocks->values[0]; asserteq(blk->type, BLOCK_TAG); asserteq(blk->tag.type, TAG_FOR); @@ -398,6 +506,9 @@ test_loop_tag(void) asserteq(sub2->tag.type, TAG_CLOSE); asserteq(sub2->tag.token.type, TOKEN_ENDFOR); + struct block *extra_blk = tmpl->blocks->values[1]; + asserteq(extra_blk->type, BLOCK_VARIABLE); + parser_destroy(parser); template_destroy(tmpl); } @@ -405,21 +516,21 @@ test_loop_tag(void) static inline void test_cond_tag(void) { - char *input = "{% if false %}" - "{{ foo }}" - "{% elif 1 > 2 %}" - "{{ bar }}" - "{% else %}" - "baz" - "{% endif %}"; - struct value ifexp = VIDENT("foo"); - struct value elifl = VINT(1); - struct slice elifop = slice_whole(">"); - struct value elifr = VINT(2); - struct value elifexp = VIDENT("bar"); - struct slice elsecont = slice_whole("baz"); - struct parser *parser = parser_new(strdup("test"), input); - struct template *tmpl = parser_parse_template(parser); + char *input = "{% if false %}" + "{{ foo }}" + "{% elif 1 > 2 %}" + "{{ bar }}" + "{% else %}" + "baz" + "{% endif %}"; + struct value ifexp = VIDENT("foo"); + struct value elifl = VINT(1); + struct slice elifop = slice_whole(">"); + struct value elifr = VINT(2); + struct value elifexp = VIDENT("bar"); + struct slice elsecont = slice_whole("baz"); + struct parser *parser = parser_new(strdup("test"), input); + struct template *tmpl = parser_parse_template(parser); check_parser_errors(parser); assertneq(tmpl, NULL); @@ -462,10 +573,10 @@ test_cond_tag(void) static inline void test_parent_tag(void) { - char *input = "{% extends \"base.html\" %}"; - struct slice name = slice_whole("base.html"); - struct parser *parser = parser_new(strdup("test"), input); - struct template *tmpl = parser_parse_template(parser); + char *input = "{% extends \"base.html\" %}"; + struct slice name = slice_whole("base.html"); + struct parser *parser = parser_new(strdup("test"), input); + struct template *tmpl = parser_parse_template(parser); check_parser_errors(parser); assertneq(tmpl, NULL); @@ -482,11 +593,11 @@ test_parent_tag(void) static inline void test_tblock_tag(void) { - char *input = "{% block cock %}" - "{% endblock %}"; - struct slice name = slice_whole("cock"); - struct parser *parser = parser_new(strdup("test"), input); - struct template *tmpl = parser_parse_template(parser); + char *input = "{% block cock %}" + "{% endblock %}"; + struct slice name = slice_whole("cock"); + struct parser *parser = parser_new(strdup("test"), input); + struct template *tmpl = parser_parse_template(parser); check_parser_errors(parser); assertneq(tmpl, NULL); diff --git a/src/token.c b/src/token.c index 0d0092d..32214b9 100644 --- a/src/token.c +++ b/src/token.c @@ -6,24 +6,24 @@ #include "hmap.h" static struct hmap *keywords = NULL; -static const char *keys[] = { - "and", - "or", - "not", - "for", - "in", - "break", - "endfor", - "true", - "false", - "if", - "elif", - "else", - "endif", - "extends", - "block", - "endblock", - NULL, +static const char *keys[] = { + "and", + "or", + "not", + "for", + "in", + "break", + "endfor", + "true", + "false", + "if", + "elif", + "else", + "endif", + "extends", + "block", + "endblock", + NULL, }; enum token_type values[] = { TOKEN_AND, @@ -46,55 +46,56 @@ enum token_type values[] = { }; const char *token_types[] = { - "ILLEGAL", - "EOF", + [TOKEN_ILLEGAL] = "ILLEGAL", + [TOKEN_EOF] = "EOF", /* Identifiers/Literals */ - "IDENTIFIER", - "INTEGER", - "STRING", + [TOKEN_IDENT] = "IDENTIFIER", + [TOKEN_INT] = "INTEGER", + [TOKEN_STRING] = "STRING", /* Operators */ - "=", - "+", - "-", - "!", - "*", - "/", - "<", - ">", - "<=", - ">=", - "==", - "!=", - "and", - "or", - "not", + [TOKEN_ASSIGN] = "=", + [TOKEN_PLUS] = "+", + [TOKEN_MINUS] = "-", + [TOKEN_BANG] = "!", + [TOKEN_ASTERISK] = "*", + [TOKEN_SLASH] = "/", + [TOKEN_LT] = "<", + [TOKEN_GT] = ">", + [TOKEN_LTE] = "<=", + [TOKEN_GTE] = ">=", + [TOKEN_EQ] = "==", + [TOKEN_NOTEQ] = "!=", + /* Keyword-like operators */ + [TOKEN_AND] = "and", + [TOKEN_OR] = "or", + [TOKEN_NOT] = "not", /* Delimiters */ - ".", - ",", - "(", - ")", - "{", - "}", - "[", - "]", - "#", - "%", + [TOKEN_DOT] = ".", + [TOKEN_COMMA] = ",", + [TOKEN_LPAREN] = "(", + [TOKEN_RPAREN] = ")", + [TOKEN_LBRACE] = "{", + [TOKEN_RBRACE] = "}", + [TOKEN_LBRACKET] = "[", + [TOKEN_RBRACKET] = "]", + [TOKEN_POUND] = "#", + [TOKEN_PERCENT] = "%", /* Keywords */ - "for", - "in", - "break", - "endfor", - "true", - "false", - "if", - "elif", - "else", - "endif", - "extends", - "block", - "endblock", + [TOKEN_FOR] = "for", + [TOKEN_IN] = "in", + [TOKEN_BREAK] = "break", + [TOKEN_ENDFOR] = "endfor", + [TOKEN_TRUE] = "true", + [TOKEN_FALSE] = "false", + [TOKEN_IF] = "if", + [TOKEN_ELIF] = "elif", + [TOKEN_ELSE] = "else", + [TOKEN_ENDIF] = "endif", + [TOKEN_EXTENDS] = "extends", + [TOKEN_BLOCK] = "block", + [TOKEN_ENDBLOCK] = "endblock", /* The document content */ - "CONTENT", + [TOKEN_CONTENT] = "CONTENT", }; void @@ -106,7 +107,6 @@ token_init_keywords(void) hmap_set(keywords, keys[i], values + i); } } - } enum token_type @@ -129,10 +129,10 @@ token_type_print(enum token_type t) sds token_string(struct token *token, sds str) { - const char *type = token_type_print(token->type); - sds slicebuf = sdsempty(); + const char *type = token_type_print(token->type); + sds slicebuf = sdsempty(); sdscatfmt(str, "TOKEN: type: %s, literal: %s", type, - slice_string(&token->literal, slicebuf)); + slice_string(&token->literal, slicebuf)); sdsfree(slicebuf); return str; } -- cgit v1.2.3