summaryrefslogtreecommitdiff
path: root/ast.c
blob: d261b9d832624978f3fb99c3813dca0899e3f5a6 (plain)
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);
}