text: // Generated by CoffeeScript 1.7.1
  var Inline, ParseException, Parser, Pattern, Utils;
  
  Inline = require('./Inline');
  
  Pattern = require('./Pattern');
  
  Utils = require('./Utils');
  
  ParseException = require('./Exception/ParseException');
  
  Parser = (function() {
    Parser.prototype.PATTERN_FOLDED_SCALAR_ALL = new Pattern('^(?:(?<type>![^\\|>]*)\\s+)?(?<separator>\\||>)(?<modifiers>\\+|\\-|\\d+|\\+\\d+|\\-\\d+|\\d+\\+|\\d+\\-)?(?<comments> +#.*)?$');
  
    Parser.prototype.PATTERN_FOLDED_SCALAR_END = new Pattern('(?<separator>\\||>)(?<modifiers>\\+|\\-|\\d+|\\+\\d+|\\-\\d+|\\d+\\+|\\d+\\-)?(?<comments> +#.*)?$');
  
    Parser.prototype.PATTERN_SEQUENCE_ITEM = new Pattern('^\\-((?<leadspaces>\\s+)(?<value>.+?))?\\s*$');
  
    Parser.prototype.PATTERN_ANCHOR_VALUE = new Pattern('^&(?<ref>[^ ]+) *(?<value>.*)');
  
    Parser.prototype.PATTERN_COMPACT_NOTATION = new Pattern('^(?<key>' + Inline.REGEX_QUOTED_STRING + '|[^ \'"\\{\\[].*?) *\\:(\\s+(?<value>.+?))?\\s*$');
  
    Parser.prototype.PATTERN_MAPPING_ITEM = new Pattern('^(?<key>' + Inline.REGEX_QUOTED_STRING + '|[^ \'"\\[\\{].*?) *\\:(\\s+(?<value>.+?))?\\s*$');
  
    Parser.prototype.PATTERN_DECIMAL = new Pattern('\\d+');
  
    Parser.prototype.PATTERN_INDENT_SPACES = new Pattern('^ +');
  
    Parser.prototype.PATTERN_TRAILING_LINES = new Pattern('(\n*)$');
  
    Parser.prototype.PATTERN_YAML_HEADER = new Pattern('^\\%YAML[: ][\\d\\.]+.*\n');
  
    Parser.prototype.PATTERN_LEADING_COMMENTS = new Pattern('^(\\#.*?\n)+');
  
    Parser.prototype.PATTERN_DOCUMENT_MARKER_START = new Pattern('^\\-\\-\\-.*?\n');
  
    Parser.prototype.PATTERN_DOCUMENT_MARKER_END = new Pattern('^\\.\\.\\.\\s*$');
  
    Parser.prototype.PATTERN_FOLDED_SCALAR_BY_INDENTATION = {};
  
    Parser.prototype.CONTEXT_NONE = 0;
  
    Parser.prototype.CONTEXT_SEQUENCE = 1;
  
    Parser.prototype.CONTEXT_MAPPING = 2;
  
    function Parser(offset) {
      this.offset = offset != null ? offset : 0;
      this.lines = [];
      this.currentLineNb = -1;
      this.currentLine = '';
      this.refs = {};
    }
  
    Parser.prototype.parse = function(value, exceptionOnInvalidType, objectDecoder) {
      var alias, allowOverwrite, block, c, context, data, e, first, i, indent, isRef, k, key, lastKey, lineCount, matches, mergeNode, parsed, parsedItem, parser, refName, refValue, val, values, _i, _j, _k, _l, _len, _len1, _len2, _len3, _name, _ref, _ref1, _ref2;
      if (exceptionOnInvalidType == null) {
        exceptionOnInvalidType = false;
      }
      if (objectDecoder == null) {
        objectDecoder = null;
      }
      this.currentLineNb = -1;
      this.currentLine = '';
      this.lines = this.cleanup(value).split("\n");
      data = null;
      context = this.CONTEXT_NONE;
      allowOverwrite = false;
      while (this.moveToNextLine()) {
        if (this.isCurrentLineEmpty()) {
          continue;
        }
        if ("\t" === this.currentLine[0]) {
          throw new ParseException('A YAML file cannot contain tabs as indentation.', this.getRealCurrentLineNb() + 1, this.currentLine);
        }
        isRef = mergeNode = false;
        if (values = this.PATTERN_SEQUENCE_ITEM.exec(this.currentLine)) {
          if (this.CONTEXT_MAPPING === context) {
            throw new ParseException('You cannot define a sequence item when in a mapping');
          }
          context = this.CONTEXT_SEQUENCE;
          if (data == null) {
            data = [];
          }
          if ((values.value != null) && (matches = this.PATTERN_ANCHOR_VALUE.exec(values.value))) {
            isRef = matches.ref;
            values.value = matches.value;
          }
          if (!(values.value != null) || '' === Utils.trim(values.value, ' ') || Utils.ltrim(values.value, ' ').indexOf('#') === 0) {
            if (this.currentLineNb < this.lines.length - 1 && !this.isNextLineUnIndentedCollection()) {
              c = this.getRealCurrentLineNb() + 1;
              parser = new Parser(c);
              parser.refs = this.refs;
              data.push(parser.parse(this.getNextEmbedBlock(null, true), exceptionOnInvalidType, objectDecoder));
            } else {
              data.push(null);
            }
          } else {
            if (((_ref = values.leadspaces) != null ? _ref.length : void 0) && (matches = this.PATTERN_COMPACT_NOTATION.exec(values.value))) {
              c = this.getRealCurrentLineNb();
              parser = new Parser(c);
              parser.refs = this.refs;
              block = values.value;
              indent = this.getCurrentLineIndentation();
              if (this.isNextLineIndented(false)) {
                block += "\n" + this.getNextEmbedBlock(indent + values.leadspaces.length + 1, true);
              }
              data.push(parser.parse(block, exceptionOnInvalidType, objectDecoder));
            } else {
              data.push(this.parseValue(values.value, exceptionOnInvalidType, objectDecoder));
            }
          }
        } else if ((values = this.PATTERN_MAPPING_ITEM.exec(this.currentLine)) && values.key.indexOf(' #') === -1) {
          if (this.CONTEXT_SEQUENCE === context) {
            throw new ParseException('You cannot define a mapping item when in a sequence');
          }
          context = this.CONTEXT_MAPPING;
          if (data == null) {
            data = {};
          }
          Inline.configure(exceptionOnInvalidType, objectDecoder);
          try {
            key = Inline.parseScalar(values.key);
          } catch (_error) {
            e = _error;
            e.parsedLine = this.getRealCurrentLineNb() + 1;
            e.snippet = this.currentLine;
            throw e;
          }
          if ('<<' === key) {
            mergeNode = true;
            allowOverwrite = true;
            if (((_ref1 = values.value) != null ? _ref1.indexOf('*') : void 0) === 0) {
              refName = values.value.slice(1);
              if (this.refs[refName] == null) {
                throw new ParseException('Reference "' + refName + '" does not exist.', this.getRealCurrentLineNb() + 1, this.currentLine);
              }
              refValue = this.refs[refName];
              if (typeof refValue !== 'object') {
                throw new ParseException('YAML merge keys used with a scalar value instead of an object.', this.getRealCurrentLineNb() + 1, this.currentLine);
              }
              if (refValue instanceof Array) {
                for (i = _i = 0, _len = refValue.length; _i < _len; i = ++_i) {
                  value = refValue[i];
                  if (data[_name = String(i)] == null) {
                    data[_name] = value;
                  }
                }
              } else {
                for (key in refValue) {
                  value = refValue[key];
                  if (data[key] == null) {
                    data[key] = value;
                  }
                }
              }
            } else {
              if ((values.value != null) && values.value !== '') {
                value = values.value;
              } else {
                value = this.getNextEmbedBlock();
              }
              c = this.getRealCurrentLineNb() + 1;
              parser = new Parser(c);
              parser.refs = this.refs;
              parsed = parser.parse(value, exceptionOnInvalidType);
              if (typeof parsed !== 'object') {
                throw new ParseException('YAML merge keys used with a scalar value instead of an object.', this.getRealCurrentLineNb() + 1, this.currentLine);
              }
              if (parsed instanceof Array) {
                for (_j = 0, _len1 = parsed.length; _j < _len1; _j++) {
                  parsedItem = parsed[_j];
                  if (typeof parsedItem !== 'object') {
                    throw new ParseException('Merge items must be objects.', this.getRealCurrentLineNb() + 1, parsedItem);
                  }
                  if (parsedItem instanceof Array) {
                    for (i = _k = 0, _len2 = parsedItem.length; _k < _len2; i = ++_k) {
                      value = parsedItem[i];
                      k = String(i);
                      if (!data.hasOwnProperty(k)) {
                        data[k] = value;
                      }
                    }
                  } else {
                    for (key in parsedItem) {
                      value = parsedItem[key];
                      if (!data.hasOwnProperty(key)) {
                        data[key] = value;
                      }
                    }
                  }
                }
              } else {
                for (key in parsed) {
                  value = parsed[key];
                  if (!data.hasOwnProperty(key)) {
                    data[key] = value;
                  }
                }
              }
            }
          } else if ((values.value != null) && (matches = this.PATTERN_ANCHOR_VALUE.exec(values.value))) {
            isRef = matches.ref;
            values.value = matches.value;
          }
          if (mergeNode) {
  
          } else if (!(values.value != null) || '' === Utils.trim(values.value, ' ') || Utils.ltrim(values.value, ' ').indexOf('#') === 0) {
            if (!(this.isNextLineIndented()) && !(this.isNextLineUnIndentedCollection())) {
              if (allowOverwrite || data[key] === void 0) {
                data[key] = null;
              }
            } else {
              c = this.getRealCurrentLineNb() + 1;
              parser = new Parser(c);
              parser.refs = this.refs;
              val = parser.parse(this.getNextEmbedBlock(), exceptionOnInvalidType, objectDecoder);
              if (allowOverwrite || data[key] === void 0) {
                data[key] = val;
              }
            }
          } else {
            val = this.parseValue(values.value, exceptionOnInvalidType, objectDecoder);
            if (allowOverwrite || data[key] === void 0) {
              data[key] = val;
            }
          }
        } else {
          lineCount = this.lines.length;
          if (1 === lineCount || (2 === lineCount && Utils.isEmpty(this.lines[1]))) {
            try {
              value = Inline.parse(this.lines[0], exceptionOnInvalidType, objectDecoder);
            } catch (_error) {
              e = _error;
              e.parsedLine = this.getRealCurrentLineNb() + 1;
              e.snippet = this.currentLine;
              throw e;
            }
            if (typeof value === 'object') {
              if (value instanceof Array) {
                first = value[0];
              } else {
                for (key in value) {
                  first = value[key];
                  break;
                }
              }
              if (typeof first === 'string' && first.indexOf('*') === 0) {
                data = [];
                for (_l = 0, _len3 = value.length; _l < _len3; _l++) {
                  alias = value[_l];
                  data.push(this.refs[alias.slice(1)]);
                }
                value = data;
              }
            }
            return value;
          } else if ((_ref2 = Utils.ltrim(value).charAt(0)) === '[' || _ref2 === '{') {
            try {
              return Inline.parse(value, exceptionOnInvalidType, objectDecoder);
            } catch (_error) {
              e = _error;
              e.parsedLine = this.getRealCurrentLineNb() + 1;
              e.snippet = this.currentLine;
              throw e;
            }
          }
          throw new ParseException('Unable to parse.', this.getRealCurrentLineNb() + 1, this.currentLine);
        }
        if (isRef) {
          if (data instanceof Array) {
            this.refs[isRef] = data[data.length - 1];
          } else {
            lastKey = null;
            for (key in data) {
              lastKey = key;
            }
            this.refs[isRef] = data[lastKey];
          }
        }
      }
      if (Utils.isEmpty(data)) {
        return null;
      } else {
        return data;
      }
    };
  
    Parser.prototype.getRealCurrentLineNb = function() {
      return this.currentLineNb + this.offset;
    };
  
    Parser.prototype.getCurrentLineIndentation = function() {
      return this.currentLine.length - Utils.ltrim(this.currentLine, ' ').length;
    };
  
    Parser.prototype.getNextEmbedBlock = function(indentation, includeUnindentedCollection) {
      var data, indent, isItUnindentedCollection, newIndent, removeComments, removeCommentsPattern, unindentedEmbedBlock;
      if (indentation == null) {
        indentation = null;
      }
      if (includeUnindentedCollection == null) {
        includeUnindentedCollection = false;
      }
      this.moveToNextLine();
      if (indentation == null) {
        newIndent = this.getCurrentLineIndentation();
        unindentedEmbedBlock = this.isStringUnIndentedCollectionItem(this.currentLine);
        if (!(this.isCurrentLineEmpty()) && 0 === newIndent && !unindentedEmbedBlock) {
          throw new ParseException('Indentation problem.', this.getRealCurrentLineNb() + 1, this.currentLine);
        }
      } else {
        newIndent = indentation;
      }
      data = [this.currentLine.slice(newIndent)];
      if (!includeUnindentedCollection) {
        isItUnindentedCollection = this.isStringUnIndentedCollectionItem(this.currentLine);
      }
      removeCommentsPattern = this.PATTERN_FOLDED_SCALAR_END;
      removeComments = !removeCommentsPattern.test(this.currentLine);
      while (this.moveToNextLine()) {
        indent = this.getCurrentLineIndentation();
        if (indent === newIndent) {
          removeComments = !removeCommentsPattern.test(this.currentLine);
        }
        if (isItUnindentedCollection && !this.isStringUnIndentedCollectionItem(this.currentLine) && indent === newIndent) {
          this.moveToPreviousLine();
          break;
        }
        if (this.isCurrentLineBlank()) {
          data.push(this.currentLine.slice(newIndent));
          continue;
        }
        if (removeComments && this.isCurrentLineComment()) {
          if (indent === newIndent) {
            continue;
          }
        }
        if (indent >= newIndent) {
          data.push(this.currentLine.slice(newIndent));
        } else if (0 === indent) {
          this.moveToPreviousLine();
          break;
        } else {
          throw new ParseException('Indentation problem.', this.getRealCurrentLineNb() + 1, this.currentLine);
        }
      }
      return data.join("\n");
    };
  
    Parser.prototype.moveToNextLine = function() {
      if (this.currentLineNb >= this.lines.length - 1) {
        return false;
      }
      this.currentLine = this.lines[++this.currentLineNb];
      return true;
    };
  
    Parser.prototype.moveToPreviousLine = function() {
      this.currentLine = this.lines[--this.currentLineNb];
    };
  
    Parser.prototype.parseValue = function(value, exceptionOnInvalidType, objectDecoder) {
      var e, foldedIndent, matches, modifiers, pos, val, _ref, _ref1;
      if (0 === value.indexOf('*')) {
        pos = value.indexOf('#');
        if (pos !== -1) {
          value = value.substr(1, pos - 2);
        } else {
          value = value.slice(1);
        }
        if (this.refs[value] === void 0) {
          throw new ParseException('Reference "' + value + '" does not exist.', this.currentLine);
        }
        return this.refs[value];
      }
      if (matches = this.PATTERN_FOLDED_SCALAR_ALL.exec(value)) {
        modifiers = (_ref = matches.modifiers) != null ? _ref : '';
        foldedIndent = Math.abs(parseInt(modifiers));
        if (isNaN(foldedIndent)) {
          foldedIndent = 0;
        }
        val = this.parseFoldedScalar(matches.separator, this.PATTERN_DECIMAL.replace(modifiers, ''), foldedIndent);
        if (matches.type != null) {
          Inline.configure(exceptionOnInvalidType, objectDecoder);
          return Inline.parseScalar(matches.type + ' ' + val);
        } else {
          return val;
        }
      }
      try {
        return Inline.parse(value, exceptionOnInvalidType, objectDecoder);
      } catch (_error) {
        e = _error;
        if (((_ref1 = value.charAt(0)) === '[' || _ref1 === '{') && e instanceof ParseException && this.isNextLineIndented()) {
          value += "\n" + this.getNextEmbedBlock();
          try {
            return Inline.parse(value, exceptionOnInvalidType, objectDecoder);
          } catch (_error) {
            e = _error;
            e.parsedLine = this.getRealCurrentLineNb() + 1;
            e.snippet = this.currentLine;
            throw e;
          }
        } else {
          e.parsedLine = this.getRealCurrentLineNb() + 1;
          e.snippet = this.currentLine;
          throw e;
        }
      }
    };
  
    Parser.prototype.parseFoldedScalar = function(separator, indicator, indentation) {
      var isCurrentLineBlank, line, matches, newText, notEOF, pattern, text, _i, _len, _ref;
      if (indicator == null) {
        indicator = '';
      }
      if (indentation == null) {
        indentation = 0;
      }
      notEOF = this.moveToNextLine();
      if (!notEOF) {
        return '';
      }
      isCurrentLineBlank = this.isCurrentLineBlank();
      text = '';
      while (notEOF && isCurrentLineBlank) {
        if (notEOF = this.moveToNextLine()) {
          text += "\n";
          isCurrentLineBlank = this.isCurrentLineBlank();
        }
      }
      if (0 === indentation) {
        if (matches = this.PATTERN_INDENT_SPACES.exec(this.currentLine)) {
          indentation = matches[0].length;
        }
      }
      if (indentation > 0) {
        pattern = this.PATTERN_FOLDED_SCALAR_BY_INDENTATION[indentation];
        if (pattern == null) {
          pattern = new Pattern('^ {' + indentation + '}(.*)$');
          Parser.prototype.PATTERN_FOLDED_SCALAR_BY_INDENTATION[indentation] = pattern;
        }
        while (notEOF && (isCurrentLineBlank || (matches = pattern.exec(this.currentLine)))) {
          if (isCurrentLineBlank) {
            text += this.currentLine.slice(indentation);
          } else {
            text += matches[1];
          }
          if (notEOF = this.moveToNextLine()) {
            text += "\n";
            isCurrentLineBlank = this.isCurrentLineBlank();
          }
        }
      } else if (notEOF) {
        text += "\n";
      }
      if (notEOF) {
        this.moveToPreviousLine();
      }
      if ('>' === separator) {
        newText = '';
        _ref = text.split("\n");
        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
          line = _ref[_i];
          if (line.length === 0 || line.charAt(0) === ' ') {
            newText = Utils.rtrim(newText, ' ') + line + "\n";
          } else {
            newText += line + ' ';
          }
        }
        text = newText;
      }
      if ('+' !== indicator) {
        text = Utils.rtrim(text);
      }
      if ('' === indicator) {
        text = this.PATTERN_TRAILING_LINES.replace(text, "\n");
      } else if ('-' === indicator) {
        text = this.PATTERN_TRAILING_LINES.replace(text, '');
      }
      return text;
    };
  
    Parser.prototype.isNextLineIndented = function(ignoreComments) {
      var EOF, currentIndentation, ret;
      if (ignoreComments == null) {
        ignoreComments = true;
      }
      currentIndentation = this.getCurrentLineIndentation();
      EOF = !this.moveToNextLine();
      if (ignoreComments) {
        while (!EOF && this.isCurrentLineEmpty()) {
          EOF = !this.moveToNextLine();
        }
      } else {
        while (!EOF && this.isCurrentLineBlank()) {
          EOF = !this.moveToNextLine();
        }
      }
      if (EOF) {
        return false;
      }
      ret = false;
      if (this.getCurrentLineIndentation() > currentIndentation) {
        ret = true;
      }
      this.moveToPreviousLine();
      return ret;
    };
  
    Parser.prototype.isCurrentLineEmpty = function() {
      var trimmedLine;
      trimmedLine = Utils.trim(this.currentLine, ' ');
      return trimmedLine.length === 0 || trimmedLine.charAt(0) === '#';
    };
  
    Parser.prototype.isCurrentLineBlank = function() {
      return '' === Utils.trim(this.currentLine, ' ');
    };
  
    Parser.prototype.isCurrentLineComment = function() {
      var ltrimmedLine;
      ltrimmedLine = Utils.ltrim(this.currentLine, ' ');
      return ltrimmedLine.charAt(0) === '#';
    };
  
    Parser.prototype.cleanup = function(value) {
      var count, trimmedValue, _ref, _ref1, _ref2;
      if (value.indexOf("\r") !== -1) {
        value = value.split("\r\n").join("\n").split("\r").join("\n");
      }
      count = 0;
      _ref = this.PATTERN_YAML_HEADER.replaceAll(value, ''), value = _ref[0], count = _ref[1];
      this.offset += count;
      _ref1 = this.PATTERN_LEADING_COMMENTS.replaceAll(value, '', 1), trimmedValue = _ref1[0], count = _ref1[1];
      if (count === 1) {
        this.offset += Utils.subStrCount(value, "\n") - Utils.subStrCount(trimmedValue, "\n");
        value = trimmedValue;
      }
      _ref2 = this.PATTERN_DOCUMENT_MARKER_START.replaceAll(value, '', 1), trimmedValue = _ref2[0], count = _ref2[1];
      if (count === 1) {
        this.offset += Utils.subStrCount(value, "\n") - Utils.subStrCount(trimmedValue, "\n");
        value = trimmedValue;
        value = this.PATTERN_DOCUMENT_MARKER_END.replace(value, '');
      }
      return value;
    };
  
    Parser.prototype.isNextLineUnIndentedCollection = function(currentIndentation) {
      var notEOF, ret;
      if (currentIndentation == null) {
        currentIndentation = null;
      }
      if (currentIndentation == null) {
        currentIndentation = this.getCurrentLineIndentation();
      }
      notEOF = this.moveToNextLine();
      while (notEOF && this.isCurrentLineEmpty()) {
        notEOF = this.moveToNextLine();
      }
      if (false === notEOF) {
        return false;
      }
      ret = false;
      if (this.getCurrentLineIndentation() === currentIndentation && this.isStringUnIndentedCollectionItem(this.currentLine)) {
        ret = true;
      }
      this.moveToPreviousLine();
      return ret;
    };
  
    Parser.prototype.isStringUnIndentedCollectionItem = function() {
      return this.currentLine === '-' || this.currentLine.slice(0, 2) === '- ';
    };
  
    return Parser;
  
  })();
  
  module.exports = Parser;
  