#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; }; 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); 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; } 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; 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: %u => ", rule->left); map_list(rule->right, print_tnt); printf("\n"); } /* 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_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, ...) { /* 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(void *rule, int flag) { 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); }