docs: function(input) {
    var code = '';
  
    var unparsedInput = input;
    var unparsedInputLength;
    var output;
  
    do {
      var section = toplevel(unparsedInput);
      unparsedInputLength = unparsedInput.length;
      if (section.zone === null) {
        output = unparsedInput;
        code += '$_write('
          + JSON.stringify(escapeCurly(output, section.escapes))
          + ');\n';
        break;
      }
      var span = unparsedInput.slice(section.zone.from + 2, section.zone.to - 2);
      var params = zoneParser(span);    // Fragment the parameters.
      var macro = params[0];
  
      output = unparsedInput.slice(0, section.zone.from);
      code += '$_write('
        + JSON.stringify(escapeCurly(output, section.escapes))
        + ');\n';
  
      // If the macro is not present, print the zone directly.
      if (macros[macro] === undefined) {
        output = unparsedInput.slice(section.zone.from, section.zone.to);
        code += '$_write('
          + JSON.stringify(escapeCurly(output, section.escapes))
          + ');\n';
        unparsedInput = unparsedInput.slice(section.zone.to);
        continue;
      }
      // If the macro is empty, this is code.
      if (macro === "") {
        code += params.slice(1).join('') + '\n';
        unparsedInput = unparsedInput.slice(section.zone.to);
        continue;
      }
  
      // Call the macro.
      var errmsg = JSON.stringify([
        'Template error: macro "MACRO" didn\'t work.',
        'Parameters: PARAMS',
        'Literal: LITERAL',
        'Message: MESSAGE'
      ].join('\n'))
       .replace('MACRO', '" + ' + JSON.stringify(macro) + ' + "')
       .replace('MESSAGE', '" + e.message + "')
       .replace('PARAMS', '" + ' + JSON.stringify(params.slice(1)) + ' + "')
       .replace('LITERAL', '" + $_scopestr + "');
      var macrocode = macros[macro](params.slice(1));
      code += [
        'try {',
        '  ' + macrocode,
        '} catch(e) {',
        '  try {',
        '    var $_scopestr = JSON.stringify($_scope);',
        '  } catch(e) { var $_scopestr = Object.keys($_scope).join(" "); }',
        '  throw Error (' + errmsg + ');',
        '}'
      ].join('\n');
  
      unparsedInput = unparsedInput.slice(section.zone.to);
    } while (section.zone.to < unparsedInputLength);
  
    return code;
  }