204 lines
4.3 KiB
C
204 lines
4.3 KiB
C
// 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);
|
|
}
|