2 /* Parser accelerator module */
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. */
13 #include "pgenheaders.h"
19 /* Forward references */
20 static void fixdfa(grammar
*, dfa
*);
21 static void fixstate(grammar
*, state
*);
24 PyGrammar_AddAccelerators(grammar
*g
)
29 fprintf(stderr
, "Adding parser accelerators ...\n");
32 for (i
= g
->g_ndfas
; --i
>= 0; d
++)
36 fprintf(stderr
, "Done.\n");
41 PyGrammar_RemoveAccelerators(grammar
*g
)
47 for (i
= g
->g_ndfas
; --i
>= 0; d
++) {
51 for (j
= 0; j
< d
->d_nstates
; j
++, s
++) {
53 PyMem_DEL(s
->s_accel
);
60 fixdfa(grammar
*g
, dfa
*d
)
65 for (j
= 0; j
< d
->d_nstates
; j
++, s
++)
70 fixstate(grammar
*g
, state
*s
)
75 int nl
= g
->g_ll
.ll_nlabels
;
77 accel
= PyMem_NEW(int, nl
);
78 for (k
= 0; k
< nl
; k
++)
81 for (k
= s
->s_narcs
; --k
>= 0; a
++) {
83 label
*l
= &g
->g_ll
.ll_label
[lbl
];
84 int type
= l
->lb_type
;
85 if (a
->a_arrow
>= (1 << 7)) {
86 printf("XXX too many states!\n");
89 if (ISNONTERMINAL(type
)) {
90 dfa
*d1
= PyGrammar_FindDFA(g
, type
);
92 if (type
- NT_OFFSET
>= (1 << 7)) {
93 printf("XXX too high nonterminal number!\n");
96 for (ibit
= 0; ibit
< g
->g_ll
.ll_nlabels
; ibit
++) {
97 if (testbit(d1
->d_first
, ibit
)) {
99 #define MPW_881_BUG /* Undefine if bug below is fixed */
102 /* In 881 mode MPW 3.1 has a code
103 generation bug which seems to
104 set the upper bits; fix this by
105 explicitly masking them off */
108 if (accel
[ibit
] != -1)
109 printf("XXX ambiguity!\n");
112 (a
->a_arrow
| (1 << 7) |
113 ((type
- NT_OFFSET
) << 8));
116 accel
[ibit
] = a
->a_arrow
| (1 << 7) |
117 ((type
- NT_OFFSET
) << 8);
122 else if (lbl
== EMPTY
)
124 else if (lbl
>= 0 && lbl
< nl
)
125 accel
[lbl
] = a
->a_arrow
;
127 while (nl
> 0 && accel
[nl
-1] == -1)
129 for (k
= 0; k
< nl
&& accel
[k
] == -1;)
133 s
->s_accel
= PyMem_NEW(int, nl
-k
);
134 if (s
->s_accel
== NULL
) {
135 fprintf(stderr
, "no mem to add parser accelerators\n");
140 for (i
= 0; k
< nl
; i
++, k
++)
141 s
->s_accel
[i
] = accel
[k
];