JavaScript Templates (redux)

In the spirit of code kata (the origional problem was a kata) here is an alternative solution to the JavaScript templating problem:

var template = (function(){
    var grammar = parsec.grammar([
        parsec.token("placeholder", "[$]\\w+"),
        parsec.token("literal", "[^$]+")
    ]);

    with(grammar){
        root("template", placeholder.or(literal).repeated().then(eof));
    }

    return {
        render: function render(source, context){
            var handlers = {
                literal: function(node){
                    return node.v;
                },

                placeholder: function(node){
                    var key = node.v.substring(1);
                    return context[key] || "";
                },

                template: function(node){
                    return $.map(node.children, evaluate).join("");
                }
            };

            function evaluate(node){
                return handlers[node.type](node);
            }

            var root = grammar.parse(source);
            return evaluate(root);
        }
    };
})(parsec.util);

It's a bunch longer. It's not quite ten time's longer, but it's kind of close... and it passes exactly the same test suite and has the same features, so what, if anything is good about it?

For one thing, it uses a completely different approach. It builds a recursive descent parser using a parsing library that I put together that's based on Parsec. The basic idea of Parsec, and other parser combinator libraries, is that you define simple parsers and then compose them into more complicated parsers using combinators. What this means is that, while it is not necessary here, this approach can handle much more complicated languages than the regex based approach.

Oh, and there was one little nugget of joy in there that deserves special mention. You, might have missed it, so I'll show it again:

with(grammar){
    root("template", placeholder.or(literal).repeated().then(eof));
}

That's right, a with statement. I bet you never though you would see somebody actually try to use one of those. Sure, with statements are widely reviled, they are not one of the good parts, and they're dead in EC5 strict mode... but embedded DSLs are one of the places where you're allowed to cheat like there's not tomorrow. 'sides, $.extend(window, grammar); is your other option for scope manipulation and that's just plain evil.