grammar.c 4.64 KB
Newer Older
1

Guido van Rossum's avatar
Guido van Rossum committed
2 3
/* Grammar implementation */

4
#include "Python.h"
Guido van Rossum's avatar
Guido van Rossum committed
5 6
#include "pgenheaders.h"

Guido van Rossum's avatar
Guido van Rossum committed
7 8 9 10 11
#include <ctype.h>

#include "token.h"
#include "grammar.h"

12
extern int Py_DebugFlag;
Guido van Rossum's avatar
Guido van Rossum committed
13 14

grammar *
Thomas Wouters's avatar
Thomas Wouters committed
15
newgrammar(int start)
Guido van Rossum's avatar
Guido van Rossum committed
16 17 18
{
	grammar *g;
	
19
	g = PyMem_NEW(grammar, 1);
Guido van Rossum's avatar
Guido van Rossum committed
20
	if (g == NULL)
21
		Py_FatalError("no mem for new grammar");
Guido van Rossum's avatar
Guido van Rossum committed
22 23 24 25 26
	g->g_ndfas = 0;
	g->g_dfa = NULL;
	g->g_start = start;
	g->g_ll.ll_nlabels = 0;
	g->g_ll.ll_label = NULL;
27
	g->g_accel = 0;
Guido van Rossum's avatar
Guido van Rossum committed
28 29 30 31
	return g;
}

dfa *
Thomas Wouters's avatar
Thomas Wouters committed
32
adddfa(grammar *g, int type, char *name)
Guido van Rossum's avatar
Guido van Rossum committed
33 34 35
{
	dfa *d;
	
36
	PyMem_RESIZE(g->g_dfa, dfa, g->g_ndfas + 1);
Guido van Rossum's avatar
Guido van Rossum committed
37
	if (g->g_dfa == NULL)
38
		Py_FatalError("no mem to resize dfa in adddfa");
Guido van Rossum's avatar
Guido van Rossum committed
39 40 41 42 43 44 45 46 47 48 49
	d = &g->g_dfa[g->g_ndfas++];
	d->d_type = type;
	d->d_name = name;
	d->d_nstates = 0;
	d->d_state = NULL;
	d->d_initial = -1;
	d->d_first = NULL;
	return d; /* Only use while fresh! */
}

int
Thomas Wouters's avatar
Thomas Wouters committed
50
addstate(dfa *d)
Guido van Rossum's avatar
Guido van Rossum committed
51 52 53
{
	state *s;
	
54
	PyMem_RESIZE(d->d_state, state, d->d_nstates + 1);
Guido van Rossum's avatar
Guido van Rossum committed
55
	if (d->d_state == NULL)
56
		Py_FatalError("no mem to resize state in addstate");
Guido van Rossum's avatar
Guido van Rossum committed
57 58 59
	s = &d->d_state[d->d_nstates++];
	s->s_narcs = 0;
	s->s_arc = NULL;
60 61 62 63
	s->s_lower = 0;
	s->s_upper = 0;
	s->s_accel = NULL;
	s->s_accept = 0;
Guido van Rossum's avatar
Guido van Rossum committed
64 65 66 67
	return s - d->d_state;
}

void
Thomas Wouters's avatar
Thomas Wouters committed
68
addarc(dfa *d, int from, int to, int lbl)
Guido van Rossum's avatar
Guido van Rossum committed
69 70 71 72 73 74 75 76
{
	state *s;
	arc *a;
	
	assert(0 <= from && from < d->d_nstates);
	assert(0 <= to && to < d->d_nstates);
	
	s = &d->d_state[from];
77
	PyMem_RESIZE(s->s_arc, arc, s->s_narcs + 1);
Guido van Rossum's avatar
Guido van Rossum committed
78
	if (s->s_arc == NULL)
79
		Py_FatalError("no mem to resize arc list in addarc");
Guido van Rossum's avatar
Guido van Rossum committed
80 81 82 83 84 85
	a = &s->s_arc[s->s_narcs++];
	a->a_lbl = lbl;
	a->a_arrow = to;
}

int
Thomas Wouters's avatar
Thomas Wouters committed
86
addlabel(labellist *ll, int type, char *str)
Guido van Rossum's avatar
Guido van Rossum committed
87 88 89 90 91 92 93 94 95
{
	int i;
	label *lb;
	
	for (i = 0; i < ll->ll_nlabels; i++) {
		if (ll->ll_label[i].lb_type == type &&
			strcmp(ll->ll_label[i].lb_str, str) == 0)
			return i;
	}
96
	PyMem_RESIZE(ll->ll_label, label, ll->ll_nlabels + 1);
Guido van Rossum's avatar
Guido van Rossum committed
97
	if (ll->ll_label == NULL)
98
		Py_FatalError("no mem to resize labellist in addlabel");
Guido van Rossum's avatar
Guido van Rossum committed
99 100 101 102 103 104 105 106 107
	lb = &ll->ll_label[ll->ll_nlabels++];
	lb->lb_type = type;
	lb->lb_str = str; /* XXX strdup(str) ??? */
	return lb - ll->ll_label;
}

/* Same, but rather dies than adds */

int
Thomas Wouters's avatar
Thomas Wouters committed
108
findlabel(labellist *ll, int type, char *str)
Guido van Rossum's avatar
Guido van Rossum committed
109 110 111 112 113 114 115 116 117
{
	int i;
	
	for (i = 0; i < ll->ll_nlabels; i++) {
		if (ll->ll_label[i].lb_type == type /*&&
			strcmp(ll->ll_label[i].lb_str, str) == 0*/)
			return i;
	}
	fprintf(stderr, "Label %d/'%s' not found\n", type, str);
118
	Py_FatalError("grammar.c:findlabel()");
Guido van Rossum's avatar
Guido van Rossum committed
119
	return 0; /* Make gcc -Wall happy */
Guido van Rossum's avatar
Guido van Rossum committed
120 121
}

Guido van Rossum's avatar
Guido van Rossum committed
122
/* Forward */
123
static void translabel(grammar *, label *);
Guido van Rossum's avatar
Guido van Rossum committed
124 125

void
Thomas Wouters's avatar
Thomas Wouters committed
126
translatelabels(grammar *g)
Guido van Rossum's avatar
Guido van Rossum committed
127 128
{
	int i;
129

130
#ifdef Py_DEBUG
Guido van Rossum's avatar
Guido van Rossum committed
131
	printf("Translating labels ...\n");
132
#endif
Guido van Rossum's avatar
Guido van Rossum committed
133 134 135 136 137
	/* Don't translate EMPTY */
	for (i = EMPTY+1; i < g->g_ll.ll_nlabels; i++)
		translabel(g, &g->g_ll.ll_label[i]);
}

Guido van Rossum's avatar
Guido van Rossum committed
138
static void
Thomas Wouters's avatar
Thomas Wouters committed
139
translabel(grammar *g, label *lb)
Guido van Rossum's avatar
Guido van Rossum committed
140 141 142
{
	int i;
	
143 144
	if (Py_DebugFlag)
		printf("Translating label %s ...\n", PyGrammar_LabelRepr(lb));
Guido van Rossum's avatar
Guido van Rossum committed
145 146 147 148
	
	if (lb->lb_type == NAME) {
		for (i = 0; i < g->g_ndfas; i++) {
			if (strcmp(lb->lb_str, g->g_dfa[i].d_name) == 0) {
149 150 151 152 153
				if (Py_DebugFlag)
					printf(
					    "Label %s is non-terminal %d.\n",
					    lb->lb_str,
					    g->g_dfa[i].d_type);
Guido van Rossum's avatar
Guido van Rossum committed
154 155 156 157 158 159
				lb->lb_type = g->g_dfa[i].d_type;
				lb->lb_str = NULL;
				return;
			}
		}
		for (i = 0; i < (int)N_TOKENS; i++) {
160 161
			if (strcmp(lb->lb_str, _PyParser_TokenNames[i]) == 0) {
				if (Py_DebugFlag)
Guido van Rossum's avatar
Guido van Rossum committed
162 163 164 165 166 167 168 169 170 171 172 173
					printf("Label %s is terminal %d.\n",
						lb->lb_str, i);
				lb->lb_type = i;
				lb->lb_str = NULL;
				return;
			}
		}
		printf("Can't translate NAME label '%s'\n", lb->lb_str);
		return;
	}
	
	if (lb->lb_type == STRING) {
174
		if (isalpha((int)(lb->lb_str[1])) || lb->lb_str[1] == '_') {
175
			char *p;
176
			if (Py_DebugFlag)
Guido van Rossum's avatar
Guido van Rossum committed
177 178 179 180 181 182 183
				printf("Label %s is a keyword\n", lb->lb_str);
			lb->lb_type = NAME;
			lb->lb_str++;
			p = strchr(lb->lb_str, '\'');
			if (p)
				*p = '\0';
		}
184
		else if (lb->lb_str[2] == lb->lb_str[0]) {
185
			int type = (int) PyToken_OneChar(lb->lb_str[1]);
186 187 188 189 190 191 192 193 194
			if (type != OP) {
				lb->lb_type = type;
				lb->lb_str = NULL;
			}
			else
				printf("Unknown OP label %s\n",
					lb->lb_str);
		}
		else if (lb->lb_str[2] && lb->lb_str[3] == lb->lb_str[0]) {
195
			int type = (int) PyToken_TwoChars(lb->lb_str[1],
196 197 198 199
						   lb->lb_str[2]);
			if (type != OP) {
				lb->lb_type = type;
				lb->lb_str = NULL;
Guido van Rossum's avatar
Guido van Rossum committed
200 201
			}
			else
202
				printf("Unknown OP label %s\n",
Guido van Rossum's avatar
Guido van Rossum committed
203 204
					lb->lb_str);
		}
205 206 207 208 209 210 211 212 213 214 215 216
		else if (lb->lb_str[2] && lb->lb_str[3] && lb->lb_str[4] == lb->lb_str[0]) {
			int type = (int) PyToken_ThreeChars(lb->lb_str[1],
							    lb->lb_str[2],
							    lb->lb_str[3]);
			if (type != OP) {
				lb->lb_type = type;
				lb->lb_str = NULL;
			}
			else
				printf("Unknown OP label %s\n",
					lb->lb_str);
		}
217 218 219
		else
			printf("Can't translate STRING label %s\n",
				lb->lb_str);
Guido van Rossum's avatar
Guido van Rossum committed
220 221
	}
	else
222 223
		printf("Can't translate label '%s'\n",
		       PyGrammar_LabelRepr(lb));
Guido van Rossum's avatar
Guido van Rossum committed
224
}