#include #include #include #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); }