summaryrefslogtreecommitdiffstats
path: root/doc/ebnf.py
blob: 1989118cf0a66fe5d5627da796c708538953b887 (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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import string

class EBNF:
    IDENT   = 0
    LITERAL = 2
    LPAREN  = 3
    LBRAK   = 4
    LBRACE  = 5
    BAR     = 6
    EQL     = 7
    RPAREN  = 8
    RBRAK   = 9
    RBRACE  = 10
    PERIOD  = 11
    OTHER   = 12

    __input__  = None
    __char__   = None
    __symbol__ = None
    __data__   = None

    def __init__(self, input):
        self.__input__ = input
        self.__get_char__()

    def __get_char__(self):
        self.__char__ = self.__input__.read(1)
        if self.__char__ == '':
            raise EOFError
        return self.__char__

    def __get_sym__(self):
        self.__data__ = None

        while self.__char__ in string.whitespace:
            self.__get_char__()

        if self.__char__ in string.letters + "_":
            self.__symbol__ = self.IDENT
            self.__data__ = self.__char__
            while self.__get_char__() in string.letters + "_":
                self.__data__ += self.__char__
            return

        elif self.__char__ == '"':
            self.__symbol__ = self.LITERAL
            self.__data__ = ""
            while self.__get_char__() != '"':
                self.__data__ += self.__char__

        elif self.__char__ == '=':
            self.__symbol__ = self.EQL
        elif self.__char__ == '(':
            self.__symbol__ = self.LPAREN
        elif self.__char__ == ')':
            self.__symbol__ = self.RPAREN
        elif self.__char__ == '[':
            self.__symbol__ = self.LBRAK
        elif self.__char__ == ']':
            self.__symbol__ = self.RBRAK
        elif self.__char__ == '{':
            self.__symbol__ = self.LBRACE
        elif self.__char__ == '}':
            self.__symbol__ = self.RBRACE
        elif self.__char__ == '|':
            self.__symbol__ = self.BAR
        elif self.__char__ == '.':
            self.__symbol__ = self.PERIOD
        else:
            self.__symbol__ = self.OTHER

        self.__get_char__()

    def __error__(self, num):
        pos = self.__input__.tell()
        if pos > self.__lastpos__ + 2:
            print "ERROR: pos=%d, err=%d, sym=%d" % (pos, num, self.__symbol__)
            self.__lastpos__ = pos

    def __expression__(self):
        self.__term__()
        while self.__symbol__ == self.BAR:
            self.__get_sym__()
            self.__term__()

    def __term__(self):
        self.__factor__()
        while self.__symbol__ < self.BAR:
            self.__factor__()

    def __factor__(self):
        if self.__symbol__ == self.IDENT:
            print "record(TO, '%s', 1)" % (self.__data__,)
            self.__get_sym__()
        elif self.__symbol__ == self.LITERAL:
            print "record(T1, '%s', 0)" % (self.__data__,)
            self.__get_sym__()
        elif self.__symbol__ == self.LPAREN:
            self.__get_sym__()
            self.__expression__()
            if self.__symbol__ == self.RPAREN:
                self.__get_sym__()
            else:
                self.__error__(2)
        elif self.__symbol__ == self.LBRAK:
            self.__get_sym__()
            self.__expression__()
            if self.__symbol__ == self.RBRAK:
                self.__get_sym__()
            else:
                self.__error__(3)
        elif self.__symbol__ == self.LBRACE:
            self.__get_sym__()
            self.__expression__()
            if self.__symbol__ == self.RBRACE:
                self.__get_sym__()
            else:
                self.__error__(4)
        else:
            self.__error__(5)

    def __production__(self):
        self.__get_sym__()

        if self.__symbol__ == self.EQL:
            self.__get_sym__()
        else:
            self.__error__(7)

        self.__expression__()

        if self.__symbol__ == self.PERIOD:
            self.__get_sym__()
        else:
            self.__error__(8)

    def __syntax__(self):
        while self.__symbol__ == self.IDENT:
            self.__production__()

    def compile(self):
        try:
            self.__lastpos__ = 0
            self.__get_sym__()
            self.__syntax__()
        except EOFError:
            return

if __name__ == '__main__':
    import sys
    ebnf = EBNF(sys.stdin)
    ebnf.compile()