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
|
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "ast.h"
struct atom *ast;
struct atom *mkatom(const struct atom *src)
{
struct atom *ret = malloc(sizeof *ret);
if (ret) *ret = *src;
return ret;
}
static void ivprintf(int level, const char *fmt, va_list ap)
{
printf("%*s", 4 * level, "");
vprintf(fmt, ap);
}
static void iprintf(int level, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
ivprintf(level, fmt, ap);
va_end(ap);
}
static void dump_atom_indent(const struct atom *a, int level);
static void dump_atom_children(const struct atom *a, int level, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
ivprintf(level, fmt, ap);
va_end(ap);
iprintf(level, "{\n");
dump_atom_indent(a->u.children[0], level + 1);
dump_atom_indent(a->u.children[1], level + 1);
iprintf(level, "}\n");
}
const char *fmt_repeat(char *buf, const struct repeat *r)
{
if (r->min == r->max)
sprintf(buf, "%ld", r->min);
else if (r->max < 0)
sprintf(buf, "%ld+", r->min);
else
sprintf(buf, "%ld - %ld", r->min, r->max);
return buf;
}
#define FMT_REPEAT(r) fmt_repeat((char[64]){0}, (r))
static void dump_atom_indent(const struct atom *a, int level)
{
switch (a->type) {
case ATOM_ALTERNATION:
dump_atom_children(a, level, "alternation\n");
break;
case ATOM_SEQUENCE:
dump_atom_indent(a->u.children[0], level);
dump_atom_indent(a->u.children[1], level);
break;
case ATOM_REPETITION:
if (a->u.repeat.counts.min == 1 && a->u.repeat.counts.max == 1) {
dump_atom_indent(a->u.repeat.child, level);
} else {
iprintf(level, "repeat %s times\n", FMT_REPEAT(&a->u.repeat.counts));
iprintf(level, "{\n");
dump_atom_indent(a->u.repeat.child, level + 1);
iprintf(level, "}\n");
}
break;
case ATOM_LITERAL:
iprintf(level, "literal: %s\n", a->u.literal);
break;
case ATOM_ALPHABETIC: iprintf(level, "[:alpha:]\n"); break;
case ATOM_NUMERIC: iprintf(level, "[:digit:]\n"); break;
case ATOM_UPPERCASE: iprintf(level, "[:upper:]\n"); break;
case ATOM_LOWERCASE: iprintf(level, "[:lower:]\n"); break;
case ATOM_CONTROL: iprintf(level, "[:cntrl:]\n"); break;
case ATOM_PUNCTUATION: iprintf(level, "[:punct:]\n"); break;
case ATOM_EVERYTHING: iprintf(level, "any\n"); break;
}
}
void dump_atom(const struct atom *a)
{
dump_atom_indent(a, 0);
}
|