Exercise 1: A Real {% else %} Branch — Possible Solution ==================================================================== THE EXTENDED IfNode AND parse() ------------------------------ class IfNode: def __init__(self, cond_name, if_body, else_body=None): self.cond_name = cond_name self.if_body = if_body self.else_body = else_body or [] def render(self, ctx): body = self.if_body if ctx.get(self.cond_name) else self.else_body return ''.join(node.render(ctx) for node in body) parse() now has to know WHICH terminator it stopped on -- 'endif', 'endfor', or 'else' -- so an if-block can tell whether to keep parsing a second body for the else branch. It returns a 3-tuple instead of 2: def parse(tokens, index=0): nodes = [] while index < len(tokens): token = tokens[index] if token.startswith('{{'): nodes.append(VarNode(token[2:-2].strip())) index += 1 elif token.startswith('{%'): tag = token[2:-2].strip() if tag.startswith('if '): cond_name = tag[3:].strip() if_body, index, term = parse(tokens, index + 1) else_body = [] if term == 'else': else_body, index, term = parse(tokens, index) nodes.append(IfNode(cond_name, if_body, else_body)) elif tag.startswith('for '): m = re.match(r'for (\w+) in (\w+)', tag) var, coll_name = m.group(1), m.group(2) body, index, term = parse(tokens, index + 1) nodes.append(ForNode(var, coll_name, body)) elif tag in ('endif', 'endfor'): return nodes, index + 1, tag elif tag == 'else': return nodes, index + 1, 'else' else: index += 1 else: nodes.append(TextNode(token)) index += 1 return nodes, index, None def compile_template(source): nodes, _, _ = parse(tokenize(source)) return nodes VERIFIED, REAL RESULT ------------------------------ template = '{% if logged_in %}Welcome back!{% else %}Please log in.{% endif %}' nodes = compile_template(template) render_nodes(nodes, {'logged_in': True}) -> 'Welcome back!' render_nodes(nodes, {'logged_in': False}) -> 'Please log in.' Nested inside a for loop, to confirm else-tracking doesn't get confused by a sibling loop's own endfor: mixed = '{% for user in users %}{% if user %}