diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/hashmap.c | 74 | ||||
| -rw-r--r-- | src/hashmap.h | 10 | ||||
| -rw-r--r-- | src/hyde.c | 142 | 
3 files changed, 226 insertions, 0 deletions
| diff --git a/src/hashmap.c b/src/hashmap.c new file mode 100644 index 0000000..3d9edd0 --- /dev/null +++ b/src/hashmap.c @@ -0,0 +1,74 @@ +#include <string.h> +#include <stdlib.h> +#include <err.h> +#include "hashmap.h" + +struct node { +    char *key; +    void *value; +    struct node *next; +}; + +struct hashmap *hashmap_new() { +    struct hashmap *hm = malloc(sizeof *hm); +    if (!hm) err(EXIT_FAILURE, "out of memory"); +    for (int i=0; i < 26; i++) { +        hm->buckets[i] = NULL; +    } + +    return hm; +} + +void hashmap_insert(struct hashmap *hm, char *key, void *value) { +    int pos = (key[0] - 'a') % 26; +    struct node *head = hm->buckets[pos]; +    struct node *node = head; + +    while (node) { +        if (strcmp(node->key, key) == 0) { +            node->value = value; +            return; +        } +        node = node->next; +    } +     +    node = malloc(sizeof *node); +    node->key = key; +    node->value = value; +    node->next = head; +    hm->buckets[pos] = node; +} + +void *hashmap_get(struct hashmap *hm, char *key) { +    int pos = (key[0] - 'a') % 26; +    struct node *node = hm->buckets[pos]; +    while (node) { +        if (strcmp(node->key, key) == 0) { +            return node->value; +        } + +        node = node->next; +    } + +    return NULL; +} + +void hashmap_remove(char *key) { + +} + +void hashmap_free(struct hashmap *hm) { +    struct node *node; +    struct node *next; + +    for (int i=0; i < 26; i++) { +        node = hm->buckets[i]; +        while (node) { +            next = node->next; +            free(node);             +            node = next; +        } +    } + +    free(hm); +}
\ No newline at end of file diff --git a/src/hashmap.h b/src/hashmap.h new file mode 100644 index 0000000..a37d3d6 --- /dev/null +++ b/src/hashmap.h @@ -0,0 +1,10 @@ + +struct hashmap { +    struct node *buckets[26]; +}; + +void hashmap_insert(struct hashmap *hm, char *key, void *value); +void *hashmap_get(struct hashmap *hm, char *key); +void hashmap_remove(char *key); +struct hashmap *hashmap_new(); +void hashmap_free(struct hashmap *hm);
\ No newline at end of file diff --git a/src/hyde.c b/src/hyde.c new file mode 100644 index 0000000..332ddab --- /dev/null +++ b/src/hyde.c @@ -0,0 +1,142 @@ +#include <stdio.h> +#include <stdlib.h> +#include "vendor/mpc.h" +#include "hashmap.h" + + +struct post { +    char title[64]; +    char tags[8][32]; +}; + +char *read_file(char *filename) { +    char *input = malloc(BUFSIZ); +    unsigned int size = 0; + +    FILE *f = fopen(filename, "r"); +    if (!f) { +        printf("Could not open \"%s\" for reading", filename); +        exit(1); +    } + +    unsigned int read = 0; +    while ( (read = fread(input, 1, BUFSIZ, f)) > 0) { +        size += read; +        input = realloc(input, size + BUFSIZ); +    } + +    fclose(f); + +    input[size] = '\0'; +    return input; +} + +int eval(char *dest, mpc_ast_t* t, struct hashmap *ctx) { +    printf("%s: %s\n", t->tag, t->contents); + +    if (strstr(t->tag, "content|text")) { +        strcat(dest, t->contents); +        return 0; +    } + +    if (strstr(t->tag, "content|var")) { +        printf("Key: %s\n", t->contents); +        char *value = hashmap_get(ctx, t->children[1]->contents); +        if  (value == NULL) { +            return 1; +        } +        strcat(dest, value); +        return 0; +    } + +    if (strstr(t->tag, "content|for")) { +        char *tmp_key = t->children[2]->contents; +        char *iterator_key = t->children[4]->contents; +        // TODO: Make this dynamic +        struct post **posts = hashmap_get(ctx, iterator_key); +        for (int i=0; i < 2; i++) { +            hashmap_insert(ctx, tmp_key, posts[i]); +            eval(dest, t->children[6], ctx); +        } +        return 0; +    } + +    for (int i=0; i < t->children_num; i++) { +        eval(dest, t->children[i], ctx); +    } +     +    return 0; +} + +mpc_parser_t *parser_init() { +    mpc_parser_t *Symbol = mpc_new("symbol"); +    mpc_parser_t *Text = mpc_new("text"); +    mpc_parser_t *Var_Open = mpc_new("var_open"); +    mpc_parser_t *Var_Close = mpc_new("var_close"); +    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 *For = mpc_new("for"); +    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_open  : /\{{2} ?/ ;" +    " var_close : / ?}{2}/ ;" +    " var       : <var_open> <symbol> <var_close> ;" +    " block_open: /\{\% ?/ ;" +    " block_close: / ?\%}/ ;" +    " for       : <block_open> \"for \" <symbol> \" in \" <symbol> <block_close> <content>* <block_open> \"endfor\" <block_close> ;" +    " text      : /[^{][^{%]*/ ;" +    " content   : <var> | <for> | <text>;" +    " template  : /^/ <content>* /$/ ;", +    Symbol, Var_Open, Var_Close, Var, Block_Open, Block_Close, For, Text, Content, Template, NULL); +    return Template; +} + +void template(char *tmpl, struct hashmap *ctx) { +    mpc_parser_t *parser = parser_init(); +    mpc_result_t r; + +    if (mpc_parse("input", tmpl, parser, &r)) { +        mpc_ast_print(r.output); +         +        // FIXME: Allocate precisely +        char *output = malloc(strlen(tmpl) * 2); +        output[0] = '\0'; +        eval(output, r.output, ctx); +        printf("Template: \n%s", output); +         +        mpc_ast_delete(r.output); +        free(output); +    } else { +        mpc_err_print(r.error); +        mpc_err_delete(r.error); +    } +} + + +int main() { +    char *input = read_file("index.tpl"); + +    struct hashmap *ctx = hashmap_new(); +    hashmap_insert(ctx, "title", "Hello world"); + +    struct post home = {  +        .title = "Homepage", +        .tags = { +            "Tag 1", "Tag 2" +        } +    }; +    hashmap_insert(ctx, "home", &home); + +    struct post posts[] = { +        { .title = "Post 1", .tags = { "p1t1" } }, +        { .title = "Post 2", .tags = { "p2t1" } }, +    }; +    hashmap_insert(ctx, "posts", &posts); + +    template(input, ctx); +    hashmap_free(ctx); +    free(input); +}
\ No newline at end of file | 
