root/sexpr.py

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

* switch from readlisp to sexpr
* fix pick behaviour to return 0 instead of (so that scan pick foo never

gets you all of the records)

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

  • Property mode set to 100644
Line 
1 # $ProjectHeader: sexprmodule 0.2.1 Wed, 05 Apr 2000 23:33:53 -0600 nas $
2 # originally from: http://arctrix.com/nas/python/
3 # modified to understand \-escaped quotes instead of "" escaping  - pj 20060809
4 import string
5
6 # tokens
7 [T_EOF, T_ERROR, T_SYMBOL, T_STRING,
8  T_INTEGER, T_FLOAT, T_OPEN, T_CLOSE] = range(8)
9 # states
10 [S_START, S_SYMBOL, S_STRING, S_NUMBER] = range(4)
11
12 SexprError = 'SexprError'
13
14 class SexprParser:
15         def __init__(self, input):
16                 self.line_no = 1
17                 self.input = input
18                 self.char = None
19
20         def getc(self):
21                 if self.char is None:
22                         c = self.input.read(1)
23                         if c == '\n':
24                                 self.line_no = self.line_no + 1
25                         return c
26                 else:
27                         t = self.char
28                         self.char = None
29                         return t
30
31         def ungetc(self, c):
32                 self.char = c
33                
34         def convert_number(self, token):
35                 try:
36                         i = string.atoi(token)
37                         return (T_INTEGER, i)
38                 except ValueError:
39                         try:
40                                 f = string.atof(token)
41                                 return (T_FLOAT, f)
42                         except ValueError:
43                                 return (T_ERROR, '%d: invalid number "%s"' % (self.line_no, token))
44
45         def get_token(self):
46                 token = []
47                 state = S_START
48                 while 1:
49                         c = self.getc()
50                         if state == S_START:
51                                 # EOF
52                                 if not c:
53                                         return (T_EOF, None)
54                                 # whitespace
55                                 elif c in ' \t\n':
56                                         continue
57                                 # comments
58                                 elif c == ';':
59                                         while c and (c != '\n'):
60                                                 c = self.getc()
61                                 elif c == '(':
62                                         return (T_OPEN, None)
63                                 elif c == ')':
64                                         return (T_CLOSE, None)
65                                 elif c == '"':
66                                         state = S_STRING
67                                 elif c in '-0123456789.':
68                                         state = S_NUMBER
69                                         token.append(c)
70                                 else:
71                                         state = S_SYMBOL
72                                         token.append(c)
73                         elif state == S_SYMBOL:
74                                 if not c:
75                                         return (T_SYMBOL, string.join(token, ''))
76                                 if c in ' \t\n;()':
77                                         self.ungetc(c)
78                                         return (T_SYMBOL, string.join(token, ''))
79                                 else:
80                                         token.append(c)
81                         elif state == S_STRING:
82                                 if not c:
83                                         return (T_ERROR, '%d: unexpected EOF inside string' % self.line_no)
84                                 elif c == '\\':
85                                         c = self.getc()
86                                         if c == '"':
87                                                 token.append('"')
88                                         else:
89                                                 self.ungetc(c)
90                                                 token.append('\\')
91                                 elif c == '"':
92                                         return (T_STRING, string.join(token, ''))
93                                 else:
94                                         token.append(c)
95                         elif state == S_NUMBER:
96                                 if not c:
97                                         return self.convert_number(string.join(token, ''))
98                                 if c in ' \t\n;()':
99                                         self.ungetc(c)
100                                         return self.convert_number(string.join(token, ''))
101                                 elif c in '0123456789.eE-':
102                                         token.append(c)
103                                 else:
104                                         return (T_ERROR, '%d: invalid character "%s" while reading integer'
105                                                                                 % (self.line_no, c))
106
107         def parse(self, t=None):
108                 if not t:
109                         (t, v) = self.get_token()
110                 if t == T_OPEN:
111                         l = []
112                         while 1:
113                                 (t, v) = self.get_token()
114                                 if t == T_CLOSE:
115                                         return l
116                                 elif t == T_OPEN:
117                                         v = self.parse(t)
118                                         if v == None:
119                                                 raise SexprError, '%d: unexpected EOF' % self.line_no
120                                 elif t == T_ERROR:
121                                         raise SexprError, v
122                                 elif t == T_EOF:
123                                         raise SexprError, '%d: EOF while inside list' % self.line_no
124                                 l.append(v)
125                 elif t == T_CLOSE:
126                         raise SexprError, '%d: unexpected )' % self.line_no
127                 elif t == T_EOF:
128                         return None
129                 elif t == T_ERROR:
130                         raise SexprError, v
131                 else:
132                         return v
133
134 if __name__ == '__main__':
135         import sys
136         #import profile
137         p = SexprParser(sys.stdin)
138         #profile.run('p.parse()')
139         while 1:
140                 e = p.parse()
141                 print e
142                 if not e:
143                         break
Note: See TracBrowser for help on using the browser.