define(
  ["exports"],
  function(__exports__) {
    "use strict";
    var AST = {
      Program: function(statements, blockParams, strip, locInfo) {
        this.loc = locInfo;
        this.type = 'Program';
        this.body = statements;

        this.blockParams = blockParams;
        this.strip = strip;
      },

      MustacheStatement: function(path, params, hash, escaped, strip, locInfo) {
        this.loc = locInfo;
        this.type = 'MustacheStatement';

        this.path = path;
        this.params = params || [];
        this.hash = hash;
        this.escaped = escaped;

        this.strip = strip;
      },

      BlockStatement: function(path, params, hash, program, inverse, openStrip, inverseStrip, closeStrip, locInfo) {
        this.loc = locInfo;
        this.type = 'BlockStatement';

        this.path = path;
        this.params = params || [];
        this.hash = hash;
        this.program  = program;
        this.inverse  = inverse;

        this.openStrip = openStrip;
        this.inverseStrip = inverseStrip;
        this.closeStrip = closeStrip;
      },

      PartialStatement: function(name, params, hash, strip, locInfo) {
        this.loc = locInfo;
        this.type = 'PartialStatement';

        this.name = name;
        this.params = params || [];
        this.hash = hash;

        this.indent = '';
        this.strip = strip;
      },

      ContentStatement: function(string, locInfo) {
        this.loc = locInfo;
        this.type = 'ContentStatement';
        this.original = this.value = string;
      },

      CommentStatement: function(comment, strip, locInfo) {
        this.loc = locInfo;
        this.type = 'CommentStatement';
        this.value = comment;

        this.strip = strip;
      },

      SubExpression: function(path, params, hash, locInfo) {
        this.loc = locInfo;

        this.type = 'SubExpression';
        this.path = path;
        this.params = params || [];
        this.hash = hash;
      },

      PathExpression: function(data, depth, parts, original, locInfo) {
        this.loc = locInfo;
        this.type = 'PathExpression';

        this.data = data;
        this.original = original;
        this.parts    = parts;
        this.depth    = depth;
      },

      StringLiteral: function(string, locInfo) {
        this.loc = locInfo;
        this.type = 'StringLiteral';
        this.original =
          this.value = string;
      },

      NumberLiteral: function(number, locInfo) {
        this.loc = locInfo;
        this.type = 'NumberLiteral';
        this.original =
          this.value = Number(number);
      },

      BooleanLiteral: function(bool, locInfo) {
        this.loc = locInfo;
        this.type = 'BooleanLiteral';
        this.original =
          this.value = bool === 'true';
      },

      Hash: function(pairs, locInfo) {
        this.loc = locInfo;
        this.type = 'Hash';
        this.pairs = pairs;
      },
      HashPair: function(key, value, locInfo) {
        this.loc = locInfo;
        this.type = 'HashPair';
        this.key = key;
        this.value = value;
      },

      // Public API used to evaluate derived attributes regarding AST nodes
      helpers: {
        // a mustache is definitely a helper if:
        // * it is an eligible helper, and
        // * it has at least one parameter or hash segment
        // TODO: Make these public utility methods
        helperExpression: function(node) {
          return !!(node.type === 'SubExpression' || node.params.length || node.hash);
        },

        scopedId: function(path) {
          return (/^\.|this\b/).test(path.original);
        },

        // an ID is simple if it only has one part, and that part is not
        // `..` or `this`.
        simpleId: function(path) {
          return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth;
        }
      }
    };


    // Must be exported as an object rather than the root of the module as the jison lexer
    // must modify the object to operate properly.
    __exports__["default"] = AST;
  });