-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBraceConverter.py
160 lines (138 loc) · 4.83 KB
/
BraceConverter.py
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
"""BraceConverter.py
Contributed 2000-09-04 by Dave Wallace ([email protected])
Converts Brace-blocked Python into normal indented Python.
Brace-blocked Python is non-indentation aware and blocks are
delimited by ':{' and '}' pairs.
Thus:
for x in range(10) :{
if x%2 :{ print x } else :{ print z }
}
Becomes (roughly, barring some spurious newlines):
for x in range(10) :
if x%2 :
print x
else :
print z
This implementation is fed a line at a time via parseLine(),
outputs to a PSPServletWriter, and tracks the current quotation
and block levels internally.
"""
import re
import sys
class BraceConverter(object):
CSKIP = re.compile("(^[^\"'{}:#]+)")
COLONBRACE = re.compile(":\s*{\s*([^\s].*)?$")
def __init__(self):
self.inquote = False
self.dictlevel = 0
def parseLine(self, line, writer):
"""Parse a line.
The only public method of this class, call with subsequent lines
and an instance of PSPServletWriter.
"""
self.line = line
if self.inquote and self.line:
self.skipquote(writer)
self.line = self.line.lstrip()
if not self.line:
writer.printChars('\n')
return
writer.printIndent()
while self.line:
while self.inquote and self.line:
self.skipquote(writer)
match = self.CSKIP.search(self.line)
if match:
writer.printChars(self.line[:match.end(1)])
self.line = self.line[match.end(1):]
else:
ch = self.line[0]
if ch == "'":
self.handleQuote("'", writer)
self.skipquote(writer)
elif ch == '"':
self.handleQuote('"', writer)
self.skipquote(writer)
elif ch == '{':
self.openBrace(writer)
elif ch == '}':
self.closeBrace(writer)
elif ch == ':':
self.openBlock(writer)
elif ch == '#':
writer.printChars(self.line)
self.line = ''
else:
# should never get here
raise Exception()
else:
writer.printChars('\n')
def openBlock(self, writer):
"""Open a new block."""
match = self.COLONBRACE.match(self.line)
if match and not self.dictlevel:
writer.printChars(':')
writer.pushIndent()
if match.group(1):
# text follows :{, if its a comment leave it on the same line
# else start a new line and leave the text for processing
if match.group(1)[0] == '#':
writer.printChars(' ' + match.group(1))
self.line = ''
else:
writer.printChars('\n')
writer.printIndent()
self.line = match.group(1)
else:
self.line = ''
else:
writer.printChars(':')
self.line = self.line[1:]
def openBrace(self, writer):
"""Open brace encountered."""
writer.printChars('{')
self.line = self.line[1:]
self.dictlevel += 1
def closeBrace(self, writer):
"""Close brace encountered."""
if self.dictlevel:
writer.printChars('}')
self.line = self.line[1:]
self.dictlevel -= 1
else:
writer.popIndent()
self.line = self.line[1:].lstrip()
if self.line:
writer.printChars('\n')
writer.printIndent()
def skipquote(self, writer):
"""Skip to end of quote.
Skip over all chars until the line is exhausted
or the current non-escaped quote sequence is encountered.
"""
pos = self.line.find(self.quotechars)
if pos < 0:
writer.printChars(self.line)
self.line = ''
elif pos > 0 and self.line[pos-1] == '\\':
pos += 1
writer.printChars(self.line[:pos])
self.line = self.line[pos:]
self.skipquote(writer)
else:
pos += len(self.quotechars)
writer.printChars(self.line[:pos])
self.line = self.line[pos:]
self.inquote = False
def handleQuote(self, quote, writer):
"""Check and handle if current pos is a single or triple quote."""
self.inquote = True
triple = quote*3
if self.line[0:3] == triple:
self.quotechars = triple
writer.printChars(triple)
self.line = self.line[3:]
else:
self.quotechars = quote
writer.printChars(quote)
self.line = self.line[1:]