#! /usr/bin/python import re, sys keywords = 'end', 'template', 'if', 'elif', 'else', 'apply-template', 'include' _templates = {} class THtml: def __init__(self, input, loc, parent = {}): self._liter = iter(input) self._locals = loc self._parent = parent def begin(self): try: line = self._liter.next() while self.recv(line): line = self._liter.next() except StopIteration: pass except: raise return self._liter def recv(self, line): key, exp = _G_meta(line) if key: return self.statement(key, exp) return self.normal(line) def statement(self, key, exp): if key == 'if': exp = eval(_Repl(exp[:exp.rindex(':')], self)) self._liter = If(exp, self._liter, self).begin() elif key == 'template': exp = eval(_Repl(exp[:exp.rindex(':')], self)) txt = [] self._liter = Extract(self._liter, txt).begin() txt.pop() _templates[exp] = txt elif key == 'include': exp = eval(_Repl(exp, self)) THtml(file(exp).readlines(), self).begin() elif key == 'apply-template': exp = eval(_Repl(exp, self)) tval = self.get(exp) if type(tval) == list: for d in tval: THtml(_templates.get(exp, []), d, self).begin() elif type(tval) == dict: THtml(_templates.get(exp, []), tval, self).begin() elif tval != None: raise ValueError, "'%s': type of '{}/[{}*]' expected" % exp return 1 def normal(self, line): sys.stdout.write(_Repl(line, self)) return 1 def __getitem__(self, key): val = self._locals.get(key) if val != None: return val return self._parent[key] def get(self, key): val = self._locals.get(key) if val != None: return val return self._parent.get(key) class Skip(THtml): def __init__(self, input): THtml.__init__(self, input, None) def statement(self, key, exp): if key == 'end': return 0 elif key in ('if', 'template'): self._liter = Skip(self._liter).begin() return 1 def normal(self, line): return 1 class Extract(THtml): def __init__(self, input, lines): THtml.__init__(self, input, None) self._lines = lines def recv(self, line,): self._lines.append(line) return THtml.recv(self, line) def statement(self, key, exp): if key == 'end': return 0 elif key in ('if', 'template'): self._liter = Extract(self._liter, self._lines).begin() return 1 def normal(self, line): return 1 class If(THtml): def __init__(self, bool, input, env): THtml.__init__(self, input, env) self._true = bool def statement(self, key, exp): if key == 'end': return 0 elif key in ('elif', 'else'): if self._true: self._liter = Skip(self._liter).begin() else: if key == 'elif': self._true = eval(_Repl(exp[: exp.rindex(':')], self)) else: self._true = 1 else: if self._true: return THtml.statement(self, key, exp) elif key in ('if', 'template'): self._liter = Skip(self._liter, None).begin() return 1 def normal(self, line): if self._true: THtml.normal(self, line) return 1 #_varname = re.compile('%\((\w+)\)s') def _Repl(txt, dct): #return re.sub(_varname, lambda g: str(dct.get(g.group(1))), txt) return txt % dct _meta = re.compile('^\s*\s*$' % '|'.join(keywords)) def _G_meta(line): res = re.search(_meta, line) if res: return res.group(1, 2) return 0, 0 def fprintf(outf, inf, glob): if type(outf) == str: outf = file(outf, 'w') bak, sys.stdout = sys.stdout, outf THtml(inf, glob).begin() sys.stdout = bak def printf(inf, glob): if type(inf) == str: inf = file(inf) fprintf(sys.stdout, inf, glob) import os def test(): from StringIO import StringIO content = """\ %(name)s %(sex)s %(age)s %(subject)s %(score)s %(name)s %(age)s %(city)s """ 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'] = [] 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 = { 'family_inc' : 'family.inc' } t['age'], t['name'] = r.pop(), r.pop() h['family'].append(t) glob.append(h) return glob glob = test_data() fprintf(sys.stderr, StringIO(content), { 'glob': glob, 'foo': 'wjy' }) try: 1 #printf(StringIO(content), { 'glob' : glob }) except Exception, e: print 'Error:', e if __name__ == '__main__': test()