#! /usr/bin/python
import re, sys
keywords = 'end', 'template', 'if', 'elif', 'else', 'apply-template', 'include'
_varname = re.compile('%{(\w+)}')
_meta = re.compile('^\s*\s*$' % '|'.join(keywords))
_templates = {}
class THtml:
def __init__(self, src):
self._liter = iter(src)
def begin(self, dct):
try:
while self.recv(self._liter.next(), dct): pass
except StopIteration:
pass
return self._liter
def recv(self, line, dct):
key, exp = _G_meta(line)
if key:
return self.statement(key, exp, dct)
return self.normal(line, dct)
def statement(self, key, exp, dct):
if key == 'if':
exp = eval(_G_repl(exp[:exp.rindex(':')], dct))
self._liter = If(exp, self._liter).begin(dct)
elif key == 'template':
exp = eval(_G_repl(exp[:exp.rindex(':')], dct))
txt = []
self._liter = Extract(self._liter, txt).begin(dct)
txt.pop()
_templates[exp] = txt
elif key == 'include':
exp = eval(_G_repl(exp, dct))
THtml(file(exp).readlines()).begin(dct)
elif key == 'apply-template':
exp = eval(_G_repl(exp, dct))
tval = dct.get(exp, {})
if type(tval) == list:
for d in tval:
THtml(_templates.get(exp, [])).begin(d)
elif type(tval) == dict:
THtml(_templates.get(exp, [])).begin(tval)
elif tval != None:
raise ValueError, "'%s': type of '{}/[{}*]' expected" % exp
else: assert 0, 'Unknown keyword: ' + key
return 1
def normal(self, line, dct):
sys.stdout.write(_G_repl(line, dct))
return 1
class Skip(THtml):
def __init__(self, src):
THtml.__init__(self, src)
def statement(self, key, exp, dct):
if key == 'end':
return 0
elif key in ('if', 'template'):
self._liter = Skip(self._liter).begin(dct)
return 1
def normal(self, line, dct):
return 1
class Extract(THtml):
def __init__(self, src, lines):
THtml.__init__(self, src)
self._lines = lines
def recv(self, line, dct):
self._lines.append(line)
return THtml.recv(self, line, dct)
def statement(self, key, exp, dct):
if key == 'end':
return 0
elif key in ('if', 'template'):
self._liter = Extract(self._liter, self._lines).begin(dct)
return 1
def normal(self, line, dct):
return 1
class If(THtml):
def __init__(self, bool, src):
THtml.__init__(self, src)
self._true = bool
def statement(self, key, exp, dct):
if key == 'end':
return 0
elif key in ('elif', 'else'):
if self._true:
self._liter = Skip(self._liter).begin(dct)
else:
if key == 'elif':
self._true = eval(_G_repl((exp[: exp.rindex(':')]), dct))
else:
self._true = 1
else:
if self._true:
return THtml.statement(self, key, exp, dct)
elif key in ('if', 'template'):
self._liter = Skip(self._liter).begin(dct)
return 1
def normal(self, line, dct):
if self._true:
THtml.normal(self, line, dct)
return 1
def _G_repl(txt, dct):
return re.sub(_varname, lambda g: str(dct.get(g.group(1))), txt)
def _G_meta(line):
res = re.search(_meta, line)
if res:
return res.group(1, 2)
return 0, 0
def fprintf(outf, filename, glob):
bak, sys.stdout = sys.stdout, outf
printf(filename, glob)
sys.stdout = bak
def printf(inf, glob):
if type(inf) == str:
inf = file(inf)
THtml(inf).begin(glob)
import os
def test():
from StringIO import StringIO
content = """\
%{name}
%{sex}
%{age}
%{subject}
%{score}
%{name}
%{age}
%{inc_file}
%{city}
"""
def test_data():
data = """\
Xiaoyu * female * 20 * english 80 maths 88 chinese 92 * song 44 yang 45 * Beijing * ()
wu * male * 20 * c/c++ 8 maths 8 listening 9 * wu 4 wei 5 * ShenZhen * ()
"""
glob = []
for line in data.splitlines():
h = {}
v = [x.strip() for x in line.rstrip().split('*')][:-1]
h['name'], h['sex'], h['age'], result_exam, family, h['city'] = v
h['result_exam'] = [{None: None}]
if result_exam:
r = result_exam.split()
while r:
t = {}
t['score'], t['subject'] = r.pop(), r.pop()
h['result_exam'].append(t)
h['family'] = []
if family:
r = family.split()
while r:
t = { 'inc_file' : 'family.inc' }
t['age'], t['name'] = r.pop(), r.pop()
h['family'].append(t)
glob.append(h)
return glob
glob = test_data()
try:
fprintf(sys.stdout, StringIO(content).readlines(), { 'glob' : glob })
except Exception, e:
print 'Error:', e
if __name__ == '__main__':
test()