mirror of
https://github.com/python/cpython
synced 2026-09-29 12:10:30 +03:00
"Compiling" version
This commit is contained in:
parent
226d79eb4a
commit
3f5da24ea3
72 changed files with 3363 additions and 2061 deletions
|
|
@ -1,11 +1,52 @@
|
|||
/* Parser accelerator module */
|
||||
|
||||
#include <stdio.h>
|
||||
/* The parser as originally conceived had disappointing performance.
|
||||
This module does some precomputation that speeds up the selection
|
||||
of a DFA based upon a token, turning a search through an array
|
||||
into a simple indexing operation. The parser now cannot work
|
||||
without the accelerators installed. Note that the accelerators
|
||||
are installed dynamically when the parser is initialized, they
|
||||
are not part of the static data structure written on graminit.[ch]
|
||||
by the parser generator. */
|
||||
|
||||
#include "PROTO.h"
|
||||
#include "pgenheaders.h"
|
||||
#include "grammar.h"
|
||||
#include "token.h"
|
||||
#include "malloc.h"
|
||||
#include "parser.h"
|
||||
|
||||
/* Forward references */
|
||||
static void fixdfa PROTO((grammar *, dfa *));
|
||||
static void fixstate PROTO((grammar *, dfa *, state *));
|
||||
|
||||
void
|
||||
addaccelerators(g)
|
||||
grammar *g;
|
||||
{
|
||||
dfa *d;
|
||||
int i;
|
||||
#ifdef DEBUG
|
||||
printf("Adding parser accellerators ...\n");
|
||||
#endif
|
||||
d = g->g_dfa;
|
||||
for (i = g->g_ndfas; --i >= 0; d++)
|
||||
fixdfa(g, d);
|
||||
g->g_accel = 1;
|
||||
#ifdef DEBUG
|
||||
printf("Done.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
fixdfa(g, d)
|
||||
grammar *g;
|
||||
dfa *d;
|
||||
{
|
||||
state *s;
|
||||
int j;
|
||||
s = d->d_state;
|
||||
for (j = 0; j < d->d_nstates; j++, s++)
|
||||
fixstate(g, d, s);
|
||||
}
|
||||
|
||||
static void
|
||||
fixstate(g, d, s)
|
||||
|
|
@ -69,33 +110,3 @@ fixstate(g, d, s)
|
|||
}
|
||||
DEL(accel);
|
||||
}
|
||||
|
||||
static void
|
||||
fixdfa(g, d)
|
||||
grammar *g;
|
||||
dfa *d;
|
||||
{
|
||||
state *s;
|
||||
int j;
|
||||
s = d->d_state;
|
||||
for (j = 0; j < d->d_nstates; j++, s++)
|
||||
fixstate(g, d, s);
|
||||
}
|
||||
|
||||
void
|
||||
addaccelerators(g)
|
||||
grammar *g;
|
||||
{
|
||||
dfa *d;
|
||||
int i;
|
||||
#ifdef DEBUG
|
||||
printf("Adding parser accellerators ...\n");
|
||||
#endif
|
||||
d = g->g_dfa;
|
||||
for (i = g->g_ndfas; --i >= 0; d++)
|
||||
fixdfa(g, d);
|
||||
g->g_accel = 1;
|
||||
#ifdef DEBUG
|
||||
printf("Done.\n");
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
/* Bitset primitives */
|
||||
/* Bitset primitives used by the parser generator */
|
||||
|
||||
#include "PROTO.h"
|
||||
#include "malloc.h"
|
||||
#include "pgenheaders.h"
|
||||
#include "bitset.h"
|
||||
|
||||
bitset
|
||||
|
|
|
|||
|
|
@ -1,14 +1,29 @@
|
|||
/* Computation of FIRST stets */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "PROTO.h"
|
||||
#include "malloc.h"
|
||||
#include "pgenheaders.h"
|
||||
#include "grammar.h"
|
||||
#include "token.h"
|
||||
|
||||
extern int debugging;
|
||||
|
||||
/* Forward */
|
||||
static void calcfirstset PROTO((grammar *, dfa *));
|
||||
|
||||
void
|
||||
addfirstsets(g)
|
||||
grammar *g;
|
||||
{
|
||||
int i;
|
||||
dfa *d;
|
||||
|
||||
printf("Adding FIRST sets ...\n");
|
||||
for (i = 0; i < g->g_ndfas; i++) {
|
||||
d = &g->g_dfa[i];
|
||||
if (d->d_first == NULL)
|
||||
calcfirstset(g, d);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
calcfirstset(g, d)
|
||||
grammar *g;
|
||||
|
|
@ -92,18 +107,3 @@ calcfirstset(g, d)
|
|||
printf(" }\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
addfirstsets(g)
|
||||
grammar *g;
|
||||
{
|
||||
int i;
|
||||
dfa *d;
|
||||
|
||||
printf("Adding FIRST sets ...\n");
|
||||
for (i = 0; i < g->g_ndfas; i++) {
|
||||
d = &g->g_dfa[i];
|
||||
if (d->d_first == NULL)
|
||||
calcfirstset(g, d);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
/* Grammar implementation */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "pgenheaders.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "PROTO.h"
|
||||
#include "malloc.h"
|
||||
#include "assert.h"
|
||||
#include "token.h"
|
||||
#include "grammar.h"
|
||||
|
|
@ -127,6 +126,21 @@ findlabel(ll, type, str)
|
|||
abort();
|
||||
}
|
||||
|
||||
/* Forward */
|
||||
static void translabel PROTO((grammar *, label *));
|
||||
|
||||
void
|
||||
translatelabels(g)
|
||||
grammar *g;
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("Translating labels ...\n");
|
||||
/* Don't translate EMPTY */
|
||||
for (i = EMPTY+1; i < g->g_ll.ll_nlabels; i++)
|
||||
translabel(g, &g->g_ll.ll_label[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
translabel(g, lb)
|
||||
grammar *g;
|
||||
|
|
@ -193,15 +207,3 @@ translabel(g, lb)
|
|||
else
|
||||
printf("Can't translate label '%s'\n", labelrepr(lb));
|
||||
}
|
||||
|
||||
void
|
||||
translatelabels(g)
|
||||
grammar *g;
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("Translating labels ...\n");
|
||||
/* Don't translate EMPTY */
|
||||
for (i = EMPTY+1; i < g->g_ll.ll_nlabels; i++)
|
||||
translabel(g, &g->g_ll.ll_label[i]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
/* Grammar subroutines needed by parser */
|
||||
|
||||
#include "PROTO.h"
|
||||
#define NULL 0
|
||||
#include "pgenheaders.h"
|
||||
#include "assert.h"
|
||||
#include "grammar.h"
|
||||
#include "token.h"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#ifdef MSDOS
|
||||
|
||||
/* This might work for MS-DOS: */
|
||||
/* This might work for MS-DOS (untested though): */
|
||||
|
||||
void
|
||||
initintr()
|
||||
|
|
@ -37,7 +37,7 @@ initintr()
|
|||
int
|
||||
intrcheck()
|
||||
{
|
||||
/* Static to make it faster(?) only */
|
||||
/* Static to make it faster only */
|
||||
static EventRecord e;
|
||||
|
||||
/* XXX This fails if the user first types ahead and then
|
||||
|
|
@ -59,7 +59,7 @@ intrcheck()
|
|||
|
||||
#ifndef OK
|
||||
|
||||
/* Default version -- should work for Unix and Standard C */
|
||||
/* Default version -- for real operating systems and for Standard C */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,31 @@
|
|||
/* List a node on a file */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "PROTO.h"
|
||||
#include "pgenheaders.h"
|
||||
#include "token.h"
|
||||
#include "node.h"
|
||||
|
||||
/* Forward */
|
||||
static void list1node PROTO((FILE *, node *));
|
||||
|
||||
void
|
||||
listtree(n)
|
||||
node *n;
|
||||
{
|
||||
listnode(stdout, n);
|
||||
}
|
||||
|
||||
static int level, atbol;
|
||||
|
||||
void
|
||||
listnode(fp, n)
|
||||
FILE *fp;
|
||||
node *n;
|
||||
{
|
||||
level = 0;
|
||||
atbol = 1;
|
||||
list1node(fp, n);
|
||||
}
|
||||
|
||||
static void
|
||||
list1node(fp, n)
|
||||
FILE *fp;
|
||||
|
|
@ -49,20 +67,3 @@ list1node(fp, n)
|
|||
else
|
||||
fprintf(fp, "? ");
|
||||
}
|
||||
|
||||
void
|
||||
listnode(fp, n)
|
||||
FILE *fp;
|
||||
node *n;
|
||||
{
|
||||
level = 0;
|
||||
atbol = 1;
|
||||
list1node(fp, n);
|
||||
}
|
||||
|
||||
void
|
||||
listtree(n)
|
||||
node *n;
|
||||
{
|
||||
listnode(stdout, n);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "PROTO.h"
|
||||
#include "pgenheaders.h"
|
||||
#include "metagrammar.h"
|
||||
#include "grammar.h"
|
||||
#include "pgen.h"
|
||||
static arc arcs_0_0[3] = {
|
||||
{2, 0},
|
||||
{3, 0},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
/* Parse tree node implementation */
|
||||
|
||||
#include "PROTO.h"
|
||||
#include "malloc.h"
|
||||
#include "pgenheaders.h"
|
||||
#include "node.h"
|
||||
|
||||
node *
|
||||
newnode(type)
|
||||
newtree(type)
|
||||
int type;
|
||||
{
|
||||
node *n = NEW(node, 1);
|
||||
|
|
@ -13,6 +12,7 @@ newnode(type)
|
|||
return NULL;
|
||||
n->n_type = type;
|
||||
n->n_str = NULL;
|
||||
n->n_lineno = 0;
|
||||
n->n_nchildren = 0;
|
||||
n->n_child = NULL;
|
||||
return n;
|
||||
|
|
@ -22,10 +22,11 @@ newnode(type)
|
|||
#define XXXROUNDUP(n) ((n) == 1 ? 1 : ((n) + XXX - 1) / XXX * XXX)
|
||||
|
||||
node *
|
||||
addchild(n1, type, str)
|
||||
addchild(n1, type, str, lineno)
|
||||
register node *n1;
|
||||
int type;
|
||||
char *str;
|
||||
int lineno;
|
||||
{
|
||||
register int nch = n1->n_nchildren;
|
||||
register int nch1 = nch+1;
|
||||
|
|
@ -41,11 +42,26 @@ addchild(n1, type, str)
|
|||
n = &n1->n_child[n1->n_nchildren++];
|
||||
n->n_type = type;
|
||||
n->n_str = str;
|
||||
n->n_lineno = lineno;
|
||||
n->n_nchildren = 0;
|
||||
n->n_child = NULL;
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Forward */
|
||||
static void freechildren PROTO((node *));
|
||||
|
||||
|
||||
void
|
||||
freetree(n)
|
||||
node *n;
|
||||
{
|
||||
if (n != NULL) {
|
||||
freechildren(n);
|
||||
DEL(n);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
freechildren(n)
|
||||
node *n;
|
||||
|
|
@ -58,13 +74,3 @@ freechildren(n)
|
|||
if (STR(n) != NULL)
|
||||
DEL(STR(n));
|
||||
}
|
||||
|
||||
void
|
||||
freenode(n)
|
||||
node *n;
|
||||
{
|
||||
if (n != NULL) {
|
||||
freechildren(n);
|
||||
DEL(n);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,20 +4,17 @@
|
|||
|
||||
/* XXX To do: error recovery */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "pgenheaders.h"
|
||||
#include "assert.h"
|
||||
|
||||
#include "PROTO.h"
|
||||
#include "malloc.h"
|
||||
#include "token.h"
|
||||
#include "grammar.h"
|
||||
#include "node.h"
|
||||
#include "parser.h"
|
||||
#include "errcode.h"
|
||||
|
||||
extern int debugging;
|
||||
|
||||
#ifdef DEBUG
|
||||
extern int debugging;
|
||||
#define D(x) if (!debugging); else x
|
||||
#else
|
||||
#define D(x)
|
||||
|
|
@ -94,7 +91,7 @@ newparser(g, start)
|
|||
if (ps == NULL)
|
||||
return NULL;
|
||||
ps->p_grammar = g;
|
||||
ps->p_tree = newnode(start);
|
||||
ps->p_tree = newtree(start);
|
||||
if (ps->p_tree == NULL) {
|
||||
DEL(ps);
|
||||
return NULL;
|
||||
|
|
@ -110,24 +107,25 @@ delparser(ps)
|
|||
{
|
||||
/* NB If you want to save the parse tree,
|
||||
you must set p_tree to NULL before calling delparser! */
|
||||
freenode(ps->p_tree);
|
||||
freetree(ps->p_tree);
|
||||
DEL(ps);
|
||||
}
|
||||
|
||||
|
||||
/* PARSER STACK OPERATIONS */
|
||||
|
||||
static int shift PROTO((stack *, int, char *, int));
|
||||
static int shift PROTO((stack *, int, char *, int, int));
|
||||
|
||||
static int
|
||||
shift(s, type, str, newstate)
|
||||
shift(s, type, str, newstate, lineno)
|
||||
register stack *s;
|
||||
int type;
|
||||
char *str;
|
||||
int newstate;
|
||||
int lineno;
|
||||
{
|
||||
assert(!s_empty(s));
|
||||
if (addchild(s->s_top->s_parent, type, str) == NULL) {
|
||||
if (addchild(s->s_top->s_parent, type, str, lineno) == NULL) {
|
||||
fprintf(stderr, "shift: no mem in addchild\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -135,19 +133,20 @@ shift(s, type, str, newstate)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int push PROTO((stack *, int, dfa *, int));
|
||||
static int push PROTO((stack *, int, dfa *, int, int));
|
||||
|
||||
static int
|
||||
push(s, type, d, newstate)
|
||||
push(s, type, d, newstate, lineno)
|
||||
register stack *s;
|
||||
int type;
|
||||
dfa *d;
|
||||
int newstate;
|
||||
int lineno;
|
||||
{
|
||||
register node *n;
|
||||
n = s->s_top->s_parent;
|
||||
assert(!s_empty(s));
|
||||
if (addchild(n, type, (char *)NULL) == NULL) {
|
||||
if (addchild(n, type, (char *)NULL, lineno) == NULL) {
|
||||
fprintf(stderr, "push: no mem in addchild\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -198,10 +197,11 @@ classify(g, type, str)
|
|||
}
|
||||
|
||||
int
|
||||
addtoken(ps, type, str)
|
||||
addtoken(ps, type, str, lineno)
|
||||
register parser_state *ps;
|
||||
register int type;
|
||||
char *str;
|
||||
int lineno;
|
||||
{
|
||||
register int ilabel;
|
||||
|
||||
|
|
@ -230,7 +230,8 @@ addtoken(ps, type, str)
|
|||
int nt = (x >> 8) + NT_OFFSET;
|
||||
int arrow = x & ((1<<7)-1);
|
||||
dfa *d1 = finddfa(ps->p_grammar, nt);
|
||||
if (push(&ps->p_stack, nt, d1, arrow) < 0) {
|
||||
if (push(&ps->p_stack, nt, d1,
|
||||
arrow, lineno) < 0) {
|
||||
D(printf(" MemError: push.\n"));
|
||||
return E_NOMEM;
|
||||
}
|
||||
|
|
@ -239,7 +240,8 @@ addtoken(ps, type, str)
|
|||
}
|
||||
|
||||
/* Shift the token */
|
||||
if (shift(&ps->p_stack, type, str, x) < 0) {
|
||||
if (shift(&ps->p_stack, type, str,
|
||||
x, lineno) < 0) {
|
||||
D(printf(" MemError: shift.\n"));
|
||||
return E_NOMEM;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
typedef struct _stackentry {
|
||||
int s_state; /* State in current DFA */
|
||||
dfa *s_dfa; /* Current DFA */
|
||||
node *s_parent; /* Where to add next node */
|
||||
struct _node *s_parent; /* Where to add next node */
|
||||
} stackentry;
|
||||
|
||||
typedef struct _stack {
|
||||
|
|
@ -22,4 +22,5 @@ typedef struct {
|
|||
|
||||
parser_state *newparser PROTO((struct _grammar *g, int start));
|
||||
void delparser PROTO((parser_state *ps));
|
||||
int addtoken PROTO((parser_state *ps, int type, char *str));
|
||||
int addtoken PROTO((parser_state *ps, int type, char *str, int lineno));
|
||||
void addaccelerators PROTO((grammar *g));
|
||||
|
|
|
|||
|
|
@ -1,16 +1,82 @@
|
|||
/* Parser-tokenizer link implementation */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "PROTO.h"
|
||||
#include "malloc.h"
|
||||
#include "pgenheaders.h"
|
||||
#include "tokenizer.h"
|
||||
#include "node.h"
|
||||
#include "grammar.h"
|
||||
#include "parser.h"
|
||||
#include "parsetok.h"
|
||||
#include "errcode.h"
|
||||
|
||||
extern int debugging;
|
||||
|
||||
/* Forward */
|
||||
static int parsetok PROTO((struct tok_state *, grammar *, int, node **));
|
||||
|
||||
|
||||
/* Parse input coming from a string. Return error code, print some errors. */
|
||||
|
||||
int
|
||||
parsestring(s, g, start, n_ret)
|
||||
char *s;
|
||||
grammar *g;
|
||||
int start;
|
||||
node **n_ret;
|
||||
{
|
||||
struct tok_state *tok = tok_setups(s);
|
||||
int ret;
|
||||
|
||||
if (tok == NULL) {
|
||||
fprintf(stderr, "no mem for tok_setups\n");
|
||||
return E_NOMEM;
|
||||
}
|
||||
ret = parsetok(tok, g, start, n_ret);
|
||||
if (ret == E_TOKEN || ret == E_SYNTAX) {
|
||||
fprintf(stderr, "String parsing error at line %d\n",
|
||||
tok->lineno);
|
||||
}
|
||||
tok_free(tok);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Parse input coming from a file. Return error code, print some errors. */
|
||||
|
||||
int
|
||||
parsefile(fp, filename, g, start, ps1, ps2, n_ret)
|
||||
FILE *fp;
|
||||
char *filename;
|
||||
grammar *g;
|
||||
int start;
|
||||
char *ps1, *ps2;
|
||||
node **n_ret;
|
||||
{
|
||||
struct tok_state *tok = tok_setupf(fp, ps1, ps2);
|
||||
int ret;
|
||||
|
||||
if (tok == NULL) {
|
||||
fprintf(stderr, "no mem for tok_setupf\n");
|
||||
return E_NOMEM;
|
||||
}
|
||||
ret = parsetok(tok, g, start, n_ret);
|
||||
if (ret == E_TOKEN || ret == E_SYNTAX) {
|
||||
char *p;
|
||||
fprintf(stderr, "Parsing error: file %s, line %d:\n",
|
||||
filename, tok->lineno);
|
||||
*tok->inp = '\0';
|
||||
if (tok->inp > tok->buf && tok->inp[-1] == '\n')
|
||||
tok->inp[-1] = '\0';
|
||||
fprintf(stderr, "%s\n", tok->buf);
|
||||
for (p = tok->buf; p < tok->cur; p++) {
|
||||
if (*p == '\t')
|
||||
putc('\t', stderr);
|
||||
else
|
||||
putc(' ', stderr);
|
||||
}
|
||||
fprintf(stderr, "^\n");
|
||||
}
|
||||
tok_free(tok);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Parse input coming from the given tokenizer structure.
|
||||
|
|
@ -51,7 +117,7 @@ parsetok(tok, g, start, n_ret)
|
|||
}
|
||||
strncpy(str, a, len);
|
||||
str[len] = '\0';
|
||||
ret = addtoken(ps, (int)type, str);
|
||||
ret = addtoken(ps, (int)type, str, tok->lineno);
|
||||
if (ret != E_OK) {
|
||||
if (ret == E_DONE) {
|
||||
*n_ret = ps->p_tree;
|
||||
|
|
@ -66,67 +132,3 @@ parsetok(tok, g, start, n_ret)
|
|||
delparser(ps);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Parse input coming from a string. Return error code. */
|
||||
|
||||
int
|
||||
parsestring(s, g, start, n_ret)
|
||||
char *s;
|
||||
grammar *g;
|
||||
int start;
|
||||
node **n_ret;
|
||||
{
|
||||
struct tok_state *tok = tok_setups(s);
|
||||
int ret;
|
||||
|
||||
if (tok == NULL) {
|
||||
fprintf(stderr, "no mem for tok_setups\n");
|
||||
return E_NOMEM;
|
||||
}
|
||||
ret = parsetok(tok, g, start, n_ret);
|
||||
if (ret == E_TOKEN || ret == E_SYNTAX) {
|
||||
fprintf(stderr, "String parsing error at line %d\n",
|
||||
tok->lineno);
|
||||
}
|
||||
tok_free(tok);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Parse input coming from a file. Return error code. */
|
||||
|
||||
int
|
||||
parsefile(fp, g, start, ps1, ps2, n_ret)
|
||||
FILE *fp;
|
||||
grammar *g;
|
||||
int start;
|
||||
char *ps1, *ps2;
|
||||
node **n_ret;
|
||||
{
|
||||
struct tok_state *tok = tok_setupf(fp, ps1, ps2);
|
||||
int ret;
|
||||
|
||||
if (tok == NULL) {
|
||||
fprintf(stderr, "no mem for tok_setupf\n");
|
||||
return E_NOMEM;
|
||||
}
|
||||
ret = parsetok(tok, g, start, n_ret);
|
||||
if (ret == E_TOKEN || ret == E_SYNTAX) {
|
||||
char *p;
|
||||
fprintf(stderr, "Parsing error at line %d:\n", tok->lineno);
|
||||
*tok->inp = '\0';
|
||||
if (tok->inp > tok->buf && tok->inp[-1] == '\n')
|
||||
tok->inp[-1] = '\0';
|
||||
fprintf(stderr, "%s\n", tok->buf);
|
||||
for (p = tok->buf; p < tok->cur; p++) {
|
||||
if (*p == '\t')
|
||||
putc('\t', stderr);
|
||||
else
|
||||
putc(' ', stderr);
|
||||
}
|
||||
fprintf(stderr, "^\n");
|
||||
}
|
||||
tok_free(tok);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
/* Parser generator */
|
||||
/* XXX This file is not yet fully PROTOized */
|
||||
|
||||
/* For a description, see the comments at end of this file */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "pgenheaders.h"
|
||||
#include "assert.h"
|
||||
|
||||
#include "PROTO.h"
|
||||
#include "malloc.h"
|
||||
#include "token.h"
|
||||
#include "node.h"
|
||||
#include "grammar.h"
|
||||
|
|
|
|||
|
|
@ -3,4 +3,4 @@
|
|||
extern grammar gram;
|
||||
|
||||
extern grammar *meta_grammar PROTO((void));
|
||||
extern grammar *pgen PROTO((node *));
|
||||
extern grammar *pgen PROTO((struct _node *));
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
/* Parser generator main program */
|
||||
|
||||
#include <stdio.h>
|
||||
/* This expects a filename containing the grammar as argv[1] (UNIX)
|
||||
or asks the console for such a file name (THINK C).
|
||||
It writes its output on two files in the current directory:
|
||||
- "graminit.c" gets the grammar as a bunch of initialized data
|
||||
- "graminit.h" gets the grammar's non-terminals as #defines.
|
||||
Error messages and status info during the generation process are
|
||||
written to stdout, or sometimes to stderr. */
|
||||
|
||||
#include "PROTO.h"
|
||||
#include "pgenheaders.h"
|
||||
#include "grammar.h"
|
||||
#include "node.h"
|
||||
#include "parsetok.h"
|
||||
|
|
@ -10,54 +16,14 @@
|
|||
|
||||
int debugging;
|
||||
|
||||
/* Forward */
|
||||
grammar *getgrammar PROTO((char *filename));
|
||||
#ifdef THINK_C
|
||||
char *
|
||||
askfile()
|
||||
{
|
||||
char buf[256];
|
||||
static char name[256];
|
||||
printf("Input file name: ");
|
||||
if (fgets(buf, sizeof buf, stdin) == NULL) {
|
||||
printf("EOF\n");
|
||||
exit(1);
|
||||
}
|
||||
if (sscanf(buf, " %s ", name) != 1) {
|
||||
printf("No file\n");
|
||||
exit(1);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
int main PROTO((int, char **));
|
||||
char *askfile PROTO((void));
|
||||
#endif
|
||||
|
||||
grammar *
|
||||
getgrammar(filename)
|
||||
char *filename;
|
||||
{
|
||||
FILE *fp;
|
||||
node *n;
|
||||
grammar *g0, *g;
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
if (fp == NULL) {
|
||||
perror(filename);
|
||||
exit(1);
|
||||
}
|
||||
g0 = meta_grammar();
|
||||
n = NULL;
|
||||
parsefile(fp, g0, g0->g_start, (char *)NULL, (char *)NULL, &n);
|
||||
fclose(fp);
|
||||
if (n == NULL) {
|
||||
fprintf(stderr, "Parsing error.\n");
|
||||
exit(1);
|
||||
}
|
||||
g = pgen(n);
|
||||
if (g == NULL) {
|
||||
printf("Bad grammar.\n");
|
||||
exit(1);
|
||||
}
|
||||
return g;
|
||||
}
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
|
|
@ -96,6 +62,55 @@ main(argc, argv)
|
|||
exit(0);
|
||||
}
|
||||
|
||||
grammar *
|
||||
getgrammar(filename)
|
||||
char *filename;
|
||||
{
|
||||
FILE *fp;
|
||||
node *n;
|
||||
grammar *g0, *g;
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
if (fp == NULL) {
|
||||
perror(filename);
|
||||
exit(1);
|
||||
}
|
||||
g0 = meta_grammar();
|
||||
n = NULL;
|
||||
parsefile(fp, filename, g0, g0->g_start, (char *)NULL, (char *)NULL, &n);
|
||||
fclose(fp);
|
||||
if (n == NULL) {
|
||||
fprintf(stderr, "Parsing error.\n");
|
||||
exit(1);
|
||||
}
|
||||
g = pgen(n);
|
||||
if (g == NULL) {
|
||||
printf("Bad grammar.\n");
|
||||
exit(1);
|
||||
}
|
||||
return g;
|
||||
}
|
||||
|
||||
#ifdef THINK_C
|
||||
char *
|
||||
askfile()
|
||||
{
|
||||
char buf[256];
|
||||
static char name[256];
|
||||
printf("Input file name: ");
|
||||
if (fgets(buf, sizeof buf, stdin) == NULL) {
|
||||
printf("EOF\n");
|
||||
exit(1);
|
||||
}
|
||||
/* XXX The (unsigned char *) case is needed by THINK C */
|
||||
if (sscanf((unsigned char *)buf, " %s ", name) != 1) {
|
||||
printf("No file\n");
|
||||
exit(1);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
fatal(msg)
|
||||
char *msg;
|
||||
|
|
@ -104,8 +119,6 @@ fatal(msg)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
/* TO DO:
|
||||
|
||||
- improve user interface
|
||||
- check for duplicate definitions of names (instead of fatal err)
|
||||
/* XXX TO DO:
|
||||
- check for duplicate definitions of names (instead of fatal err)
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,10 +1,44 @@
|
|||
/* Print a bunch of C initializers that represent a grammar */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "PROTO.h"
|
||||
#include "pgenheaders.h"
|
||||
#include "grammar.h"
|
||||
|
||||
/* Forward */
|
||||
static void printarcs PROTO((int, dfa *, FILE *));
|
||||
static void printstates PROTO((grammar *, FILE *));
|
||||
static void printdfas PROTO((grammar *, FILE *));
|
||||
static void printlabels PROTO((grammar *, FILE *));
|
||||
|
||||
void
|
||||
printgrammar(g, fp)
|
||||
grammar *g;
|
||||
FILE *fp;
|
||||
{
|
||||
fprintf(fp, "#include \"pgenheaders.h\"\n");
|
||||
fprintf(fp, "#include \"grammar.h\"\n");
|
||||
printdfas(g, fp);
|
||||
printlabels(g, fp);
|
||||
fprintf(fp, "grammar gram = {\n");
|
||||
fprintf(fp, "\t%d,\n", g->g_ndfas);
|
||||
fprintf(fp, "\tdfas,\n");
|
||||
fprintf(fp, "\t{%d, labels},\n", g->g_ll.ll_nlabels);
|
||||
fprintf(fp, "\t%d\n", g->g_start);
|
||||
fprintf(fp, "};\n");
|
||||
}
|
||||
|
||||
void
|
||||
printnonterminals(g, fp)
|
||||
grammar *g;
|
||||
FILE *fp;
|
||||
{
|
||||
dfa *d;
|
||||
int i;
|
||||
|
||||
d = g->g_dfa;
|
||||
for (i = g->g_ndfas; --i >= 0; d++)
|
||||
fprintf(fp, "#define %s %d\n", d->d_name, d->d_type);
|
||||
}
|
||||
|
||||
static void
|
||||
printarcs(i, d, fp)
|
||||
int i;
|
||||
|
|
@ -89,33 +123,3 @@ printlabels(g, fp)
|
|||
}
|
||||
fprintf(fp, "};\n");
|
||||
}
|
||||
|
||||
void
|
||||
printgrammar(g, fp)
|
||||
grammar *g;
|
||||
FILE *fp;
|
||||
{
|
||||
fprintf(fp, "#include \"PROTO.h\"\n");
|
||||
fprintf(fp, "#include \"grammar.h\"\n");
|
||||
printdfas(g, fp);
|
||||
printlabels(g, fp);
|
||||
fprintf(fp, "grammar gram = {\n");
|
||||
fprintf(fp, "\t%d,\n", g->g_ndfas);
|
||||
fprintf(fp, "\tdfas,\n");
|
||||
fprintf(fp, "\t{%d, labels},\n", g->g_ll.ll_nlabels);
|
||||
fprintf(fp, "\t%d\n", g->g_start);
|
||||
fprintf(fp, "};\n");
|
||||
}
|
||||
|
||||
void
|
||||
printnonterminals(g, fp)
|
||||
grammar *g;
|
||||
FILE *fp;
|
||||
{
|
||||
dfa *d;
|
||||
int i;
|
||||
|
||||
d = g->g_dfa;
|
||||
for (i = g->g_ndfas; --i >= 0; d++)
|
||||
fprintf(fp, "#define %s %d\n", d->d_name, d->d_type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@
|
|||
|
||||
/* XXX This is rather old, should be restructured perhaps */
|
||||
/* XXX Need a better interface to report errors than writing to stderr */
|
||||
/* XXX Should use editor resource to fetch true tab size on Macintosh */
|
||||
|
||||
#include "pgenheaders.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "string.h"
|
||||
|
||||
#include "PROTO.h"
|
||||
#include "malloc.h"
|
||||
#include "fgetsintr.h"
|
||||
#include "tokenizer.h"
|
||||
#include "errcode.h"
|
||||
|
||||
|
|
@ -20,6 +21,11 @@
|
|||
#define TABSIZE 8
|
||||
#endif
|
||||
|
||||
/* Forward */
|
||||
static struct tok_state *tok_new PROTO((void));
|
||||
static int tok_nextc PROTO((struct tok_state *tok));
|
||||
static void tok_backup PROTO((struct tok_state *tok, int c));
|
||||
|
||||
/* Token names */
|
||||
|
||||
char *tok_name[] = {
|
||||
|
|
@ -352,7 +358,9 @@ tok_get(tok, p_start, p_end)
|
|||
This is also recognized by vi, when it occurs near the
|
||||
beginning or end of the file. (Will vi never die...?) */
|
||||
int x;
|
||||
if (sscanf(tok->cur, " vi:set tabsize=%d:", &x) == 1 &&
|
||||
/* XXX The case to (unsigned char *) is needed by THINK C */
|
||||
if (sscanf((unsigned char *)tok->cur,
|
||||
" vi:set tabsize=%d:", &x) == 1 &&
|
||||
x >= 1 && x <= 40) {
|
||||
fprintf(stderr, "# vi:set tabsize=%d:\n", x);
|
||||
tok->tabsize = x;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue