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
|
#!/usr/bin/env python
# -*- Mode: Python; py-indent-offset: 4 -*-
import string
import types
# get the fastest implementation of StringIO
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
trans = [' '] * 256
for i in range(256):
if chr(i) in string.letters + string.digits + '_':
trans[i] = chr(i)
else:
trans[i] = '_'
trans = string.join(trans, '')
def parse(fp):
stack = [()]
line = fp.readline()
while line:
while line:
line = string.lstrip(line)
if not line:
break
elif line[0] == '(':
stack.append(())
line = line[1:]
elif line[0] == ')':
closed = stack[-1]
del stack[-1]
stack[-1] = stack[-1] + (closed,)
line = line[1:]
elif line[0] == '"':
pos = string.index(line[1:], '"')
stack[-1] = stack[-1] + (eval(line[:pos+2]),)
line = line[pos+2:]
elif line[0] in string.digits:
str = ""
while line and line[0] in "0123456789+-.":
str = str + line[0]
line = line[1:]
stack[-1] = stack[-1] + (string.atof(str),)
elif line[0] == ';':
break
elif line[0] == "'":
line = line[1:] # consume single quote
else:
str = ""
while line and line[0] not in "(); '\t\r\n":
str = str + line[0]
line = line[1:]
stack[-1] = stack[-1] + (str,)
line = fp.readline()
if len(stack) != 1:
raise IOError, "parentheses don't match"
return stack[0]
class Parser:
def __init__(self, arg):
"""Argument is either a string, a parse tree, or file object"""
if type(arg) == types.StringType:
self.filename = arg
self.parseTree = parse(open(arg))
elif type(arg) == types.TupleType:
self.filename = '<none>'
self.parseTree = arg
elif type(arg) == types.FileType:
self.filename = arg.name
self.parseTree = parse(arg)
else:
raise TypeError, 'second arg must be string, tuple or file'
def startParsing(self, arg=None):
if type(arg) == types.StringType:
tuples = parse(open(arg))
elif arg:
tuples = arg
else:
tuples = self.parseTree
for tup in tuples:
self.handle(tup)
def handle(self, tup):
cmd = string.translate(tup[0], trans)
if hasattr(self, cmd):
apply(getattr(self, cmd), tup[1:])
else:
self.unknown(tup)
def unknown(self, tup):
pass
_testString = """; a scheme file
(define-func gdk_font_load ; a comment at end of line
GdkFont
((string name)))
(define-boxed GdkEvent
gdk_event_copy
gdk_event_free
"sizeof(GdkEvent)")
"""
if __name__ == '__main__':
import sys
if sys.argv[1:]:
fp = open(sys.argv[1])
else:
fp = StringIO(_testString)
statements = parse(fp)
for s in statements:
print `s`
|