Subversion Repositories programming

Rev

Rev 166 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 166 Rev 167
Line 11... Line 11...
11
#   the whole description of the project yet.
11
#   the whole description of the project yet.
12
#
12
#
13
# 2005-11-26
13
# 2005-11-26
14
# * Got the whole class working, now to implement pretty-printing
14
# * Got the whole class working, now to implement pretty-printing
15
#
15
#
-
 
16
# 2005-11-28
-
 
17
# * This has pretty-printing now. (The derivation looks correct)
-
 
18
# * Needs testing still, but for every case I can come up with, it works.
-
 
19
#
16
 
20
 
17
# Check for <Python-2.3 compatibility (boolean values)
21
# Check for <Python-2.3 compatibility (boolean values)
18
try:
22
try:
19
  True, False
23
  True, False
20
except NameError:
24
except NameError:
21
  (True, False) = (1, 0)
25
  (True, False) = (1, 0)
22
 
26
 
23
import sys
27
import sys
24
 
28
 
25
class Queue:
-
 
26
    """Implements a basic FIFO queue"""
-
 
27
 
-
 
28
    def __init__(self):
29
# Default Symbols
29
        self.q = []
30
SYM_E = "A" # "E"
30
 
-
 
31
    def empty(self):
31
SYM_T = "B" # "T"
32
        """Empty the queue"""
32
SYM_P = "C" # "P"
33
        self.q = []
33
SYM_F = "F"
34
 
-
 
35
    def enqueue(self, elem):
34
SYM_N = "N"
36
        """Enqueue an element"""
35
SYM_V = "V"
37
        self.q.append(elem)
36
SYM_D = "D"
38
 
-
 
39
    def dequeue(self):
37
SYM_EPRM = "E'"
40
        """Get the object at the front of the queue"""
-
 
41
        elem = self.q[0]
38
SYM_TPRM = "T'"
42
        self.q = self.q[1:]
39
SYM_PPRM = "P'"
43
        return elem
40
SYM_EMPTY = ""
44
 
41
 
45
class RecursiveDescentParser:
42
class RecursiveDescentParser:
46
    def __init__(self):
43
    def __init__(self):
47
        self.__clear()
44
        self.__clear()
48
 
45
 
Line 52... Line 49...
52
        self.derivation = ""
49
        self.derivation = ""
53
 
50
 
54
    def __replace_sym(self, to_repl, with_this):
51
    def __replace_sym(self, to_repl, with_this):
55
        """Replace a string in the derivation with another string"""
52
        """Replace a string in the derivation with another string"""
56
 
53
 
57
        pos = s.find(to_repl)
54
        pos = self.derivation.find(to_repl)
58
    
55
    
59
        if pos == -1:
56
        if pos == -1:
-
 
57
            #print 'str: %s' % (self.derivation, )
-
 
58
            #print 'to_repl: %s' % (to_repl, )
-
 
59
            #print 'with_this: %s' % (with_this, )
60
            raise ValueError
60
            raise ValueError
61
    
61
    
62
        self.derivation = s[:pos] + str(with_this) + s[pos+len(to_repl):]
62
        self.derivation = self.derivation[:pos] + str(with_this) + self.derivation[pos+len(to_repl):]
63
 
63
 
64
    def __input_test_str(self):
64
    def __input_test_str(self):
65
        self.str = raw_input("input str: ")
65
        self.str = raw_input("input str: ")
66
 
66
 
67
    def main_menu(self):
67
    def main_menu(self):
Line 85... Line 85...
85
                done = True
85
                done = True
86
            else:
86
            else:
87
                print 'Bad Selection'
87
                print 'Bad Selection'
88
                print
88
                print
89
 
89
 
-
 
90
    def __print_deriv(self, with_arrow=True):
-
 
91
        if with_arrow:
-
 
92
            print "%s ->" % (self.derivation, ),
-
 
93
        else:
-
 
94
            print "%s" % (self.derivation, )
-
 
95
                
90
    def __test_str(self):
96
    def __test_str(self):
-
 
97
        self.derivation = SYM_E[:]
-
 
98
        
-
 
99
        procE_ans = self.procE()
-
 
100
        all_input_used = (len(self.str) == self.strpos)
-
 
101
        ans = procE_ans and all_input_used
-
 
102
 
-
 
103
        self.__print_deriv(with_arrow=False)
-
 
104
        print
91
        print 'Parsing: %s' % ((self.procE() and len(self.str) == self.strpos) and 'Completed' or 'Failed', )
105
        print 'Parsing: %s' % (ans and 'Completed' or 'Failed', )
-
 
106
 
-
 
107
        if not ans:
-
 
108
            print 'All input used: %s' % (all_input_used and 'True' or 'False', )
-
 
109
 
92
        print
110
        print
93
 
111
 
94
    def procE(self):
112
    def procE(self):
95
        print 'procE(%s) ->' % (self.str[self.strpos:])
113
        self.__print_deriv()
96
 
114
 
97
        # Catch the exception generated below if we don't have enough
115
        # Catch the exception generated below if we don't have enough
98
        # input to 'look ahead'
116
        # input to 'look ahead'
99
        try:
117
        try:
-
 
118
            self.__replace_sym(SYM_E, SYM_T + SYM_EPRM)
100
            return self.procT() and self.procEprm()
119
            return self.procT() and self.procEprm()
101
        except IndexError:
120
        except IndexError:
102
            print 'Not enough input to continue, failed.'
121
            print 'Not enough input to continue, failed.'
103
            return False
122
            return False
104
 
123
 
105
    def procEprm(self):
124
    def procEprm(self):
-
 
125
        self.__print_deriv()
-
 
126
 
106
        # Check empty str
127
        # Check empty str
107
        if self.strpos >= len(self.str):
128
        if self.strpos >= len(self.str):
-
 
129
            self.__replace_sym(SYM_EPRM, SYM_EMPTY)
108
            return True
130
            return True
109
 
131
 
110
        print 'procEprm(%s) ->' % (self.str[self.strpos:])
-
 
111
 
-
 
112
        # Check +
132
        # Check +
113
        if self.str[self.strpos] == '+':
133
        if self.str[self.strpos] == '+':
114
            self.strpos += 1
134
            self.strpos += 1
-
 
135
            self.__replace_sym(SYM_EPRM, '+' + SYM_T + SYM_EPRM)
115
            return self.procT() and self.procEprm()
136
            return self.procT() and self.procEprm()
116
 
137
 
117
        # Check -
138
        # Check -
118
        if self.str[self.strpos] == '-':
139
        if self.str[self.strpos] == '-':
119
            self.strpos += 1
140
            self.strpos += 1
-
 
141
            self.__replace_sym(SYM_EPRM, '-' + SYM_T + SYM_EPRM)
120
            return self.procT() and self.procEprm()
142
            return self.procT() and self.procEprm()
121
 
143
 
122
        # We accept empty str, so take it
144
        # We accept empty str, so take it
-
 
145
        self.__replace_sym(SYM_EPRM, SYM_EMPTY)
123
        return True
146
        return True
124
 
147
 
125
    def procT(self):
148
    def procT(self):
126
        print 'procT(%s) ->' % (self.str[self.strpos:])
149
        self.__print_deriv()
127
 
150
 
-
 
151
        self.__replace_sym(SYM_T, SYM_P + SYM_TPRM)
128
        return self.procP() and self.procTprm()
152
        return self.procP() and self.procTprm()
129
 
153
 
130
    def procTprm(self):
154
    def procTprm(self):
-
 
155
        self.__print_deriv()
-
 
156
        
131
        # Check empty str
157
        # Check empty str
132
        if self.strpos >= len(self.str):
158
        if self.strpos >= len(self.str):
-
 
159
            self.__replace_sym(SYM_TPRM, SYM_EMPTY)
133
            return True
160
            return True
134
 
161
 
135
        print 'procTprm(%s) ->' % (self.str[self.strpos:])
-
 
136
 
-
 
137
        # Check *
162
        # Check *
138
        if self.str[self.strpos] == '*':
163
        if self.str[self.strpos] == '*':
139
            self.strpos += 1
164
            self.strpos += 1
-
 
165
            self.__replace_sym(SYM_TPRM, '*' + SYM_P + SYM_TPRM)
140
            return self.procP() and self.procTprm()
166
            return self.procP() and self.procTprm()
141
 
167
 
142
        # we accept empty str, so take it
168
        # we accept empty str, so take it
-
 
169
        self.__replace_sym(SYM_TPRM, SYM_EMPTY)
143
        return True
170
        return True
144
 
171
 
145
    def procP(self):
172
    def procP(self):
146
        print 'procP(%s) ->' % (self.str[self.strpos:])
173
        self.__print_deriv()
147
 
174
 
-
 
175
        self.__replace_sym(SYM_P, SYM_F + SYM_PPRM)
148
        return self.procF() and self.procPprm()
176
        return self.procF() and self.procPprm()
149
 
177
 
150
    def procPprm(self):
178
    def procPprm(self):
-
 
179
        self.__print_deriv()
-
 
180
 
151
        # Check empty str
181
        # Check empty str
152
        if self.strpos >= len(self.str):
182
        if self.strpos >= len(self.str):
-
 
183
            self.__replace_sym(SYM_PPRM, SYM_EMPTY)
153
            return True
184
            return True
154
 
185
 
155
        print 'procPprm(%s) -> ' % (self.str[self.strpos:])
-
 
156
 
-
 
157
        # check exp symbol
186
        # check exp symbol
158
        if self.str[self.strpos] == '^':
187
        if self.str[self.strpos] == '^':
159
            self.strpos += 1
188
            self.strpos += 1
-
 
189
            self.__replace_sym(SYM_PPRM, '^' + SYM_F + SYM_PPRM)
160
            return self.procF() and self.procPprm()
190
            return self.procF() and self.procPprm()
161
 
191
 
162
        # we accept empty str, so take it
192
        # we accept empty str, so take it
-
 
193
        self.__replace_sym(SYM_PPRM, SYM_EMPTY)
163
        return True
194
        return True
164
 
195
 
165
    def procF(self):
196
    def procF(self):
166
        print 'procF(%s) ->' % (self.str[self.strpos:])
197
        self.__print_deriv()
167
 
198
 
168
        # Check x
199
        # Check x
169
        if self.str[self.strpos] == 'x':
200
        if self.str[self.strpos] == 'x':
170
            self.strpos += 1
201
            self.strpos += 1
-
 
202
            self.__replace_sym(SYM_F, 'x' + SYM_V)
171
            return self.procV()
203
            return self.procV()
172
 
204
 
173
        # Check (E)
205
        # Check (E)
174
        if self.str[self.strpos] == '(':
206
        if self.str[self.strpos] == '(':
175
            self.strpos += 1
207
            self.strpos += 1
-
 
208
            self.__replace_sym(SYM_F, '(' + SYM_E + ')')
176
 
209
 
177
            if self.procE():
210
            if self.procE():
178
                if self.str[self.strpos] == ')':
211
                if self.str[self.strpos] == ')':
179
                    self.strpos += 1
212
                    self.strpos += 1
180
                    return True
213
                    return True
Line 182... Line 215...
182
                return False
215
                return False
183
 
216
 
184
            return False
217
            return False
185
 
218
 
186
        # Must be a number
219
        # Must be a number
-
 
220
        self.__replace_sym(SYM_F, SYM_N)
187
        return self.procN()
221
        return self.procN()
188
 
222
 
189
    def procN(self):
223
    def procN(self):
190
        print 'procN(%s) ->' % (self.str[self.strpos:])
224
        self.__print_deriv()
191
 
225
 
192
        if self.procD(): # we have one digit
226
        nums = range(100) # get 0-99
193
            if self.procD(): # two digits
227
        nums.reverse()    # make it 99-0
194
                return True
-
 
195
 
228
 
-
 
229
        for n in nums:
-
 
230
            if self.str[self.strpos:self.strpos+len(str(n))] == str(n):
-
 
231
                self.strpos += len(str(n))
-
 
232
                self.__replace_sym(SYM_N, str(n))
196
            return True
233
                return True
197
 
234
 
198
        return False
235
        return False
199
 
236
    
200
    def procV(self):
237
    def procV(self):
201
        print 'procV(%s) ->' % (self.str[self.strpos:])
238
        self.__print_deriv()
202
 
239
 
203
        return self.procD()
-
 
204
 
-
 
205
    def procD(self):
-
 
206
        print 'procD(%s) ->' % (self.str[self.strpos:])
-
 
207
 
-
 
208
        try:
-
 
209
            # Check if we are a single digit
-
 
210
            if self.str[self.strpos] in '0123456789':
240
        if self.str[self.strpos] in '0123456789':
211
                self.strpos += 1
241
            self.strpos += 1
212
                return True
-
 
213
        except IndexError: # ran out of input
242
            self.__replace_sym(SYM_V, self.str[self.strpos-1])
214
            return False
243
            return True
215
 
244
 
216
        return False
245
        return False
217
 
246
    
218
if __name__ == '__main__':
247
if __name__ == '__main__':
219
    rdp = RecursiveDescentParser()
248
    rdp = RecursiveDescentParser()
220
    rdp.main_menu()
249
    rdp.main_menu()
221
 
250