diff options
Diffstat (limited to '')
| -rw-r--r-- | extras/libparser-syntax-highlighter.c | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/extras/libparser-syntax-highlighter.c b/extras/libparser-syntax-highlighter.c new file mode 100644 index 0000000..f1dbddd --- /dev/null +++ b/extras/libparser-syntax-highlighter.c @@ -0,0 +1,262 @@ +/* See LICENSE file for copyright and license details. */ +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <libparser.h> + + +#define LIST_RULES(X, D)\ + X("comment", colourise, "31") D\ + X("intrusive-identifier", colourise, "33") D\ + X("discrete-identifier", colourise, "") D\ + X("escape-payload", ignore, "") D\ + X("ESCAPE", colourise, "2;34") D\ + X("escape", colourise_and_descend, "34") D\ + X("string", colourise_and_descend, "32") D\ + X("character", descend, "") D\ + X("integer", ignore, "") D\ + X("boundary", descend, "") D\ + X("low", descend, "") D\ + X("high", descend, "") D\ + X("NONDETERMINISTIC", colourise, "1;33") D\ + X("COMMITTED", colourise, "1;33") D\ + X("committed", descend, "") D\ + X("REJECTION", colourise, "1;31") D\ + X("rejection", descend, "") D\ + X("EXCEPTION", colourise, "1;31") D\ + X("exception", descend, "") D\ + X("CONCATENATION", colourise, "2") D\ + X("concatenation", descend, "") D\ + X("ALTERNATION", colourise, "") D\ + X("alternation", descend, "") D\ + X("CHAR-RANGE-START", ignore, "") D\ + X("CHAR-RANGE-COMMA", ignore, "") D\ + X("CHAR-RANGE-END", ignore, "") D\ + X("CHAR-RANGE-EDGE", ignore, "") D\ + X("CHAR-RANGE", ignore, "") D\ + X("char-range", colourise_and_descend, "35") D\ + X("OPTIONAL-START", ignore, "") D\ + X("OPTIONAL-END", ignore, "") D\ + X("OPTIONAL", colourise, "1;34") D\ + X("optional", descend, "") D\ + X("REPEATED-START", ignore, "") D\ + X("REPEATED-END", ignore, "") D\ + X("REPEATED", colourise, "1;32") D\ + X("repeated", descend, "") D\ + X("GROUP-START", ignore, "") D\ + X("GROUP-END", ignore, "") D\ + X("GROUP", colourise, "1") D\ + X("group", descend, "") D\ + X("embedded-rule", descend, "") D\ + X("operand", descend, "") D\ + X("DEFINITION", ignore, "") D\ + X("TERMINATION", ignore, "") D\ + X("RULE", colourise, "1;36") D\ + X("rule-name", descend, "") D\ + X("rule", descend, "") D\ + X("grammar", descend, "") + + +static const char *argv0; + +static char *text = NULL; +static size_t size = 0; +static size_t len = 0; +static size_t off = 0; + + +static void descend(struct libparser_unit *tree, const char *colour); + + +static void +write_all(const char *s, size_t n) +{ + ssize_t r; + while (n) { + r = write(STDOUT_FILENO, s, n); + if (r < 0) { + if (errno == EINTR) + continue; + fprintf(stderr, "%s: write %s: %s\n", argv0, "<stdout>", strerror(errno)); + exit(1); + } + s = &s[r]; + n -= (size_t)r; + } +} + + +static void +write_str(const char *s) +{ + write_all(s, strlen(s)); +} + + +static void +output(size_t to) +{ + if (to > off) { + write_all(&text[off], to - off); + off = to; + } +} + + +static void +ignore(struct libparser_unit *tree, const char *colour) +{ + (void) tree; + (void) colour; +} + + +static void +colourise(struct libparser_unit *tree, const char *colour) +{ + output(tree->start); + write_str("\033[m"); + write_str(colour); + output(tree->end); + write_str("\033[m"); +} + + +static void +colourise_and_descend(struct libparser_unit *tree, const char *colour) +{ + struct libparser_unit *node; + output(tree->start); + write_str("\033[m"); + write_str(colour); + +#define X(RULE, ACTION, COLOUR)\ + if (!strcmp(node->rule, RULE)) ACTION(node, "\033["COLOUR"m"); + + for (node = tree->in; node; node = node->next) { + LIST_RULES(X, else) else descend(node, ""); + } + +#undef X + + write_str("\033[m"); + write_str(colour); + output(tree->end); + write_str("\033[m"); +} + + +static void +descend(struct libparser_unit *tree, const char *colour) +{ + struct libparser_unit *node; + + (void) colour; + +#define X(RULE, ACTION, COLOUR)\ + if (!strcmp(node->rule, RULE)) ACTION(node, "\033["COLOUR"m"); + + for (node = tree->in; node; node = node->next) { + LIST_RULES(X, else) else descend(node, ""); + } + +#undef X +} + + +static void +free_tree(struct libparser_unit *tree) +{ + struct libparser_unit *node; + struct libparser_unit *next; + + if (!tree) + return; + + for (node = tree->in; node; node = next) { + next = node->next; + free_tree(node); + } + + free(tree); +} + + +int +main(int argc, char *argv[]) +{ + struct libparser_unit *tree = NULL; + ssize_t r; + int fd = STDIN_FILENO; + const char *path = "<stdin>"; + + argv0 = *argv++; + argc--; + + if (argc && !strcmp(*argv, "--")) { + argv++; + argc--; + } else if (argc && argv[0][0] == '-' && argv[0][1]) { + goto usage; + } + if (argc > 1) + goto usage; + if (argc && !strcmp(*argv, "-")) + argc--; + + if (argc) { + path = *argv; + fd = open(path, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "%s: open %s O_RDONLY: %s\n", argv[0], path, strerror(errno)); + exit(1); + } + } + + for (;;) { + if (len == size) { + size += 8096u; + text = realloc(text, size); + if (!text) { + fprintf(stderr, "%s: realloc %zu: %s\n", argv[0], size, strerror(errno)); + exit(1); + } + } + r = read(fd, &text[len], size - len); + if (!r) + break; + if (r < 0) { + if (errno == EINTR) + continue; + fprintf(stderr, "%s: read %s: %s\n", argv[0], path, strerror(errno)); + exit(1); + } + len += (size_t)r; + } + + if (argc) + close(fd); + + r = libparser_parse_file(libparser_rule_table, text, len, &tree); + if (r < 0) { + fprintf(stderr, "%s: libparser_parse_file: %s\n", argv0, strerror(errno)); + exit(1); + } else if (!tree || tree->end != (size_t)len || !r) { + fprintf(stderr, "%s: failed to parse input\n", argv0); + exit(1); + } + + descend(tree, ""); + output(len); + + free(text); + free_tree(tree); + return 0; + +usage: + fprintf(stderr, "usage: %s [file]\n", argv0); + exit(1); +} |
