acceler.c revision 7b4c8e485c6ec3cc4605b6e1a24bd3a324f1c0a5
1
2/* Parser accelerator module */
3
4/* The parser as originally conceived had disappointing performance.
5   This module does some precomputation that speeds up the selection
6   of a DFA based upon a token, turning a search through an array
7   into a simple indexing operation.  The parser now cannot work
8   without the accelerators installed.  Note that the accelerators
9   are installed dynamically when the parser is initialized, they
10   are not part of the static data structure written on graminit.[ch]
11   by the parser generator. */
12
13#include "pgenheaders.h"
14#include "grammar.h"
15#include "node.h"
16#include "token.h"
17#include "parser.h"
18
19/* Forward references */
20static void fixdfa(grammar *, dfa *);
21static void fixstate(grammar *, state *);
22
23void
24PyGrammar_AddAccelerators(grammar *g)
25{
26	dfa *d;
27	int i;
28	d = g->g_dfa;
29	for (i = g->g_ndfas; --i >= 0; d++)
30		fixdfa(g, d);
31	g->g_accel = 1;
32}
33
34void
35PyGrammar_RemoveAccelerators(grammar *g)
36{
37	dfa *d;
38	int i;
39	g->g_accel = 0;
40	d = g->g_dfa;
41	for (i = g->g_ndfas; --i >= 0; d++) {
42		state *s;
43		int j;
44		s = d->d_state;
45		for (j = 0; j < d->d_nstates; j++, s++) {
46			if (s->s_accel)
47				PyMem_DEL(s->s_accel);
48			s->s_accel = NULL;
49		}
50	}
51}
52
53static void
54fixdfa(grammar *g, dfa *d)
55{
56	state *s;
57	int j;
58	s = d->d_state;
59	for (j = 0; j < d->d_nstates; j++, s++)
60		fixstate(g, s);
61}
62
63static void
64fixstate(grammar *g, state *s)
65{
66	arc *a;
67	int k;
68	int *accel;
69	int nl = g->g_ll.ll_nlabels;
70	s->s_accept = 0;
71	accel = PyMem_NEW(int, nl);
72	for (k = 0; k < nl; k++)
73		accel[k] = -1;
74	a = s->s_arc;
75	for (k = s->s_narcs; --k >= 0; a++) {
76		int lbl = a->a_lbl;
77		label *l = &g->g_ll.ll_label[lbl];
78		int type = l->lb_type;
79		if (a->a_arrow >= (1 << 7)) {
80			printf("XXX too many states!\n");
81			continue;
82		}
83		if (ISNONTERMINAL(type)) {
84			dfa *d1 = PyGrammar_FindDFA(g, type);
85			int ibit;
86			if (type - NT_OFFSET >= (1 << 7)) {
87				printf("XXX too high nonterminal number!\n");
88				continue;
89			}
90			for (ibit = 0; ibit < g->g_ll.ll_nlabels; ibit++) {
91				if (testbit(d1->d_first, ibit)) {
92#ifdef applec
93#define MPW_881_BUG			/* Undefine if bug below is fixed */
94#endif
95#ifdef MPW_881_BUG
96					/* In 881 mode MPW 3.1 has a code
97					   generation bug which seems to
98					   set the upper bits; fix this by
99					   explicitly masking them off */
100					int temp;
101#endif
102					if (accel[ibit] != -1)
103						printf("XXX ambiguity!\n");
104#ifdef MPW_881_BUG
105					temp = 0xFFFF &
106						(a->a_arrow | (1 << 7) |
107						 ((type - NT_OFFSET) << 8));
108					accel[ibit] = temp;
109#else
110					accel[ibit] = a->a_arrow | (1 << 7) |
111						((type - NT_OFFSET) << 8);
112#endif
113				}
114			}
115		}
116		else if (lbl == EMPTY)
117			s->s_accept = 1;
118		else if (lbl >= 0 && lbl < nl)
119			accel[lbl] = a->a_arrow;
120	}
121	while (nl > 0 && accel[nl-1] == -1)
122		nl--;
123	for (k = 0; k < nl && accel[k] == -1;)
124		k++;
125	if (k < nl) {
126		int i;
127		s->s_accel = PyMem_NEW(int, nl-k);
128		if (s->s_accel == NULL) {
129			fprintf(stderr, "no mem to add parser accelerators\n");
130			exit(1);
131		}
132		s->s_lower = k;
133		s->s_upper = nl;
134		for (i = 0; k < nl; i++, k++)
135			s->s_accel[i] = accel[k];
136	}
137	PyMem_DEL(accel);
138}
139