#!/usr/bin/env python2.7 from __future__ import print_function import sys import re import json def debug(obj): print(json.dumps(obj, indent=4)) def parse_file(fn): text = open(fn).read() tags = re.findall('{+\s*(.*?)\s*}+', text) root = {} context = root stack = [] def set_var(var, val): num_levels_up = len(re.findall('\.\.', var)) if num_levels_up: var = var.split('/')[-1] stack[-1 * num_levels_up][var] = val else: context[var] = val for tag in tags: if tag.startswith('! '): continue if tag == 'else': continue if tag[0] in '#^' and ' ' not in tag: var = tag[1:] set_var(var, True) stack.append(context) continue if tag.startswith('#if'): vars = tag.split()[1:] for var in vars: set_var(var, True) stack.append(context) continue if tag.startswith('/if'): context = stack.pop() continue if tag.startswith('#with '): var = tag.split()[1] new_context = {} context[var] = new_context stack.append(context) context = new_context continue if tag.startswith('/with'): context = stack.pop() continue if tag.startswith('#unless '): var = tag.split()[1] set_var(var, True) stack.append(context) continue if tag.startswith('/unless'): context = stack.pop() continue if tag.startswith('#each '): var = tag.split()[1] new_context = {} context[var] = [new_context] stack.append(context) context = new_context continue if tag.startswith('/each'): context = stack.pop() continue if tag.startswith('/'): context = stack.pop() continue set_var(tag, '') def clean_this(obj): if isinstance(obj, list): return [clean_this(item) for item in obj] if isinstance(obj, dict): if len(obj) == 1 and 'this' in obj: return clean_this(obj['this']) return {k: clean_this(v) for k, v in obj.items()} return obj root = clean_this(root) return root if __name__ == '__main__': for fn in sys.argv[1:]: print('===', fn) root = parse_file(fn) debug(root) print()