root/readlisp.py

Revision a59b25878d7a11b96442f56d1549621003b2628b, 4.2 kB (checked in by pj <pj@03e2507f-5f03-0410-b1bc-a06d56394c08>, 2 years ago)

added readlisp.py back

git-svn-id: file:///home/pj/.svnroot/mhi@39 03e2507f-5f03-0410-b1bc-a06d56394c08

  • Property mode set to 100644
Line 
1 """
2 Ole Martin Bjorndalen <olemb@stud.cs.uit.no>
3 2006-08-12
4 """
5
6 import StringIO
7 import types
8
9 EOF = ''
10 END_PAREN = ')'
11
12 class CharFile:
13     def __init__(self, file):
14         self.file = file
15         self.c = ''
16
17     def getchar(self):
18         if self.c:
19             c = self.c
20             self.c = ''
21             return c
22         else:
23             self.c = ''
24             c = self.file.read(1)
25             # print [c]
26             return c
27
28     def ungetchar(self, c):
29         self.c = c
30
31 class LispSymbol:
32     def __init__(self, name):
33         self.name = name
34
35     def __repr__(self):
36         return 'LispSymbol(%s)' % repr(self.name)
37
38     def __str__(self):
39         return self.name
40
41 class LispReader:
42     def __init__(self, file):
43         self.file = CharFile(file)
44         self.whitespace = ' \r\n\t'
45         self.atom_end = self.whitespace + '()"|;'
46
47     def _skip_whitespace(self):
48         """Read until next non-whitespace or EOF"""
49         while 1:
50             c = self.file.getchar()
51             if c == EOF or c not in self.whitespace:
52                 self.file.ungetchar(c)
53                 return
54
55     def _skip_comment(self):
56         """Read until EOL or EOF"""
57         while 1:
58             c = self.file.getchar()
59             if c == '\n' or c == EOF:
60                 return
61
62     def _parse_atom(self, atom):
63         """Parse an atom and return and integer, a float or a symbol"""
64         try:
65             return int(atom)
66         except ValueError:
67             try:
68                 return float(atom)
69             except ValueError:
70                 return LispSymbol(atom)
71
72     def _read_atom(self):
73         """Read a symbol or number"""
74         atom = ''
75
76         while 1:
77             c = self.file.getchar()
78             if c in self.atom_end or c == EOF:
79                 self.file.ungetchar(c)
80                 break
81             atom += c
82
83         return self._parse_atom(atom)
84
85     def _read_string(self):
86         string = ''
87        
88         while 1:
89             c = self.file.getchar()
90
91             if c == '':
92                 raise EOFError('Missing end quote for string')
93             elif c == '"':
94                 return string
95             elif c == '\\':
96                 c = self.file.getchar()
97                 if c == '':
98                     raise EOFError('EOF after escape sequence')
99                 else:
100                     string += c
101             else:
102                 string += c
103
104     def _read_list(self):       
105         items = []
106         while 1:
107             item = self._read_expr()
108             if item is END_PAREN:
109                 break
110             else:
111                 items.append(item)
112         return items
113
114     def _read_expr(self):
115
116         while 1:
117             self._skip_whitespace()
118
119             c = self.file.getchar()
120
121             if c == EOF:
122                 raise EOFError('End of LISP stream')
123             elif c == ';':
124                 self._skip_comment()
125             elif c == '(':
126                 return self._read_list()
127             elif c == ')':
128                 return END_PAREN
129             elif c == '"':
130                 return self._read_string()
131             #elif c == '|':
132             #    return self.read_quoted_symbol()
133             else:
134                 self.file.ungetchar(c)
135                 return self._read_atom()
136
137     def __iter__(self):
138         while 1:
139             try:
140                 yield self._read_expr()
141             except EOFError:
142                 return
143
144
145 def writelisp(obj):
146     """Convert a python object into an equivalent lisp expression."""
147
148     if type(obj) is types.ListType:
149         return '(%s)' % ' '.join(map(writelisp, obj))
150     elif type(obj) is types.StringType:
151         out = '"'
152         for c in obj:
153             if c in '\\"':
154                 out += '\\'
155             out += c
156         out += '"'
157         return out
158     elif type(obj) in [types.LongType, types.IntType]:
159         return str(obj)
160     elif type(obj) is types.ComplexType:
161         return '#C(%s %s)' % (obj.real, obj.imag)
162     elif obj == None:
163         return 'nil'
164     else:
165         return repr(obj)
166
167 def readlisp(text):
168     """Read the first lisp expression in the string"""
169     return LispReader(StringIO.StringIO(text))._read_expr()
170
171 if __name__ == '__main__':
172     p = LispReader(open('test.lisp'))
173     print repr(p._read_expr())
174
Note: See TracBrowser for help on using the browser.