1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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);
}
|