aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hashmap.c5
-rw-r--r--src/parser.c94
-rw-r--r--src/template.c57
-rw-r--r--tests/test_hashmap.c2
4 files changed, 129 insertions, 29 deletions
diff --git a/src/hashmap.c b/src/hashmap.c
index 9f36a58..6797475 100644
--- a/src/hashmap.c
+++ b/src/hashmap.c
@@ -11,6 +11,7 @@ struct node {
struct node *next;
};
+/* allocate a new hashmap */
struct hashmap *hashmap_new() {
struct hashmap *hm = malloc(sizeof *hm);
if (!hm) err(EXIT_FAILURE, "out of memory");
@@ -21,6 +22,7 @@ struct hashmap *hashmap_new() {
return hm;
}
+/* insert key-value into hashmap */
void hashmap_insert(struct hashmap *hm, char *key, void *value) {
int pos = HASH(key);
struct node *head = hm->buckets[pos];
@@ -41,6 +43,7 @@ void hashmap_insert(struct hashmap *hm, char *key, void *value) {
hm->buckets[pos] = node;
}
+/* retrieve value by key */
void *hashmap_get(struct hashmap *hm, char *key) {
int pos = HASH(key);
struct node *node = hm->buckets[pos];
@@ -55,6 +58,7 @@ void *hashmap_get(struct hashmap *hm, char *key) {
return NULL;
}
+/* retrieve value by key, handles dot notation for nested hashmaps */
void *hashmap_resolve(struct hashmap *hm, char *key) {
char tmp_key[64];
int i = 0;
@@ -83,6 +87,7 @@ void hashmap_remove(char *key) {
// TODO: Implement this
}
+/* free hashmap related memory */
void hashmap_free(struct hashmap *hm) {
struct node *node;
struct node *next;
diff --git a/src/parser.c b/src/parser.c
new file mode 100644
index 0000000..e61b1e5
--- /dev/null
+++ b/src/parser.c
@@ -0,0 +1,94 @@
+
+#include <stdlib.h>
+#include <string.h>
+
+struct text {
+ char *str;
+};
+
+struct symbol {
+ char *value;
+};
+
+struct expression {
+ struct symbol symbol;
+};
+
+struct statement {
+
+};
+
+/* discard during parsing phase */
+struct comment {};
+
+
+enum node_type {
+ NODE_EXPR,
+ NODE_COMMENT,
+ NODE_TEXT,
+};
+
+struct node {
+ enum node_type type;
+ union content {
+ struct expression expr;
+ struct comment comment;
+ struct text text;
+ } content;
+};
+
+struct ast {
+ int size;
+ int cap;
+ struct node **nodes;
+};
+
+enum token_type {
+ TOK_EOF,
+ TOK_EXPR_OPEN,
+ TOK_EXPR_CLOSE,
+ TOK_COMMENT_OPEN,
+ TOK_COMMENT_CLOSE,
+ TOK_STMT_OPEN,
+ TOK_STMT_CLOSE,
+ TOK_MINUS,
+ TOK_SYMBOL,
+ TOK_TEXT,
+};
+
+struct token {
+ enum token_type type;
+ char *literal;
+};
+
+struct token gettoken(char *str) {
+ struct token t;
+ switch (str[0]) {
+ case '{':
+
+ break;
+
+ case '}':
+
+ break;
+
+ case '\0':
+ t.type = TOK_EOF;
+ break;
+ }
+
+ return t;
+};
+
+struct ast* parse(char *str) {
+ struct ast* ast = malloc(sizeof *ast);
+ ast->size = 0;
+ ast->cap = 64;
+ ast->nodes = malloc(ast->cap * sizeof *ast->nodes);
+
+ for (struct token t = gettoken(str); t.type != TOK_EOF; t= gettoken(str)) {
+
+ }
+
+ return ast;
+} \ No newline at end of file
diff --git a/src/template.c b/src/template.c
index 12bd8df..6211b19 100644
--- a/src/template.c
+++ b/src/template.c
@@ -43,7 +43,7 @@ char *trim_leading_whitespace(char *str) {
int eval(char *dest, mpc_ast_t* t, struct hashmap *ctx) {
static int trim_whitespace = 0;
- if (strstr(t->tag, "content|var")) {
+ if (strstr(t->tag, "content|expression|")) {
// maybe eat whitespace going backward
if (strstr(t->children[1]->contents, "-")) {
dest = trim_trailing_whitespace(dest);
@@ -96,39 +96,40 @@ int eval(char *dest, mpc_ast_t* t, struct hashmap *ctx) {
}
mpc_parser_t *parser_init() {
- mpc_parser_t *Symbol = mpc_new("symbol");
- mpc_parser_t *Text = mpc_new("text");
- mpc_parser_t *Var = mpc_new("var");
- mpc_parser_t *Block_Open = mpc_new("block_open");
- mpc_parser_t *Block_Close = mpc_new("block_close");
- mpc_parser_t *Comment = mpc_new("comment");
- mpc_parser_t *For = mpc_new("for");
- mpc_parser_t *Body = mpc_new("body");
- mpc_parser_t *Content = mpc_new("content");
- mpc_parser_t *Template = mpc_new("template");
+ mpc_parser_t *symbol = mpc_new("symbol");
+ mpc_parser_t *text = mpc_new("text");
+ mpc_parser_t *expression = mpc_new("expression");
+ mpc_parser_t *statement = mpc_new("statement_open");
+ mpc_parser_t *statement_open = mpc_new("statement_open");
+ mpc_parser_t *statement_close = mpc_new("statement_close");
+ mpc_parser_t *comment = mpc_new("comment");
+ mpc_parser_t *for_statement = mpc_new("for");
+ mpc_parser_t *body = mpc_new("body");
+ mpc_parser_t *content = mpc_new("content");
+ mpc_parser_t *template = mpc_new("template");
mpca_lang(MPCA_LANG_WHITESPACE_SENSITIVE,
" symbol : /[a-zA-Z_.]+/ ;"
- " var : \"{{\" /-? ?/ <symbol> / ?-?/ \"}}\" ;"
- " block_open: /\{\% ?/ ;"
- " block_close: / ?\%}/ ;"
+ " text : /[^{][^{%#]*/ ;"
+ " expression : \"{{\" /-? */ <symbol> / *-?/ \"}}\" ;"
" comment : \"{#\" /[^#][^#}]*/ \"#}\" ;"
- " for : <block_open> \"for \" <symbol> \" in \" <symbol> <block_close> <body> <block_open> \"endfor\" <block_close> ;"
- " text : /[^{][^{%]*/ ;"
- " content : <var> | <for> | <text> | <comment>;"
+ " statement_open: \"{%\" /-? */;"
+ " statement_close: / *-?/ \"%}\";"
+ " for : <statement_open> \"for \" <symbol> \" in \" <symbol> <statement_close> <body> <statement_open> \"endfor\" <statement_close> ;"
+ " content : <expression> | <for> | <text> | <comment>;"
" body : <content>* ;"
" template : /^/ <body> /$/ ;",
- Symbol,
- Var,
- Block_Open,
- Block_Close,
- Comment,
- For,
- Text,
- Content,
- Body,
- Template,
+ symbol,
+ expression,
+ statement_open,
+ statement_close,
+ comment,
+ for_statement,
+ text,
+ content,
+ body,
+ template,
NULL);
- return Template;
+ return template;
}
char *template(char *tmpl, struct hashmap *ctx) {
diff --git a/tests/test_hashmap.c b/tests/test_hashmap.c
index b9e1cfd..14ec552 100644
--- a/tests/test_hashmap.c
+++ b/tests/test_hashmap.c
@@ -12,7 +12,6 @@ TEST(hashmap) {
hashmap_free(hm);
}
-
TEST(dot_notation) {
struct hashmap *user = hashmap_new();
hashmap_insert(user, "name", "Danny");
@@ -21,6 +20,7 @@ TEST(dot_notation) {
assert(hashmap_resolve(hm, "user") == user, "expected user hashmap, got something else");
char *value = (char *) hashmap_resolve(hm, "user.name");
assert_str(value, "Danny");
+ hashmap_free(user);
hashmap_free(hm);
}