text: 'use strict';var __extends = (this && this.__extends) || function (d, b) {
      for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
      function __() { this.constructor = d; }
      d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  };
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
      if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
      switch (arguments.length) {
          case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
          case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
          case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
      }
  };
  var __metadata = (this && this.__metadata) || function (k, v) {
      if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
  };
  var decorators_1 = require('angular2/src/core/di/decorators');
  var collection_1 = require("angular2/src/facade/collection");
  var lang_1 = require("angular2/src/facade/lang");
  var exceptions_1 = require('angular2/src/facade/exceptions');
  (function (TokenType) {
      TokenType[TokenType["Character"] = 0] = "Character";
      TokenType[TokenType["Identifier"] = 1] = "Identifier";
      TokenType[TokenType["Keyword"] = 2] = "Keyword";
      TokenType[TokenType["String"] = 3] = "String";
      TokenType[TokenType["Operator"] = 4] = "Operator";
      TokenType[TokenType["Number"] = 5] = "Number";
  })(exports.TokenType || (exports.TokenType = {}));
  var TokenType = exports.TokenType;
  var Lexer = (function () {
      function Lexer() {
      }
      Lexer.prototype.tokenize = function (text) {
          var scanner = new _Scanner(text);
          var tokens = [];
          var token = scanner.scanToken();
          while (token != null) {
              tokens.push(token);
              token = scanner.scanToken();
          }
          return tokens;
      };
      Lexer = __decorate([
          decorators_1.Injectable(), 
          __metadata('design:paramtypes', [])
      ], Lexer);
      return Lexer;
  })();
  exports.Lexer = Lexer;
  var Token = (function () {
      function Token(index, type, numValue, strValue) {
          this.index = index;
          this.type = type;
          this.numValue = numValue;
          this.strValue = strValue;
      }
      Token.prototype.isCharacter = function (code) {
          return (this.type == TokenType.Character && this.numValue == code);
      };
      Token.prototype.isNumber = function () { return (this.type == TokenType.Number); };
      Token.prototype.isString = function () { return (this.type == TokenType.String); };
      Token.prototype.isOperator = function (operater) {
          return (this.type == TokenType.Operator && this.strValue == operater);
      };
      Token.prototype.isIdentifier = function () { return (this.type == TokenType.Identifier); };
      Token.prototype.isKeyword = function () { return (this.type == TokenType.Keyword); };
      Token.prototype.isKeywordVar = function () { return (this.type == TokenType.Keyword && this.strValue == "var"); };
      Token.prototype.isKeywordNull = function () { return (this.type == TokenType.Keyword && this.strValue == "null"); };
      Token.prototype.isKeywordUndefined = function () {
          return (this.type == TokenType.Keyword && this.strValue == "undefined");
      };
      Token.prototype.isKeywordTrue = function () { return (this.type == TokenType.Keyword && this.strValue == "true"); };
      Token.prototype.isKeywordFalse = function () { return (this.type == TokenType.Keyword && this.strValue == "false"); };
      Token.prototype.toNumber = function () {
          // -1 instead of NULL ok?
          return (this.type == TokenType.Number) ? this.numValue : -1;
      };
      Token.prototype.toString = function () {
          switch (this.type) {
              case TokenType.Character:
              case TokenType.Identifier:
              case TokenType.Keyword:
              case TokenType.Operator:
              case TokenType.String:
                  return this.strValue;
              case TokenType.Number:
                  return this.numValue.toString();
              default:
                  return null;
          }
      };
      return Token;
  })();
  exports.Token = Token;
  function newCharacterToken(index, code) {
      return new Token(index, TokenType.Character, code, lang_1.StringWrapper.fromCharCode(code));
  }
  function newIdentifierToken(index, text) {
      return new Token(index, TokenType.Identifier, 0, text);
  }
  function newKeywordToken(index, text) {
      return new Token(index, TokenType.Keyword, 0, text);
  }
  function newOperatorToken(index, text) {
      return new Token(index, TokenType.Operator, 0, text);
  }
  function newStringToken(index, text) {
      return new Token(index, TokenType.String, 0, text);
  }
  function newNumberToken(index, n) {
      return new Token(index, TokenType.Number, n, "");
  }
  exports.EOF = new Token(-1, TokenType.Character, 0, "");
  exports.$EOF = 0;
  exports.$TAB = 9;
  exports.$LF = 10;
  exports.$VTAB = 11;
  exports.$FF = 12;
  exports.$CR = 13;
  exports.$SPACE = 32;
  exports.$BANG = 33;
  exports.$DQ = 34;
  exports.$HASH = 35;
  exports.$$ = 36;
  exports.$PERCENT = 37;
  exports.$AMPERSAND = 38;
  exports.$SQ = 39;
  exports.$LPAREN = 40;
  exports.$RPAREN = 41;
  exports.$STAR = 42;
  exports.$PLUS = 43;
  exports.$COMMA = 44;
  exports.$MINUS = 45;
  exports.$PERIOD = 46;
  exports.$SLASH = 47;
  exports.$COLON = 58;
  exports.$SEMICOLON = 59;
  exports.$LT = 60;
  exports.$EQ = 61;
  exports.$GT = 62;
  exports.$QUESTION = 63;
  var $0 = 48;
  var $9 = 57;
  var $A = 65, $E = 69, $Z = 90;
  exports.$LBRACKET = 91;
  exports.$BACKSLASH = 92;
  exports.$RBRACKET = 93;
  var $CARET = 94;
  var $_ = 95;
  var $a = 97, $e = 101, $f = 102, $n = 110, $r = 114, $t = 116, $u = 117, $v = 118, $z = 122;
  exports.$LBRACE = 123;
  exports.$BAR = 124;
  exports.$RBRACE = 125;
  var $NBSP = 160;
  var ScannerError = (function (_super) {
      __extends(ScannerError, _super);
      function ScannerError(message) {
          _super.call(this);
          this.message = message;
      }
      ScannerError.prototype.toString = function () { return this.message; };
      return ScannerError;
  })(exceptions_1.BaseException);
  exports.ScannerError = ScannerError;
  var _Scanner = (function () {
      function _Scanner(input) {
          this.input = input;
          this.peek = 0;
          this.index = -1;
          this.length = input.length;
          this.advance();
      }
      _Scanner.prototype.advance = function () {
          this.peek =
              ++this.index >= this.length ? exports.$EOF : lang_1.StringWrapper.charCodeAt(this.input, this.index);
      };
      _Scanner.prototype.scanToken = function () {
          var input = this.input, length = this.length, peek = this.peek, index = this.index;
          // Skip whitespace.
          while (peek <= exports.$SPACE) {
              if (++index >= length) {
                  peek = exports.$EOF;
                  break;
              }
              else {
                  peek = lang_1.StringWrapper.charCodeAt(input, index);
              }
          }
          this.peek = peek;
          this.index = index;
          if (index >= length) {
              return null;
          }
          // Handle identifiers and numbers.
          if (isIdentifierStart(peek))
              return this.scanIdentifier();
          if (isDigit(peek))
              return this.scanNumber(index);
          var start = index;
          switch (peek) {
              case exports.$PERIOD:
                  this.advance();
                  return isDigit(this.peek) ? this.scanNumber(start) : newCharacterToken(start, exports.$PERIOD);
              case exports.$LPAREN:
              case exports.$RPAREN:
              case exports.$LBRACE:
              case exports.$RBRACE:
              case exports.$LBRACKET:
              case exports.$RBRACKET:
              case exports.$COMMA:
              case exports.$COLON:
              case exports.$SEMICOLON:
                  return this.scanCharacter(start, peek);
              case exports.$SQ:
              case exports.$DQ:
                  return this.scanString();
              case exports.$HASH:
              case exports.$PLUS:
              case exports.$MINUS:
              case exports.$STAR:
              case exports.$SLASH:
              case exports.$PERCENT:
              case $CARET:
                  return this.scanOperator(start, lang_1.StringWrapper.fromCharCode(peek));
              case exports.$QUESTION:
                  return this.scanComplexOperator(start, '?', exports.$PERIOD, '.');
              case exports.$LT:
              case exports.$GT:
                  return this.scanComplexOperator(start, lang_1.StringWrapper.fromCharCode(peek), exports.$EQ, '=');
              case exports.$BANG:
              case exports.$EQ:
                  return this.scanComplexOperator(start, lang_1.StringWrapper.fromCharCode(peek), exports.$EQ, '=', exports.$EQ, '=');
              case exports.$AMPERSAND:
                  return this.scanComplexOperator(start, '&', exports.$AMPERSAND, '&');
              case exports.$BAR:
                  return this.scanComplexOperator(start, '|', exports.$BAR, '|');
              case $NBSP:
                  while (isWhitespace(this.peek))
                      this.advance();
                  return this.scanToken();
          }
          this.error("Unexpected character [" + lang_1.StringWrapper.fromCharCode(peek) + "]", 0);
          return null;
      };
      _Scanner.prototype.scanCharacter = function (start, code) {
          assert(this.peek == code);
          this.advance();
          return newCharacterToken(start, code);
      };
      _Scanner.prototype.scanOperator = function (start, str) {
          assert(this.peek == lang_1.StringWrapper.charCodeAt(str, 0));
          assert(collection_1.SetWrapper.has(OPERATORS, str));
          this.advance();
          return newOperatorToken(start, str);
      };
      /**
       * Tokenize a 2/3 char long operator
       *
       * @param start start index in the expression
       * @param one first symbol (always part of the operator)
       * @param twoCode code point for the second symbol
       * @param two second symbol (part of the operator when the second code point matches)
       * @param threeCode code point for the third symbol
       * @param three third symbol (part of the operator when provided and matches source expression)
       * @returns {Token}
       */
      _Scanner.prototype.scanComplexOperator = function (start, one, twoCode, two, threeCode, three) {
          assert(this.peek == lang_1.StringWrapper.charCodeAt(one, 0));
          this.advance();
          var str = one;
          if (this.peek == twoCode) {
              this.advance();
              str += two;
          }
          if (lang_1.isPresent(threeCode) && this.peek == threeCode) {
              this.advance();
              str += three;
          }
          assert(collection_1.SetWrapper.has(OPERATORS, str));
          return newOperatorToken(start, str);
      };
      _Scanner.prototype.scanIdentifier = function () {
          assert(isIdentifierStart(this.peek));
          var start = this.index;
          this.advance();
          while (isIdentifierPart(this.peek))
              this.advance();
          var str = this.input.substring(start, this.index);
          if (collection_1.SetWrapper.has(KEYWORDS, str)) {
              return newKeywordToken(start, str);
          }
          else {
              return newIdentifierToken(start, str);
          }
      };
      _Scanner.prototype.scanNumber = function (start) {
          assert(isDigit(this.peek));
          var simple = (this.index === start);
          this.advance(); // Skip initial digit.
          while (true) {
              if (isDigit(this.peek)) {
              }
              else if (this.peek == exports.$PERIOD) {
                  simple = false;
              }
              else if (isExponentStart(this.peek)) {
                  this.advance();
                  if (isExponentSign(this.peek))
                      this.advance();
                  if (!isDigit(this.peek))
                      this.error('Invalid exponent', -1);
                  simple = false;
              }
              else {
                  break;
              }
              this.advance();
          }
          var str = this.input.substring(start, this.index);
          // TODO
          var value = simple ? lang_1.NumberWrapper.parseIntAutoRadix(str) : lang_1.NumberWrapper.parseFloat(str);
          return newNumberToken(start, value);
      };
      _Scanner.prototype.scanString = function () {
          assert(this.peek == exports.$SQ || this.peek == exports.$DQ);
          var start = this.index;
          var quote = this.peek;
          this.advance(); // Skip initial quote.
          var buffer;
          var marker = this.index;
          var input = this.input;
          while (this.peek != quote) {
              if (this.peek == exports.$BACKSLASH) {
                  if (buffer == null)
                      buffer = new lang_1.StringJoiner();
                  buffer.add(input.substring(marker, this.index));
                  this.advance();
                  var unescapedCode;
                  if (this.peek == $u) {
                      // 4 character hex code for unicode character.
                      var hex = input.substring(this.index + 1, this.index + 5);
                      try {
                          unescapedCode = lang_1.NumberWrapper.parseInt(hex, 16);
                      }
                      catch (e) {
                          this.error("Invalid unicode escape [\\u" + hex + "]", 0);
                      }
                      for (var i = 0; i < 5; i++) {
                          this.advance();
                      }
                  }
                  else {
                      unescapedCode = unescape(this.peek);
                      this.advance();
                  }
                  buffer.add(lang_1.StringWrapper.fromCharCode(unescapedCode));
                  marker = this.index;
              }
              else if (this.peek == exports.$EOF) {
                  this.error('Unterminated quote', 0);
              }
              else {
                  this.advance();
              }
          }
          var last = input.substring(marker, this.index);
          this.advance(); // Skip terminating quote.
          // Compute the unescaped string value.
          var unescaped = last;
          if (buffer != null) {
              buffer.add(last);
              unescaped = buffer.toString();
          }
          return newStringToken(start, unescaped);
      };
      _Scanner.prototype.error = function (message, offset) {
          var position = this.index + offset;
          throw new ScannerError("Lexer Error: " + message + " at column " + position + " in expression [" + this.input + "]");
      };
      return _Scanner;
  })();
  function isWhitespace(code) {
      return (code >= exports.$TAB && code <= exports.$SPACE) || (code == $NBSP);
  }
  function isIdentifierStart(code) {
      return ($a <= code && code <= $z) || ($A <= code && code <= $Z) || (code == $_) || (code == exports.$$);
  }
  function isIdentifierPart(code) {
      return ($a <= code && code <= $z) || ($A <= code && code <= $Z) || ($0 <= code && code <= $9) ||
          (code == $_) || (code == exports.$$);
  }
  function isDigit(code) {
      return $0 <= code && code <= $9;
  }
  function isExponentStart(code) {
      return code == $e || code == $E;
  }
  function isExponentSign(code) {
      return code == exports.$MINUS || code == exports.$PLUS;
  }
  function unescape(code) {
      switch (code) {
          case $n:
              return exports.$LF;
          case $f:
              return exports.$FF;
          case $r:
              return exports.$CR;
          case $t:
              return exports.$TAB;
          case $v:
              return exports.$VTAB;
          default:
              return code;
      }
  }
  var OPERATORS = collection_1.SetWrapper.createFromList([
      '+',
      '-',
      '*',
      '/',
      '%',
      '^',
      '=',
      '==',
      '!=',
      '===',
      '!==',
      '<',
      '>',
      '<=',
      '>=',
      '&&',
      '||',
      '&',
      '|',
      '!',
      '?',
      '#',
      '?.'
  ]);
  var KEYWORDS = collection_1.SetWrapper.createFromList(['var', 'null', 'undefined', 'true', 'false', 'if', 'else']);
  //# sourceMappingURL=lexer.js.map
  