grammar.c revision fd71b9e9d496caa510dec56a9b69966558d6ba5d
1/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5                        All Rights Reserved
6
7Copyright (c) 2000, BeOpen.com.
8Copyright (c) 1995-2000, Corporation for National Research Initiatives.
9Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
10All rights reserved.
11
12See the file "Misc/COPYRIGHT" for information on usage and
13redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14
15******************************************************************/
16
17/* Grammar implementation */
18
19#include "pgenheaders.h"
20
21#include <ctype.h>
22
23#include "assert.h"
24#include "token.h"
25#include "grammar.h"
26
27extern int Py_DebugFlag;
28
29grammar *
30newgrammar(start)
31	int start;
32{
33	grammar *g;
34
35	g = PyMem_NEW(grammar, 1);
36	if (g == NULL)
37		Py_FatalError("no mem for new grammar");
38	g->g_ndfas = 0;
39	g->g_dfa = NULL;
40	g->g_start = start;
41	g->g_ll.ll_nlabels = 0;
42	g->g_ll.ll_label = NULL;
43	g->g_accel = 0;
44	return g;
45}
46
47dfa *
48adddfa(g, type, name)
49	grammar *g;
50	int type;
51	char *name;
52{
53	dfa *d;
54
55	PyMem_RESIZE(g->g_dfa, dfa, g->g_ndfas + 1);
56	if (g->g_dfa == NULL)
57		Py_FatalError("no mem to resize dfa in adddfa");
58	d = &g->g_dfa[g->g_ndfas++];
59	d->d_type = type;
60	d->d_name = name;
61	d->d_nstates = 0;
62	d->d_state = NULL;
63	d->d_initial = -1;
64	d->d_first = NULL;
65	return d; /* Only use while fresh! */
66}
67
68int
69addstate(d)
70	dfa *d;
71{
72	state *s;
73
74	PyMem_RESIZE(d->d_state, state, d->d_nstates + 1);
75	if (d->d_state == NULL)
76		Py_FatalError("no mem to resize state in addstate");
77	s = &d->d_state[d->d_nstates++];
78	s->s_narcs = 0;
79	s->s_arc = NULL;
80	s->s_lower = 0;
81	s->s_upper = 0;
82	s->s_accel = NULL;
83	s->s_accept = 0;
84	return s - d->d_state;
85}
86
87void
88addarc(d, from, to, lbl)
89	dfa *d;
90	int lbl;
91{
92	state *s;
93	arc *a;
94
95	assert(0 <= from && from < d->d_nstates);
96	assert(0 <= to && to < d->d_nstates);
97
98	s = &d->d_state[from];
99	PyMem_RESIZE(s->s_arc, arc, s->s_narcs + 1);
100	if (s->s_arc == NULL)
101		Py_FatalError("no mem to resize arc list in addarc");
102	a = &s->s_arc[s->s_narcs++];
103	a->a_lbl = lbl;
104	a->a_arrow = to;
105}
106
107int
108addlabel(ll, type, str)
109	labellist *ll;
110	int type;
111	char *str;
112{
113	int i;
114	label *lb;
115
116	for (i = 0; i < ll->ll_nlabels; i++) {
117		if (ll->ll_label[i].lb_type == type &&
118			strcmp(ll->ll_label[i].lb_str, str) == 0)
119			return i;
120	}
121	PyMem_RESIZE(ll->ll_label, label, ll->ll_nlabels + 1);
122	if (ll->ll_label == NULL)
123		Py_FatalError("no mem to resize labellist in addlabel");
124	lb = &ll->ll_label[ll->ll_nlabels++];
125	lb->lb_type = type;
126	lb->lb_str = str; /* XXX strdup(str) ??? */
127	return lb - ll->ll_label;
128}
129
130/* Same, but rather dies than adds */
131
132int
133findlabel(ll, type, str)
134	labellist *ll;
135	int type;
136	char *str;
137{
138	int i;
139
140	for (i = 0; i < ll->ll_nlabels; i++) {
141		if (ll->ll_label[i].lb_type == type /*&&
142			strcmp(ll->ll_label[i].lb_str, str) == 0*/)
143			return i;
144	}
145	fprintf(stderr, "Label %d/'%s' not found\n", type, str);
146	Py_FatalError("grammar.c:findlabel()");
147	return 0; /* Make gcc -Wall happy */
148}
149
150/* Forward */
151static void translabel Py_PROTO((grammar *, label *));
152
153void
154translatelabels(g)
155	grammar *g;
156{
157	int i;
158
159#ifdef Py_DEBUG
160	printf("Translating labels ...\n");
161#endif
162	/* Don't translate EMPTY */
163	for (i = EMPTY+1; i < g->g_ll.ll_nlabels; i++)
164		translabel(g, &g->g_ll.ll_label[i]);
165}
166
167static void
168translabel(g, lb)
169	grammar *g;
170	label *lb;
171{
172	int i;
173
174	if (Py_DebugFlag)
175		printf("Translating label %s ...\n", PyGrammar_LabelRepr(lb));
176
177	if (lb->lb_type == NAME) {
178		for (i = 0; i < g->g_ndfas; i++) {
179			if (strcmp(lb->lb_str, g->g_dfa[i].d_name) == 0) {
180				if (Py_DebugFlag)
181					printf(
182					    "Label %s is non-terminal %d.\n",
183					    lb->lb_str,
184					    g->g_dfa[i].d_type);
185				lb->lb_type = g->g_dfa[i].d_type;
186				lb->lb_str = NULL;
187				return;
188			}
189		}
190		for (i = 0; i < (int)N_TOKENS; i++) {
191			if (strcmp(lb->lb_str, _PyParser_TokenNames[i]) == 0) {
192				if (Py_DebugFlag)
193					printf("Label %s is terminal %d.\n",
194						lb->lb_str, i);
195				lb->lb_type = i;
196				lb->lb_str = NULL;
197				return;
198			}
199		}
200		printf("Can't translate NAME label '%s'\n", lb->lb_str);
201		return;
202	}
203
204	if (lb->lb_type == STRING) {
205		if (isalpha((int)(lb->lb_str[1])) || lb->lb_str[1] == '_') {
206			char *p;
207			if (Py_DebugFlag)
208				printf("Label %s is a keyword\n", lb->lb_str);
209			lb->lb_type = NAME;
210			lb->lb_str++;
211			p = strchr(lb->lb_str, '\'');
212			if (p)
213				*p = '\0';
214		}
215		else if (lb->lb_str[2] == lb->lb_str[0]) {
216			int type = (int) PyToken_OneChar(lb->lb_str[1]);
217			if (type != OP) {
218				lb->lb_type = type;
219				lb->lb_str = NULL;
220			}
221			else
222				printf("Unknown OP label %s\n",
223					lb->lb_str);
224		}
225		else if (lb->lb_str[2] && lb->lb_str[3] == lb->lb_str[0]) {
226			int type = (int) PyToken_TwoChars(lb->lb_str[1],
227						   lb->lb_str[2]);
228			if (type != OP) {
229				lb->lb_type = type;
230				lb->lb_str = NULL;
231			}
232			else
233				printf("Unknown OP label %s\n",
234					lb->lb_str);
235		}
236		else
237			printf("Can't translate STRING label %s\n",
238				lb->lb_str);
239	}
240	else
241		printf("Can't translate label '%s'\n",
242		       PyGrammar_LabelRepr(lb));
243}
244