diff options
author | JSDurand <mmemmew@gmail.com> | 2021-11-08 16:37:57 +0800 |
---|---|---|
committer | JSDurand <mmemmew@gmail.com> | 2021-11-08 16:37:57 +0800 |
commit | 9594210f02572681ed581c5197ace4c207db0917 (patch) | |
tree | 08bf1bf079d111c64cf3128dd68323abdce78228 /src/grammar.c |
initial commit
Now the rough framework is established and the grammar class is sort
of ready.
It remains to write a general input reading mechanism.
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); +} |