aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYaroslav de la Peña Smirnov <yps@yaroslavps.com>2023-01-26 22:39:41 +0300
committerYaroslav de la Peña Smirnov <yps@yaroslavps.com>2023-01-26 22:39:41 +0300
commit49c2589427e0f81bea68ccba1a95c6890e10538d (patch)
tree0633bc052552831b3860d1d4816bbee7b85d6313 /src
parent4665a620775da64ec7280762979a9fc6fa37c0bc (diff)
downloadroscha-49c2589427e0f81bea68ccba1a95c6890e10538d.tar.gz
roscha-49c2589427e0f81bea68ccba1a95c6890e10538d.zip
Fix break tag parsing and code formatHEADmaster
auto-formatted the code with clang-format.
Diffstat (limited to 'src')
-rw-r--r--src/ast.c8
-rw-r--r--src/hmap.c160
-rw-r--r--src/lexer.c56
-rw-r--r--src/object.c89
-rw-r--r--src/parser.c145
-rw-r--r--src/roscha.c133
-rw-r--r--src/tests/parser.c335
-rw-r--r--src/token.c132
8 files changed, 583 insertions, 475 deletions
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;
}