diff options
Diffstat (limited to 'src/grammar/parser-lalr-main.c')
| -rw-r--r-- | src/grammar/parser-lalr-main.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/src/grammar/parser-lalr-main.c b/src/grammar/parser-lalr-main.c new file mode 100644 index 00000000000..db88a1f2999 --- /dev/null +++ b/src/grammar/parser-lalr-main.c @@ -0,0 +1,203 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> + +extern int yylex(); +extern int rsparse(); + +#define PUSHBACK_LEN 4 + +static char pushback[PUSHBACK_LEN]; +static int verbose; + +void print(const char* format, ...) { + va_list args; + va_start(args, format); + if (verbose) { + vprintf(format, args); + } + va_end(args); +} + +// If there is a non-null char at the head of the pushback queue, +// dequeue it and shift the rest of the queue forwards. Otherwise, +// return the token from calling yylex. +int rslex() { + if (pushback[0] == '\0') { + return yylex(); + } else { + char c = pushback[0]; + memmove(pushback, pushback + 1, PUSHBACK_LEN - 1); + pushback[PUSHBACK_LEN - 1] = '\0'; + return c; + } +} + +// Note: this does nothing if the pushback queue is full. As long as +// there aren't more than PUSHBACK_LEN consecutive calls to push_back +// in an action, this shouldn't be a problem. +void push_back(char c) { + for (int i = 0; i < PUSHBACK_LEN; ++i) { + if (pushback[i] == '\0') { + pushback[i] = c; + break; + } + } +} + +extern int rsdebug; + +struct node { + struct node *next; + struct node *prev; + int own_string; + char const *name; + int n_elems; + struct node *elems[]; +}; + +struct node *nodes = NULL; +int n_nodes; + +struct node *mk_node(char const *name, int n, ...) { + va_list ap; + int i = 0; + unsigned sz = sizeof(struct node) + (n * sizeof(struct node *)); + struct node *nn, *nd = (struct node *)malloc(sz); + + print("# New %d-ary node: %s = %p\n", n, name, nd); + + nd->own_string = 0; + nd->prev = NULL; + nd->next = nodes; + if (nodes) { + nodes->prev = nd; + } + nodes = nd; + + nd->name = name; + nd->n_elems = n; + + va_start(ap, n); + while (i < n) { + nn = va_arg(ap, struct node *); + print("# arg[%d]: %p\n", i, nn); + print("# (%s ...)\n", nn->name); + nd->elems[i++] = nn; + } + va_end(ap); + n_nodes++; + return nd; +} + +struct node *mk_atom(char *name) { + struct node *nd = mk_node((char const *)strdup(name), 0); + nd->own_string = 1; + return nd; +} + +struct node *mk_none() { + return mk_atom("<none>"); +} + +struct node *ext_node(struct node *nd, int n, ...) { + va_list ap; + int i = 0, c = nd->n_elems + n; + unsigned sz = sizeof(struct node) + (c * sizeof(struct node *)); + struct node *nn; + + print("# Extending %d-ary node by %d nodes: %s = %p", + nd->n_elems, c, nd->name, nd); + + if (nd->next) { + nd->next->prev = nd->prev; + } + if (nd->prev) { + nd->prev->next = nd->next; + } + nd = realloc(nd, sz); + nd->prev = NULL; + nd->next = nodes; + nodes->prev = nd; + nodes = nd; + + print(" ==> %p\n", nd); + + va_start(ap, n); + while (i < n) { + nn = va_arg(ap, struct node *); + print("# arg[%d]: %p\n", i, nn); + print("# (%s ...)\n", nn->name); + nd->elems[nd->n_elems++] = nn; + ++i; + } + va_end(ap); + return nd; +} + +int const indent_step = 4; + +void print_indent(int depth) { + while (depth) { + if (depth-- % indent_step == 0) { + print("|"); + } else { + print(" "); + } + } +} + +void print_node(struct node *n, int depth) { + int i = 0; + print_indent(depth); + if (n->n_elems == 0) { + print("%s\n", n->name); + } else { + print("(%s\n", n->name); + for (i = 0; i < n->n_elems; ++i) { + print_node(n->elems[i], depth + indent_step); + } + print_indent(depth); + print(")\n"); + } +} + +int main(int argc, char **argv) { + if (argc == 2 && strcmp(argv[1], "-v") == 0) { + verbose = 1; + } else { + verbose = 0; + } + int ret = 0; + struct node *tmp; + memset(pushback, '\0', PUSHBACK_LEN); + ret = rsparse(); + print("--- PARSE COMPLETE: ret:%d, n_nodes:%d ---\n", ret, n_nodes); + if (nodes) { + print_node(nodes, 0); + } + while (nodes) { + tmp = nodes; + nodes = tmp->next; + if (tmp->own_string) { + free((void*)tmp->name); + } + free(tmp); + } + return ret; +} + +void rserror(char const *s) { + fprintf(stderr, "%s\n", s); +} |
