diff options
Diffstat (limited to 'src/grammar.c')
-rw-r--r-- | src/grammar.c | 118 |
1 files changed, 101 insertions, 17 deletions
diff --git a/src/grammar.c b/src/grammar.c index 9265ef5..fd38ac8 100644 --- a/src/grammar.c +++ b/src/grammar.c @@ -10,7 +10,14 @@ struct Rule_s { List *right; }; -TNT *new_tnt(int type, ...) +struct Grammar_s { + List *rules; + /* a list of names of non-terminals */ + List *names; +}; + +TNT * +new_tnt(int type, ...) { va_list args; va_start(args, type); @@ -26,10 +33,11 @@ TNT *new_tnt(int type, ...) return result; } -Rule *new_rule(NT left, List *right) +Rule * +new_rule(NT left, List *right) { if (!right) return NULL; - + Rule *rule = MYALLOC(Rule, 1); rule->left = left; @@ -38,7 +46,22 @@ Rule *new_rule(NT left, List *right) return rule; } -void print_tnt(void *element) +Grammar * +new_grammar() +{ + Grammar *g = MYALLOC(Grammar, 1); + return g; +} + +void +build_grammar(Grammar *g, List *rules, List *names) +{ + g->rules = rules; + g->names = names; +} + +void +print_tnt(void *element) { TNT *tnt = (TNT*) element; @@ -48,35 +71,55 @@ void print_tnt(void *element) printf("T %lu, ", tnt->data.t); } -void print_rule(void *r) +void +print_rule(void *r) { - Rule *rule = (Rule *)r; - printf("Rule: NT %u => ", rule->left); - + Rule *rule = (Rule *) r; + printf("Rule: %u => ", rule->left); + map_list(rule->right, print_tnt); printf("\n"); } -void print_grammar(Grammar g) +/* a local function pointer */ +void +print_name(void *element) +{ + char *str = (char *) element; + printf("%s", str); +} + +/* a local function pointer */ +void +print_sep() +{ + printf(", "); +} + +void +print_grammar(Grammar *g) { printf("Printing a grammar:\n"); - map_list(g, print_rule); + map_list_between(g->names, print_name, print_sep); + printf("\n"); + map_list(g->rules, print_rule); printf("\n"); } -List *new_tnt_string(char *format, int format_len, ...) +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': @@ -99,8 +142,49 @@ List *new_tnt_string(char *format, int format_len, ...) return result; } -void destroy_rule(Rule *rule) +void +destroy_rule(void *rule, int flag) { - destroy_list(rule->right, 1); + Rule * r = (Rule *) rule; + destroy_list(r->right, flag); free(rule); } + +void +destroy_rule_and_free_all(void *rule) +{ + destroy_rule(rule, 1); +} + +void +destroy_rule_and_free_first(void *rule) +{ + destroy_rule(rule, 2); +} + +void +destroy_rule_no_free(void *rule) +{ + destroy_rule(rule, 0); +} + +void +destroy_grammar(void *grammar, int flag) +{ + Grammar *g = (Grammar *) grammar; + + switch (flag) { + case 0: + map_list(g->rules, destroy_rule_no_free); + break; + case 1: + map_list(g->rules, destroy_rule_and_free_all); + break; + default: + map_list(g->rules, destroy_rule_and_free_first); + break; + } + + destroy_list(g->rules, 0); + destroy_list(g->names, flag); +} |