#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); }