aboutsummaryrefslogtreecommitdiffstats
path: root/extras/libparser-syntax-highlighter.c
diff options
context:
space:
mode:
Diffstat (limited to 'extras/libparser-syntax-highlighter.c')
-rw-r--r--extras/libparser-syntax-highlighter.c262
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);
+}