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
|
import contextlib
class Codebuilder(object):
def __init__(self):
self.blocks = []
self.code = []
def get_code(self):
assert not self.blocks
return "\n".join([" " * depth + line for depth, line in self.code])
def make_parser(self):
m = {'Status': Status,
'Nonterminal': Nonterminal,
'Symbol': Symbol,}
exec py.code.Source(self.get_code()).compile() in m
return m['Parser']
def emit(self, line):
for line in line.split("\n"):
if line:
self.code.append((len(self.blocks), line))
def emit_initcode(self, line):
for line in line.split("\n"):
self.initcode.append(line)
def start_block(self, blockstarter):
assert blockstarter.endswith(":")
self.emit(blockstarter)
self.blocks.append(blockstarter)
@contextlib.contextmanager
def block(self, blockstarter):
self.start_block(blockstarter)
yield None
self.end_block(blockstarter)
def end_block(self, starterpart=""):
block = self.blocks.pop()
assert starterpart in block, "ended wrong block %s with %s" % (
block, starterpart)
def store_code_away(self):
result = self.blocks, self.code
self.code = []
self.blocks = []
return result
def restore_code(self, (blocks, code)):
result = self.blocks, self.code
self.code = code
self.blocks = blocks
return result
def add_code(self, (blocks, code)):
self.code += [(depth + len(self.blocks), line) for depth, line in code]
self.blocks += blocks
|