Home | History | Annotate | Download | only in Parser
      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 */
     20 static void fixdfa(grammar *, dfa *);
     21 static void fixstate(grammar *, state *);
     22 
     23 void
     24 PyGrammar_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 
     34 void
     35 PyGrammar_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                 PyObject_FREE(s->s_accel);
     48             s->s_accel = NULL;
     49         }
     50     }
     51 }
     52 
     53 static void
     54 fixdfa(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 
     63 static void
     64 fixstate(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 = (int *) PyObject_MALLOC(nl * sizeof(int));
     72     if (accel == NULL) {
     73         fprintf(stderr, "no mem to build parser accelerators\n");
     74         exit(1);
     75     }
     76     for (k = 0; k < nl; k++)
     77         accel[k] = -1;
     78     a = s->s_arc;
     79     for (k = s->s_narcs; --k >= 0; a++) {
     80         int lbl = a->a_lbl;
     81         label *l = &g->g_ll.ll_label[lbl];
     82         int type = l->lb_type;
     83         if (a->a_arrow >= (1 << 7)) {
     84             printf("XXX too many states!\n");
     85             continue;
     86         }
     87         if (ISNONTERMINAL(type)) {
     88             dfa *d1 = PyGrammar_FindDFA(g, type);
     89             int ibit;
     90             if (type - NT_OFFSET >= (1 << 7)) {
     91                 printf("XXX too high nonterminal number!\n");
     92                 continue;
     93             }
     94             for (ibit = 0; ibit < g->g_ll.ll_nlabels; ibit++) {
     95                 if (testbit(d1->d_first, ibit)) {
     96                     if (accel[ibit] != -1)
     97                         printf("XXX ambiguity!\n");
     98                     accel[ibit] = a->a_arrow | (1 << 7) |
     99                         ((type - NT_OFFSET) << 8);
    100                 }
    101             }
    102         }
    103         else if (lbl == EMPTY)
    104             s->s_accept = 1;
    105         else if (lbl >= 0 && lbl < nl)
    106             accel[lbl] = a->a_arrow;
    107     }
    108     while (nl > 0 && accel[nl-1] == -1)
    109         nl--;
    110     for (k = 0; k < nl && accel[k] == -1;)
    111         k++;
    112     if (k < nl) {
    113         int i;
    114         s->s_accel = (int *) PyObject_MALLOC((nl-k) * sizeof(int));
    115         if (s->s_accel == NULL) {
    116             fprintf(stderr, "no mem to add parser accelerators\n");
    117             exit(1);
    118         }
    119         s->s_lower = k;
    120         s->s_upper = nl;
    121         for (i = 0; k < nl; i++, k++)
    122             s->s_accel[i] = accel[k];
    123     }
    124     PyObject_FREE(accel);
    125 }
    126