summaryrefslogtreecommitdiff
path: root/codegen/scmexpr.py
blob: 83f33aa5a0bc8b4fba6cd0741ff94b3a5324c6e7 (plain)
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
#!/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, tuples=None):
	if tuples == None: 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`