aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python/src/Parser/firstsets.c
blob: ee75d1bfe067d80e441bb91d16b6b8a78fc12706 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/* Computation of FIRST stets */

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

extern int Py_DebugFlag;

/* Forward */
static void calcfirstset(grammar *, dfa *);

void
addfirstsets(grammar *g)
{
    int i;
    dfa *d;

    if (Py_DebugFlag)
        printf("Adding FIRST sets ...\n");
    for (i = 0; i < g->g_ndfas; i++) {
        d = &g->g_dfa[i];
        if (d->d_first == NULL)
            calcfirstset(g, d);
    }
}

static void
calcfirstset(grammar *g, dfa *d)
{
    int i, j;
    state *s;
    arc *a;
    int nsyms;
    int *sym;
    int nbits;
    static bitset dummy;
    bitset result;
    int type;
    dfa *d1;
    label *l0;

    if (Py_DebugFlag)
        printf("Calculate FIRST set for '%s'\n", d->d_name);

    if (dummy == NULL)
        dummy = newbitset(1);
    if (d->d_first == dummy) {
        fprintf(stderr, "Left-recursion for '%s'\n", d->d_name);
        return;
    }
    if (d->d_first != NULL) {
        fprintf(stderr, "Re-calculating FIRST set for '%s' ???\n",
            d->d_name);
    }
    d->d_first = dummy;

    l0 = g->g_ll.ll_label;
    nbits = g->g_ll.ll_nlabels;
    result = newbitset(nbits);

    sym = (int *)PyObject_MALLOC(sizeof(int));
    if (sym == NULL)
        Py_FatalError("no mem for new sym in calcfirstset");
    nsyms = 1;
    sym[0] = findlabel(&g->g_ll, d->d_type, (char *)NULL);

    s = &d->d_state[d->d_initial];
    for (i = 0; i < s->s_narcs; i++) {
        a = &s->s_arc[i];
        for (j = 0; j < nsyms; j++) {
            if (sym[j] == a->a_lbl)
                break;
        }
        if (j >= nsyms) { /* New label */
            sym = (int *)PyObject_REALLOC(sym,
                                    sizeof(int) * (nsyms + 1));
            if (sym == NULL)
                Py_FatalError(
                    "no mem to resize sym in calcfirstset");
            sym[nsyms++] = a->a_lbl;
            type = l0[a->a_lbl].lb_type;
            if (ISNONTERMINAL(type)) {
                d1 = PyGrammar_FindDFA(g, type);
                if (d1->d_first == dummy) {
                    fprintf(stderr,
                        "Left-recursion below '%s'\n",
                        d->d_name);
                }
                else {
                    if (d1->d_first == NULL)
                        calcfirstset(g, d1);
                    mergebitset(result,
                                d1->d_first, nbits);
                }
            }
            else if (ISTERMINAL(type)) {
                addbit(result, a->a_lbl);
            }
        }
    }
    d->d_first = result;
    if (Py_DebugFlag) {
        printf("FIRST set for '%s': {", d->d_name);
        for (i = 0; i < nbits; i++) {
            if (testbit(result, i))
                printf(" %s", PyGrammar_LabelRepr(&l0[i]));
        }
        printf(" }\n");
    }

    PyObject_FREE(sym);
}