diff options
Diffstat (limited to 'ast.c')
-rw-r--r-- | ast.c | 99 |
1 files changed, 99 insertions, 0 deletions
@@ -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); +} + |