summaryrefslogtreecommitdiff
path: root/ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'ast.c')
-rw-r--r--ast.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/ast.c b/ast.c
new file mode 100644
index 0000000..d261b9d
--- /dev/null
+++ b/ast.c
@@ -0,0 +1,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);
+}
+