diff options
Diffstat (limited to 'src/grammar.c')
-rw-r--r-- | src/grammar.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/grammar.c b/src/grammar.c new file mode 100644 index 0000000..9265ef5 --- /dev/null +++ b/src/grammar.c @@ -0,0 +1,106 @@ +#include "grammar.h" + +struct TNT_s { + int type; /* 0 => T and NT otherwise */ + union { T t; NT nt; } data; +}; + +struct Rule_s { + NT left; + List *right; +}; + +TNT *new_tnt(int type, ...) +{ + va_list args; + va_start(args, type); + + TNT *result = MYALLOC(TNT, 1); + result->type = type; + + if (type) result->data.nt = va_arg(args, NT); + else result->data.t = va_arg(args, T); + + va_end(args); + + return result; +} + +Rule *new_rule(NT left, List *right) +{ + if (!right) return NULL; + + Rule *rule = MYALLOC(Rule, 1); + + rule->left = left; + rule->right = right; + + return rule; +} + +void print_tnt(void *element) +{ + TNT *tnt = (TNT*) element; + + if (tnt->type) + printf("NT %u, ", tnt->data.nt); + else + printf("T %lu, ", tnt->data.t); +} + +void print_rule(void *r) +{ + Rule *rule = (Rule *)r; + printf("Rule: NT %u => ", rule->left); + + map_list(rule->right, print_tnt); + + printf("\n"); +} + +void print_grammar(Grammar g) +{ + printf("Printing a grammar:\n"); + map_list(g, print_rule); + printf("\n"); +} + +List *new_tnt_string(char *format, int format_len, ...) +{ + /* FORMAT_LEN does not include the terminating null byte, so it + should be > 0. */ + + if (format_len <= 0) return NULL; + + List *result = new_list(); + + va_list args; + va_start(args, format_len); + + for (int point = 0; point < format_len; point++) { + switch (*(format+point)) { + case 'n': + add_to_list(result, new_tnt(1, va_arg(args, NT))); + break; + case 't': + add_to_list(result, new_tnt(0, va_arg(args, T))); + break; + default: + eprintf("Wront character: %c\n", *(format+point)); + destroy_list(result, 1); + va_end(args); + return NULL; + break; + } + } + + va_end(args); + + return result; +} + +void destroy_rule(Rule *rule) +{ + destroy_list(rule->right, 1); + free(rule); +} |