text: define(['exports', '../exception'], function (exports, _exception) {
    'use strict';
  
    var _interopRequire = function (obj) { return obj && obj.__esModule ? obj['default'] : obj; };
  
    exports.__esModule = true;
    exports.SourceLocation = SourceLocation;
    exports.id = id;
    exports.stripFlags = stripFlags;
    exports.stripComment = stripComment;
    exports.preparePath = preparePath;
    exports.prepareMustache = prepareMustache;
    exports.prepareRawBlock = prepareRawBlock;
    exports.prepareBlock = prepareBlock;
  
    var _Exception = _interopRequire(_exception);
  
    function SourceLocation(source, locInfo) {
      this.source = source;
      this.start = {
        line: locInfo.first_line,
        column: locInfo.first_column
      };
      this.end = {
        line: locInfo.last_line,
        column: locInfo.last_column
      };
    }
  
    function id(token) {
      if (/^\[.*\]$/.test(token)) {
        return token.substr(1, token.length - 2);
      } else {
        return token;
      }
    }
  
    function stripFlags(open, close) {
      return {
        open: open.charAt(2) === '~',
        close: close.charAt(close.length - 3) === '~'
      };
    }
  
    function stripComment(comment) {
      return comment.replace(/^\{\{~?\!-?-?/, '').replace(/-?-?~?\}\}$/, '');
    }
  
    function preparePath(data, parts, locInfo) {
      /*jshint -W040 */
      locInfo = this.locInfo(locInfo);
  
      var original = data ? '@' : '',
          dig = [],
          depth = 0,
          depthString = '';
  
      for (var i = 0, l = parts.length; i < l; i++) {
        var part = parts[i].part,
  
        // If we have [] syntax then we do not treat path references as operators,
        // i.e. foo.[this] resolves to approximately context.foo['this']
        isLiteral = parts[i].original !== part;
        original += (parts[i].separator || '') + part;
  
        if (!isLiteral && (part === '..' || part === '.' || part === 'this')) {
          if (dig.length > 0) {
            throw new _Exception('Invalid path: ' + original, { loc: locInfo });
          } else if (part === '..') {
            depth++;
            depthString += '../';
          }
        } else {
          dig.push(part);
        }
      }
  
      return new this.PathExpression(data, depth, dig, original, locInfo);
    }
  
    function prepareMustache(path, params, hash, open, strip, locInfo) {
      /*jshint -W040 */
      // Must use charAt to support IE pre-10
      var escapeFlag = open.charAt(3) || open.charAt(2),
          escaped = escapeFlag !== '{' && escapeFlag !== '&';
  
      return new this.MustacheStatement(path, params, hash, escaped, strip, this.locInfo(locInfo));
    }
  
    function prepareRawBlock(openRawBlock, content, close, locInfo) {
      /*jshint -W040 */
      if (openRawBlock.path.original !== close) {
        var errorNode = { loc: openRawBlock.path.loc };
  
        throw new _Exception(openRawBlock.path.original + ' doesn\'t match ' + close, errorNode);
      }
  
      locInfo = this.locInfo(locInfo);
      var program = new this.Program([content], null, {}, locInfo);
  
      return new this.BlockStatement(openRawBlock.path, openRawBlock.params, openRawBlock.hash, program, undefined, {}, {}, {}, locInfo);
    }
  
    function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) {
      /*jshint -W040 */
      // When we are chaining inverse calls, we will not have a close path
      if (close && close.path && openBlock.path.original !== close.path.original) {
        var errorNode = { loc: openBlock.path.loc };
  
        throw new _Exception(openBlock.path.original + ' doesn\'t match ' + close.path.original, errorNode);
      }
  
      program.blockParams = openBlock.blockParams;
  
      var inverse = undefined,
          inverseStrip = undefined;
  
      if (inverseAndProgram) {
        if (inverseAndProgram.chain) {
          inverseAndProgram.program.body[0].closeStrip = close.strip;
        }
  
        inverseStrip = inverseAndProgram.strip;
        inverse = inverseAndProgram.program;
      }
  
      if (inverted) {
        inverted = inverse;
        inverse = program;
        program = inverted;
      }
  
      return new this.BlockStatement(openBlock.path, openBlock.params, openBlock.hash, program, inverse, openBlock.strip, inverseStrip, close && close.strip, this.locInfo(locInfo));
    }
  });