Subversion Repositories programming

Rev

Rev 165 | Rev 167 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
161 ira 1
#!/usr/bin/env python
2
# Copyright: Ira W. Snyder
3
# Start Date: 2005-11-18
4
# End Date:
5
# License: Public Domain
6
#
7
# Changelog Follows:
8
#
9
# 2005-11-18
10
# * Just getting the basics in place, since we haven't been given
11
#   the whole description of the project yet.
12
#
166 ira 13
# 2005-11-26
14
# * Got the whole class working, now to implement pretty-printing
15
#
161 ira 16
 
17
# Check for <Python-2.3 compatibility (boolean values)
18
try:
19
  True, False
20
except NameError:
21
  (True, False) = (1, 0)
22
 
162 ira 23
import sys
163 ira 24
 
164 ira 25
class Queue:
26
    """Implements a basic FIFO queue"""
27
 
28
    def __init__(self):
29
        self.q = []
30
 
31
    def empty(self):
32
        """Empty the queue"""
33
        self.q = []
34
 
35
    def enqueue(self, elem):
36
        """Enqueue an element"""
37
        self.q.append(elem)
38
 
39
    def dequeue(self):
40
        """Get the object at the front of the queue"""
41
        elem = self.q[0]
42
        self.q = self.q[1:]
43
        return elem
44
 
162 ira 45
class RecursiveDescentParser:
161 ira 46
    def __init__(self):
162 ira 47
        self.__clear()
161 ira 48
 
49
    def __clear(self):
50
        self.str = ""   # the string of input to test
51
        self.strpos = 0 # the current position in str
166 ira 52
        self.derivation = ""
161 ira 53
 
166 ira 54
    def __replace_sym(self, to_repl, with_this):
55
        """Replace a string in the derivation with another string"""
56
 
57
        pos = s.find(to_repl)
58
 
59
        if pos == -1:
60
            raise ValueError
61
 
62
        self.derivation = s[:pos] + str(with_this) + s[pos+len(to_repl):]
63
 
161 ira 64
    def __input_test_str(self):
162 ira 65
        self.str = raw_input("input str: ")
161 ira 66
 
67
    def main_menu(self):
68
 
69
        done = False
70
 
71
        while not done:
72
            print 'Menu:'
73
            print '========================================'
74
            print '1. Test a string'
75
            print '2. Quit'
76
            print
77
            s = raw_input('Choice >>> ')
78
            print
79
 
80
            if s == '1':
162 ira 81
                self.__clear()
161 ira 82
                self.__input_test_str()
83
                self.__test_str()
84
            elif s == '2':
85
                done = True
86
            else:
87
                print 'Bad Selection'
88
                print
89
 
162 ira 90
    def __test_str(self):
164 ira 91
        print 'Parsing: %s' % ((self.procE() and len(self.str) == self.strpos) and 'Completed' or 'Failed', )
163 ira 92
        print
161 ira 93
 
162 ira 94
    def procE(self):
95
        print 'procE(%s) ->' % (self.str[self.strpos:])
163 ira 96
 
164 ira 97
        # Catch the exception generated below if we don't have enough
98
        # input to 'look ahead'
99
        try:
100
            return self.procT() and self.procEprm()
101
        except IndexError:
102
            print 'Not enough input to continue, failed.'
103
            return False
162 ira 104
 
163 ira 105
    def procEprm(self):
106
        # Check empty str
107
        if self.strpos >= len(self.str):
108
            return True
109
 
110
        print 'procEprm(%s) ->' % (self.str[self.strpos:])
111
 
112
        # Check +
113
        if self.str[self.strpos] == '+':
114
            self.strpos += 1
115
            return self.procT() and self.procEprm()
116
 
117
        # Check -
118
        if self.str[self.strpos] == '-':
119
            self.strpos += 1
120
            return self.procT() and self.procEprm()
121
 
122
        # We accept empty str, so take it
123
        return True
124
 
162 ira 125
    def procT(self):
126
        print 'procT(%s) ->' % (self.str[self.strpos:])
127
 
164 ira 128
        return self.procP() and self.procTprm()
162 ira 129
 
163 ira 130
    def procTprm(self):
162 ira 131
        # Check empty str
132
        if self.strpos >= len(self.str):
133
            return True
134
 
163 ira 135
        print 'procTprm(%s) ->' % (self.str[self.strpos:])
162 ira 136
 
163 ira 137
        # Check *
138
        if self.str[self.strpos] == '*':
162 ira 139
            self.strpos += 1
164 ira 140
            return self.procP() and self.procTprm()
162 ira 141
 
163 ira 142
        # we accept empty str, so take it
143
        return True
144
 
164 ira 145
    def procP(self):
146
        print 'procP(%s) ->' % (self.str[self.strpos:])
147
 
148
        return self.procF() and self.procPprm()
149
 
150
    def procPprm(self):
151
        # Check empty str
152
        if self.strpos >= len(self.str):
153
            return True
154
 
155
        print 'procPprm(%s) -> ' % (self.str[self.strpos:])
156
 
157
        # check exp symbol
158
        if self.str[self.strpos] == '^':
159
            self.strpos += 1
160
            return self.procF() and self.procPprm()
161
 
162
        # we accept empty str, so take it
163
        return True
164
 
163 ira 165
    def procF(self):
166
        print 'procF(%s) ->' % (self.str[self.strpos:])
167
 
168
        # Check x
169
        if self.str[self.strpos] == 'x':
170
            self.strpos += 1
171
            return self.procV()
172
 
173
        # Check (E)
174
        if self.str[self.strpos] == '(':
175
            self.strpos += 1
176
 
177
            if self.procE():
178
                if self.str[self.strpos] == ')':
164 ira 179
                    self.strpos += 1
163 ira 180
                    return True
181
 
164 ira 182
                return False
183
 
163 ira 184
            return False
185
 
186
        # Must be a number
187
        return self.procN()
188
 
189
    def procN(self):
190
        print 'procN(%s) ->' % (self.str[self.strpos:])
191
 
164 ira 192
        if self.procD(): # we have one digit
193
            if self.procD(): # two digits
194
                return True
195
 
163 ira 196
            return True
197
 
162 ira 198
        return False
199
 
163 ira 200
    def procV(self):
201
        print 'procV(%s) ->' % (self.str[self.strpos:])
202
 
164 ira 203
        return self.procD()
163 ira 204
 
164 ira 205
    def procD(self):
206
        print 'procD(%s) ->' % (self.str[self.strpos:])
207
 
165 ira 208
        try:
209
            # Check if we are a single digit
210
            if self.str[self.strpos] in '0123456789':
211
                self.strpos += 1
212
                return True
213
        except IndexError: # ran out of input
214
            return False
164 ira 215
 
216
        return False
217
 
161 ira 218
if __name__ == '__main__':
162 ira 219
    rdp = RecursiveDescentParser()
220
    rdp.main_menu()
161 ira 221