Updated addon repository URL and improved debug output on download
[supertux.git] / tools / sexpr.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2014 Ingo Ruhnke <grumbel@gmail.com>
4 #
5 # This software is provided 'as-is', without any express or implied
6 # warranty. In no event will the authors be held liable for any damages
7 # arising from the use of this software.
8 #
9 # Permission is granted to anyone to use this software for any purpose,
10 # including commercial applications, and to alter it and redistribute it
11 # freely, subject to the following restrictions:
12 #
13 # 1. The origin of this software must not be misrepresented; you must not
14 #    claim that you wrote the original software. If you use this software
15 #    in a product, an acknowledgment in the product documentation would be
16 #    appreciated but is not required.
17 # 2. Altered source versions must be plainly marked as such, and must not be
18 #    misrepresented as being the original software.
19 # 3. This notice may not be removed or altered from any source distribution.
20
21 import re
22 import codecs
23
24 def parse(text):
25     stack = [[]]
26     state = 'list'
27     i = 0
28     line = 1
29     column = 0
30     while i < len(text):
31         c = text[i]
32         if c == '\n':
33             line += 1
34             column = 0
35         else:
36             column += 1
37
38         if state == 'list':
39             if c == '(':
40                 stack.append([])
41             elif c == ')':
42                 stack[-2].append(stack.pop())
43             elif c == "\"":
44                 state = 'string'
45                 atom = ""
46             elif c == ";":
47                 state = 'comment'
48             elif c.isalpha():
49                 state = 'symbol'
50                 atom = c
51             elif c.isdigit():
52                 state = 'number'
53                 atom = c
54             elif c.isspace():
55                 pass
56             else:
57                 raise Exception("%d:%d: error: unexpected character: '%s'" % (line, column, c))
58
59         elif state == 'comment':
60             if c == '\n':
61                 state = 'list'
62             else:
63                 pass
64
65         elif state == 'string':
66             if c == "\\":
67                 i += 1
68                 atom += text[i]
69             elif c == "\"":
70                 stack[-1].append(atom)
71                 state = 'list'
72             else:
73                 atom += c
74
75         elif state == 'number':
76             if not c.isdigit() or c != ".":
77                 stack[-1].append(int(atom))
78                 state = 'list'
79                 i -= 1
80             else:
81                 atom += c
82
83         elif state == 'symbol':
84             if c.isspace() or c == '(' or c == ')':
85                 stack[-1].append(atom)
86                 state = 'list'
87                 i -= 1
88             else:
89                 atom += c
90
91         # print c, stack
92
93         i += 1
94
95     if len(stack) == 1:
96         return stack[0]
97     else:
98         raise Exception("error: list not closed")
99
100 if __name__ == "__main__":
101     print "parsing..."
102     result = parse(r'(() ("bar" foo) ()) () bar ')
103     print "1.", result
104     print "2.", parse(""";;comment
105     ("Hello World" 5 1 123) ("Hello" 123 123 "foobar") ;; comment""")
106     print "3.", parse(r'(8(8)8)')
107     print "4.", parse(r'')
108     print "5.", parse(r'  ')
109     with codecs.open("white.stf", encoding='utf-8') as fin:
110         print "6.", parse(fin.read())
111
112 # EOF #