Add codegen to the tracked files
[platform/upstream/gst-editing-services.git] / bindings / python / codegen / scmexpr.py
1 #!/usr/bin/env python
2 # -*- Mode: Python; py-indent-offset: 4 -*-
3 from __future__ import generators
4
5 import string
6 import types
7 from cStringIO import StringIO
8
9 class error(Exception):
10     def __init__(self, filename, lineno, msg):
11         Exception.__init__(self, msg)
12         self.filename = filename
13         self.lineno = lineno
14         self.msg = msg
15     def __str__(self):
16         return '%s:%d: error: %s' % (self.filename, self.lineno, self.msg)
17
18 trans = [' '] * 256
19 for i in range(256):
20     if chr(i) in string.letters + string.digits + '_':
21         trans[i] = chr(i)
22     else:
23         trans[i] = '_'
24 trans = string.join(trans, '')
25
26 def parse(filename):
27     if isinstance(filename, str):
28         fp = open(filename, 'r')
29     else: # if not string, assume it is some kind of iterator
30         fp = filename
31         filename = getattr(fp, 'name', '<unknown>')
32     whitespace = ' \t\n\r\x0b\x0c'
33     nonsymbol = whitespace + '();\'"'
34     stack = []
35     openlines = []
36     lineno = 0
37     for line in fp:
38         pos = 0
39         lineno += 1
40         while pos < len(line):
41             if line[pos] in whitespace: # ignore whitespace
42                 pass
43             elif line[pos] == ';': # comment
44                 break
45             elif line[pos:pos+2] == "'(":
46                 pass # the open parenthesis will be handled next iteration
47             elif line[pos] == '(':
48                 stack.append(())
49                 openlines.append(lineno)
50             elif line[pos] == ')':
51                 if len(stack) == 0:
52                     raise error(filename, lineno, 'close parenthesis found when none open')
53                 closed = stack[-1]
54                 del stack[-1]
55                 del openlines[-1]
56                 if stack:
57                     stack[-1] += (closed,)
58                 else:
59                     yield closed
60             elif line[pos] == '"': # quoted string
61                 if not stack:
62                     raise error(filename, lineno,
63                                 'string found outside of s-expression')
64                 endpos = pos + 1
65                 chars = []
66                 while endpos < len(line):
67                     if endpos+1 < len(line) and line[endpos] == '\\':
68                         endpos += 1
69                         if line[endpos] == 'n':
70                             chars.append('\n')
71                         elif line[endpos] == 'r':
72                             chars.append('\r')
73                         elif line[endpos] == 't':
74                             chars.append('\t')
75                         else:
76                             chars.append('\\')
77                             chars.append(line[endpos])
78                     elif line[endpos] == '"':
79                         break
80                     else:
81                         chars.append(line[endpos])
82                     endpos += 1
83                 if endpos >= len(line):
84                     raise error(filename, lineno, "unclosed quoted string")
85                 pos = endpos
86                 stack[-1] += (''.join(chars),)
87             else: # symbol/number
88                 if not stack:
89                     raise error(filename, lineno,
90                                 'identifier found outside of s-expression')
91                 endpos = pos
92                 while endpos < len(line) and line[endpos] not in nonsymbol:
93                     endpos += 1
94                 symbol = line[pos:endpos]
95                 pos = max(pos, endpos-1)
96                 try: symbol = int(symbol)
97                 except ValueError:
98                     try: symbol = float(symbol)
99                     except ValueError: pass
100                 stack[-1] += (symbol,)
101             pos += 1
102     if len(stack) != 0:
103         msg = '%d unclosed parentheses found at end of ' \
104               'file (opened on line(s) %s)' % (len(stack),
105                                                ', '.join(map(str, openlines)))
106         raise error(filename, lineno, msg)
107
108 class Parser:
109     def __init__(self, filename):
110         """Argument is either a string, a parse tree, or file object"""
111         self.filename = filename
112     def startParsing(self, filename=None):
113         statements = parse(filename or self.filename)
114         for statement in statements:
115             self.handle(statement)
116     def handle(self, tup):
117         cmd = string.translate(tup[0], trans)
118         if hasattr(self, cmd):
119             getattr(self, cmd)(*tup[1:])
120         else:
121             self.unknown(tup)
122     def unknown(self, tup):
123         pass
124
125 _testString = """; a scheme file
126 (define-func gdk_font_load    ; a comment at end of line
127   GdkFont
128   ((string name)))
129
130 (define-boxed GdkEvent
131   gdk_event_copy
132   gdk_event_free
133   "sizeof(GdkEvent)")
134 """
135
136 if __name__ == '__main__':
137     import sys
138     if sys.argv[1:]:
139         fp = open(sys.argv[1])
140     else:
141         fp = StringIO(_testString)
142     statements = parse(fp)
143     for s in statements:
144         print `s`