grammar.c revision bb3649e2ba386adc16fadc2e0d1f2606c047e6aa
1/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5                        All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
16
17While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
29
30******************************************************************/
31
32/* Grammar implementation */
33
34#include "pgenheaders.h"
35
36#include <ctype.h>
37
38#include "assert.h"
39#include "token.h"
40#include "grammar.h"
41
42extern int Py_DebugFlag;
43
44grammar *
45newgrammar(start)
46	int start;
47{
48	grammar *g;
49
50	g = PyMem_NEW(grammar, 1);
51	if (g == NULL)
52		Py_FatalError("no mem for new grammar");
53	g->g_ndfas = 0;
54	g->g_dfa = NULL;
55	g->g_start = start;
56	g->g_ll.ll_nlabels = 0;
57	g->g_ll.ll_label = NULL;
58	g->g_accel = 0;
59	return g;
60}
61
62dfa *
63adddfa(g, type, name)
64	grammar *g;
65	int type;
66	char *name;
67{
68	dfa *d;
69
70	PyMem_RESIZE(g->g_dfa, dfa, g->g_ndfas + 1);
71	if (g->g_dfa == NULL)
72		Py_FatalError("no mem to resize dfa in adddfa");
73	d = &g->g_dfa[g->g_ndfas++];
74	d->d_type = type;
75	d->d_name = name;
76	d->d_nstates = 0;
77	d->d_state = NULL;
78	d->d_initial = -1;
79	d->d_first = NULL;
80	return d; /* Only use while fresh! */
81}
82
83int
84addstate(d)
85	dfa *d;
86{
87	state *s;
88
89	PyMem_RESIZE(d->d_state, state, d->d_nstates + 1);
90	if (d->d_state == NULL)
91		Py_FatalError("no mem to resize state in addstate");
92	s = &d->d_state[d->d_nstates++];
93	s->s_narcs = 0;
94	s->s_arc = NULL;
95	s->s_lower = 0;
96	s->s_upper = 0;
97	s->s_accel = NULL;
98	s->s_accept = 0;
99	return s - d->d_state;
100}
101
102void
103addarc(d, from, to, lbl)
104	dfa *d;
105	int lbl;
106{
107	state *s;
108	arc *a;
109
110	assert(0 <= from && from < d->d_nstates);
111	assert(0 <= to && to < d->d_nstates);
112
113	s = &d->d_state[from];
114	PyMem_RESIZE(s->s_arc, arc, s->s_narcs + 1);
115	if (s->s_arc == NULL)
116		Py_FatalError("no mem to resize arc list in addarc");
117	a = &s->s_arc[s->s_narcs++];
118	a->a_lbl = lbl;
119	a->a_arrow = to;
120}
121
122int
123addlabel(ll, type, str)
124	labellist *ll;
125	int type;
126	char *str;
127{
128	int i;
129	label *lb;
130
131	for (i = 0; i < ll->ll_nlabels; i++) {
132		if (ll->ll_label[i].lb_type == type &&
133			strcmp(ll->ll_label[i].lb_str, str) == 0)
134			return i;
135	}
136	PyMem_RESIZE(ll->ll_label, label, ll->ll_nlabels + 1);
137	if (ll->ll_label == NULL)
138		Py_FatalError("no mem to resize labellist in addlabel");
139	lb = &ll->ll_label[ll->ll_nlabels++];
140	lb->lb_type = type;
141	lb->lb_str = str; /* XXX strdup(str) ??? */
142	return lb - ll->ll_label;
143}
144
145/* Same, but rather dies than adds */
146
147int
148findlabel(ll, type, str)
149	labellist *ll;
150	int type;
151	char *str;
152{
153	int i;
154
155	for (i = 0; i < ll->ll_nlabels; i++) {
156		if (ll->ll_label[i].lb_type == type /*&&
157			strcmp(ll->ll_label[i].lb_str, str) == 0*/)
158			return i;
159	}
160	fprintf(stderr, "Label %d/'%s' not found\n", type, str);
161	Py_FatalError("grammar.c:findlabel()");
162	return 0; /* Make gcc -Wall happy */
163}
164
165/* Forward */
166static void translabel Py_PROTO((grammar *, label *));
167
168void
169translatelabels(g)
170	grammar *g;
171{
172	int i;
173
174#ifdef Py_DEBUG
175	printf("Translating labels ...\n");
176#endif
177	/* Don't translate EMPTY */
178	for (i = EMPTY+1; i < g->g_ll.ll_nlabels; i++)
179		translabel(g, &g->g_ll.ll_label[i]);
180}
181
182static void
183translabel(g, lb)
184	grammar *g;
185	label *lb;
186{
187	int i;
188
189	if (Py_DebugFlag)
190		printf("Translating label %s ...\n", PyGrammar_LabelRepr(lb));
191
192	if (lb->lb_type == NAME) {
193		for (i = 0; i < g->g_ndfas; i++) {
194			if (strcmp(lb->lb_str, g->g_dfa[i].d_name) == 0) {
195				if (Py_DebugFlag)
196					printf(
197					    "Label %s is non-terminal %d.\n",
198					    lb->lb_str,
199					    g->g_dfa[i].d_type);
200				lb->lb_type = g->g_dfa[i].d_type;
201				lb->lb_str = NULL;
202				return;
203			}
204		}
205		for (i = 0; i < (int)N_TOKENS; i++) {
206			if (strcmp(lb->lb_str, _PyParser_TokenNames[i]) == 0) {
207				if (Py_DebugFlag)
208					printf("Label %s is terminal %d.\n",
209						lb->lb_str, i);
210				lb->lb_type = i;
211				lb->lb_str = NULL;
212				return;
213			}
214		}
215		printf("Can't translate NAME label '%s'\n", lb->lb_str);
216		return;
217	}
218
219	if (lb->lb_type == STRING) {
220		if (isalpha((int)(lb->lb_str[1])) || lb->lb_str[1] == '_') {
221			char *p;
222			if (Py_DebugFlag)
223				printf("Label %s is a keyword\n", lb->lb_str);
224			lb->lb_type = NAME;
225			lb->lb_str++;
226			p = strchr(lb->lb_str, '\'');
227			if (p)
228				*p = '\0';
229		}
230		else if (lb->lb_str[2] == lb->lb_str[0]) {
231			int type = (int) PyToken_OneChar(lb->lb_str[1]);
232			if (type != OP) {
233				lb->lb_type = type;
234				lb->lb_str = NULL;
235			}
236			else
237				printf("Unknown OP label %s\n",
238					lb->lb_str);
239		}
240		else if (lb->lb_str[2] && lb->lb_str[3] == lb->lb_str[0]) {
241			int type = (int) PyToken_TwoChars(lb->lb_str[1],
242						   lb->lb_str[2]);
243			if (type != OP) {
244				lb->lb_type = type;
245				lb->lb_str = NULL;
246			}
247			else
248				printf("Unknown OP label %s\n",
249					lb->lb_str);
250		}
251		else
252			printf("Can't translate STRING label %s\n",
253				lb->lb_str);
254	}
255	else
256		printf("Can't translate label '%s'\n",
257		       PyGrammar_LabelRepr(lb));
258}
259