diff --git a/modules/@angular/compiler/src/chars.ts b/modules/@angular/compiler/src/chars.ts index 490aef42ba..af7bc9d3a1 100644 --- a/modules/@angular/compiler/src/chars.ts +++ b/modules/@angular/compiler/src/chars.ts @@ -62,6 +62,20 @@ export const $PIPE = 124; export const $TILDA = 126; export const $AT = 64; +export const $BT = 96; + export function isWhitespace(code: number): boolean { return (code >= $TAB && code <= $SPACE) || (code == $NBSP); } + +export function isDigit(code: number): boolean { + return $0 <= code && code <= $9; +} + +export function isAsciiLetter(code: number): boolean { + return code >= $a && code <= $z || code >= $A && code <= $Z; +} + +export function isAsciiHexDigit(code: number): boolean { + return code >= $a && code <= $f || code >= $A && code <= $F || isDigit(code); +} diff --git a/modules/@angular/compiler/src/css_lexer.ts b/modules/@angular/compiler/src/css_lexer.ts index 53309a8410..2452932d7a 100644 --- a/modules/@angular/compiler/src/css_lexer.ts +++ b/modules/@angular/compiler/src/css_lexer.ts @@ -1,9 +1,7 @@ -import {$$, $0, $9, $A, $AMPERSAND, $AT, $BACKSLASH, $BANG, $CARET, $COLON, $COMMA, $CR, $DQ, $EOF, $EQ, $FF, $GT, $HASH, $LBRACE, $LBRACKET, $LF, $LPAREN, $MINUS, $PERCENT, $PERIOD, $PIPE, $PLUS, $QUESTION, $RBRACE, $RBRACKET, $RPAREN, $SEMICOLON, $SLASH, $SPACE, $SQ, $STAR, $TAB, $TILDA, $VTAB, $Z, $_, $a, $z, isWhitespace} from './chars'; +import * as chars from './chars'; import {BaseException} from './facade/exceptions'; import {StringWrapper, isPresent, resolveEnumToken} from './facade/lang'; -export {$AT, $COLON, $COMMA, $EOF, $GT, $LBRACE, $LBRACKET, $LPAREN, $PLUS, $RBRACE, $RBRACKET, $RPAREN, $SEMICOLON, $SLASH, $SPACE, $TAB, $TILDA, isWhitespace} from './chars'; - export enum CssTokenType { EOF, String, @@ -148,25 +146,25 @@ export class CssScanner { } peekAt(index: number): number { - return index >= this.length ? $EOF : StringWrapper.charCodeAt(this.input, index); + return index >= this.length ? chars.$EOF : StringWrapper.charCodeAt(this.input, index); } consumeEmptyStatements(): void { this.consumeWhitespace(); - while (this.peek == $SEMICOLON) { + while (this.peek == chars.$SEMICOLON) { this.advance(); this.consumeWhitespace(); } } consumeWhitespace(): void { - while (isWhitespace(this.peek) || isNewline(this.peek)) { + while (chars.isWhitespace(this.peek) || isNewline(this.peek)) { this.advance(); if (!this._trackComments && isCommentStart(this.peek, this.peekPeek)) { this.advance(); // / this.advance(); // * while (!isCommentEnd(this.peek, this.peekPeek)) { - if (this.peek == $EOF) { + if (this.peek == chars.$EOF) { this.error('Unterminated comment'); } this.advance(); @@ -255,7 +253,7 @@ export class CssScanner { _scan(): CssToken { var peek = this.peek; var peekPeek = this.peekPeek; - if (peek == $EOF) return null; + if (peek == chars.$EOF) return null; if (isCommentStart(peek, peekPeek)) { // even if comments are not tracked we still lex the @@ -266,13 +264,13 @@ export class CssScanner { } } - if (_trackWhitespace(this._currentMode) && (isWhitespace(peek) || isNewline(peek))) { + if (_trackWhitespace(this._currentMode) && (chars.isWhitespace(peek) || isNewline(peek))) { return this.scanWhitespace(); } peek = this.peek; peekPeek = this.peekPeek; - if (peek == $EOF) return null; + if (peek == chars.$EOF) return null; if (isStringStart(peek, peekPeek)) { return this.scanString(); @@ -283,14 +281,15 @@ export class CssScanner { return this.scanCssValueFunction(); } - var isModifier = peek == $PLUS || peek == $MINUS; - var digitA = isModifier ? false : isDigit(peek); - var digitB = isDigit(peekPeek); - if (digitA || (isModifier && (peekPeek == $PERIOD || digitB)) || (peek == $PERIOD && digitB)) { + var isModifier = peek == chars.$PLUS || peek == chars.$MINUS; + var digitA = isModifier ? false : chars.isDigit(peek); + var digitB = chars.isDigit(peekPeek); + if (digitA || (isModifier && (peekPeek == chars.$PERIOD || digitB)) || + (peek == chars.$PERIOD && digitB)) { return this.scanNumber(); } - if (peek == $AT) { + if (peek == chars.$AT) { return this.scanAtExpression(); } @@ -319,7 +318,7 @@ export class CssScanner { this.advance(); // * while (!isCommentEnd(this.peek, this.peekPeek)) { - if (this.peek == $EOF) { + if (this.peek == chars.$EOF) { this.error('Unterminated comment'); } this.advance(); @@ -336,7 +335,7 @@ export class CssScanner { var start = this.index; var startingColumn = this.column; var startingLine = this.line; - while (isWhitespace(this.peek) && this.peek != $EOF) { + while (chars.isWhitespace(this.peek) && this.peek != chars.$EOF) { this.advance(); } var str = this.input.substring(start, this.index); @@ -357,7 +356,7 @@ export class CssScanner { this.advance(); while (!isCharMatch(target, previous, this.peek)) { - if (this.peek == $EOF || isNewline(this.peek)) { + if (this.peek == chars.$EOF || isNewline(this.peek)) { this.error('Unterminated quote'); } previous = this.peek; @@ -376,12 +375,12 @@ export class CssScanner { scanNumber(): CssToken { var start = this.index; var startingColumn = this.column; - if (this.peek == $PLUS || this.peek == $MINUS) { + if (this.peek == chars.$PLUS || this.peek == chars.$MINUS) { this.advance(); } var periodUsed = false; - while (isDigit(this.peek) || this.peek == $PERIOD) { - if (this.peek == $PERIOD) { + while (chars.isDigit(this.peek) || this.peek == chars.$PERIOD) { + if (this.peek == chars.$PERIOD) { if (periodUsed) { this.error('Unexpected use of a second period value'); } @@ -412,11 +411,11 @@ export class CssScanner { var start = this.index; var startingColumn = this.column; var parenBalance = 1; - while (this.peek != $EOF && parenBalance > 0) { + while (this.peek != chars.$EOF && parenBalance > 0) { this.advance(); - if (this.peek == $LPAREN) { + if (this.peek == chars.$LPAREN) { parenBalance++; - } else if (this.peek == $RPAREN) { + } else if (this.peek == chars.$RPAREN) { parenBalance--; } } @@ -440,7 +439,7 @@ export class CssScanner { } scanAtExpression(): CssToken { - if (this.assertCondition(this.peek == $AT, 'Expected @ value')) { + if (this.assertCondition(this.peek == chars.$AT, 'Expected @ value')) { return null; } @@ -481,53 +480,45 @@ export class CssScanner { } } -function isAtKeyword(current: CssToken, next: CssToken): boolean { - return current.numValue == $AT && next.type == CssTokenType.Identifier; -} - function isCharMatch(target: number, previous: number, code: number): boolean { - return code == target && previous != $BACKSLASH; -} - -function isDigit(code: number): boolean { - return $0 <= code && code <= $9; + return code == target && previous != chars.$BACKSLASH; } function isCommentStart(code: number, next: number): boolean { - return code == $SLASH && next == $STAR; + return code == chars.$SLASH && next == chars.$STAR; } function isCommentEnd(code: number, next: number): boolean { - return code == $STAR && next == $SLASH; + return code == chars.$STAR && next == chars.$SLASH; } function isStringStart(code: number, next: number): boolean { var target = code; - if (target == $BACKSLASH) { + if (target == chars.$BACKSLASH) { target = next; } - return target == $DQ || target == $SQ; + return target == chars.$DQ || target == chars.$SQ; } function isIdentifierStart(code: number, next: number): boolean { var target = code; - if (target == $MINUS) { + if (target == chars.$MINUS) { target = next; } - return ($a <= target && target <= $z) || ($A <= target && target <= $Z) || target == $BACKSLASH || - target == $MINUS || target == $_; + return chars.isAsciiLetter(target) || target == chars.$BACKSLASH || target == chars.$MINUS || + target == chars.$_; } function isIdentifierPart(target: number): boolean { - return ($a <= target && target <= $z) || ($A <= target && target <= $Z) || target == $BACKSLASH || - target == $MINUS || target == $_ || isDigit(target); + return chars.isAsciiLetter(target) || target == chars.$BACKSLASH || target == chars.$MINUS || + target == chars.$_ || chars.isDigit(target); } function isValidPseudoSelectorCharacter(code: number): boolean { switch (code) { - case $LPAREN: - case $RPAREN: + case chars.$LPAREN: + case chars.$RPAREN: return true; default: return false; @@ -535,18 +526,18 @@ function isValidPseudoSelectorCharacter(code: number): boolean { } function isValidKeyframeBlockCharacter(code: number): boolean { - return code == $PERCENT; + return code == chars.$PERCENT; } function isValidAttributeSelectorCharacter(code: number): boolean { // value^*|$~=something switch (code) { - case $$: - case $PIPE: - case $CARET: - case $TILDA: - case $STAR: - case $EQ: + case chars.$$: + case chars.$PIPE: + case chars.$CARET: + case chars.$TILDA: + case chars.$STAR: + case chars.$EQ: return true; default: return false; @@ -559,17 +550,17 @@ function isValidSelectorCharacter(code: number): boolean { // #id, .class, *+~> // tag:PSEUDO switch (code) { - case $HASH: - case $PERIOD: - case $TILDA: - case $STAR: - case $PLUS: - case $GT: - case $COLON: - case $PIPE: - case $COMMA: - case $LBRACKET: - case $RBRACKET: + case chars.$HASH: + case chars.$PERIOD: + case chars.$TILDA: + case chars.$STAR: + case chars.$PLUS: + case chars.$GT: + case chars.$COLON: + case chars.$PIPE: + case chars.$COMMA: + case chars.$LBRACKET: + case chars.$RBRACKET: return true; default: return false; @@ -580,16 +571,16 @@ function isValidStyleBlockCharacter(code: number): boolean { // key:value; // key:calc(something ... ) switch (code) { - case $HASH: - case $SEMICOLON: - case $COLON: - case $PERCENT: - case $SLASH: - case $BACKSLASH: - case $BANG: - case $PERIOD: - case $LPAREN: - case $RPAREN: + case chars.$HASH: + case chars.$SEMICOLON: + case chars.$COLON: + case chars.$PERCENT: + case chars.$SLASH: + case chars.$BACKSLASH: + case chars.$BANG: + case chars.$PERIOD: + case chars.$LPAREN: + case chars.$RPAREN: return true; default: return false; @@ -599,11 +590,11 @@ function isValidStyleBlockCharacter(code: number): boolean { function isValidMediaQueryRuleCharacter(code: number): boolean { // (min-width: 7.5em) and (orientation: landscape) switch (code) { - case $LPAREN: - case $RPAREN: - case $COLON: - case $PERCENT: - case $PERIOD: + case chars.$LPAREN: + case chars.$RPAREN: + case chars.$COLON: + case chars.$PERCENT: + case chars.$PERIOD: return true; default: return false; @@ -613,21 +604,21 @@ function isValidMediaQueryRuleCharacter(code: number): boolean { function isValidAtRuleCharacter(code: number): boolean { // @document url(http://www.w3.org/page?something=on#hash), switch (code) { - case $LPAREN: - case $RPAREN: - case $COLON: - case $PERCENT: - case $PERIOD: - case $SLASH: - case $BACKSLASH: - case $HASH: - case $EQ: - case $QUESTION: - case $AMPERSAND: - case $STAR: - case $COMMA: - case $MINUS: - case $PLUS: + case chars.$LPAREN: + case chars.$RPAREN: + case chars.$COLON: + case chars.$PERCENT: + case chars.$PERIOD: + case chars.$SLASH: + case chars.$BACKSLASH: + case chars.$HASH: + case chars.$EQ: + case chars.$QUESTION: + case chars.$AMPERSAND: + case chars.$STAR: + case chars.$COMMA: + case chars.$MINUS: + case chars.$PLUS: return true; default: return false; @@ -636,14 +627,14 @@ function isValidAtRuleCharacter(code: number): boolean { function isValidStyleFunctionCharacter(code: number): boolean { switch (code) { - case $PERIOD: - case $MINUS: - case $PLUS: - case $STAR: - case $SLASH: - case $LPAREN: - case $RPAREN: - case $COMMA: + case chars.$PERIOD: + case chars.$MINUS: + case chars.$PLUS: + case chars.$STAR: + case chars.$SLASH: + case chars.$LPAREN: + case chars.$RPAREN: + case chars.$COMMA: return true; default: return false; @@ -653,7 +644,7 @@ function isValidStyleFunctionCharacter(code: number): boolean { function isValidBlockCharacter(code: number): boolean { // @something { } // IDENT - return code == $AT; + return code == chars.$AT; } function isValidCssCharacter(code: number, mode: CssLexerMode): boolean { @@ -695,20 +686,20 @@ function isValidCssCharacter(code: number, mode: CssLexerMode): boolean { } } -function charCode(input: any /** TODO #9100 */, index: any /** TODO #9100 */): number { - return index >= input.length ? $EOF : StringWrapper.charCodeAt(input, index); +function charCode(input: string, index: number): number { + return index >= input.length ? chars.$EOF : StringWrapper.charCodeAt(input, index); } function charStr(code: number): string { return StringWrapper.fromCharCode(code); } -export function isNewline(code: any /** TODO #9100 */): boolean { +export function isNewline(code: number): boolean { switch (code) { - case $FF: - case $CR: - case $LF: - case $VTAB: + case chars.$FF: + case chars.$CR: + case chars.$LF: + case chars.$VTAB: return true; default: diff --git a/modules/@angular/compiler/src/css_parser.ts b/modules/@angular/compiler/src/css_parser.ts index 258d7d4da0..fd629504e8 100644 --- a/modules/@angular/compiler/src/css_parser.ts +++ b/modules/@angular/compiler/src/css_parser.ts @@ -1,5 +1,6 @@ -import {$AT, $COLON, $COMMA, $EOF, $GT, $LBRACE, $LBRACKET, $LPAREN, $PLUS, $RBRACE, $RBRACKET, $RPAREN, $SEMICOLON, $SLASH, $SPACE, $TAB, $TILDA, CssLexerMode, CssScanner, CssScannerError, CssToken, CssTokenType, generateErrorMessage, isNewline, isWhitespace} from './css_lexer'; -import {NumberWrapper, StringWrapper, isPresent} from './facade/lang'; +import * as chars from './chars'; +import {CssLexerMode, CssScanner, CssToken, CssTokenType, generateErrorMessage, isNewline} from './css_lexer'; +import {isPresent} from './facade/lang'; import {ParseError, ParseLocation, ParseSourceFile, ParseSourceSpan} from './parse_util'; const SPACE_OPERATOR = ' '; @@ -43,13 +44,13 @@ function _pseudoSelectorSupportsInnerSelectors(name: string): boolean { function isSelectorOperatorCharacter(code: number): boolean { switch (code) { - case $SLASH: - case $TILDA: - case $PLUS: - case $GT: + case chars.$SLASH: + case chars.$TILDA: + case chars.$PLUS: + case chars.$GT: return true; default: - return isWhitespace(code); + return chars.isWhitespace(code); } } @@ -69,22 +70,22 @@ function getDelimFromToken(token: CssToken): number { function getDelimFromCharacter(code: number): number { switch (code) { - case $EOF: + case chars.$EOF: return EOF_DELIM_FLAG; - case $COMMA: + case chars.$COMMA: return COMMA_DELIM_FLAG; - case $COLON: + case chars.$COLON: return COLON_DELIM_FLAG; - case $SEMICOLON: + case chars.$SEMICOLON: return SEMICOLON_DELIM_FLAG; - case $RBRACE: + case chars.$RBRACE: return RBRACE_DELIM_FLAG; - case $LBRACE: + case chars.$LBRACE: return LBRACE_DELIM_FLAG; - case $RPAREN: + case chars.$RPAREN: return RPAREN_DELIM_FLAG; - case $SPACE: - case $TAB: + case chars.$SPACE: + case chars.$TAB: return SPACE_DELIM_FLAG; default: return isNewline(code) ? NEWLINE_DELIM_FLAG : 0; @@ -187,7 +188,7 @@ export class CssParser { const start = this._getScannerIndex(); var results: any[] /** TODO #9100 */ = []; this._scanner.consumeEmptyStatements(); - while (this._scanner.peek != $EOF) { + while (this._scanner.peek != chars.$EOF) { this._scanner.setMode(CssLexerMode.BLOCK); results.push(this._parseRule(delimiters)); } @@ -197,7 +198,7 @@ export class CssParser { /** @internal */ _parseRule(delimiters: number): CssRuleAst { - if (this._scanner.peek == $AT) { + if (this._scanner.peek == chars.$AT) { return this._parseAtRule(delimiters); } return this._parseSelectorRule(delimiters); @@ -277,7 +278,7 @@ export class CssParser { this._collectUntilDelim(delimiters | LBRACE_DELIM_FLAG | SEMICOLON_DELIM_FLAG) .forEach((token) => { listOfTokens.push(token); }); - if (this._scanner.peek == $LBRACE) { + if (this._scanner.peek == chars.$LBRACE) { listOfTokens.push(this._consume(CssTokenType.Character, '{')); this._collectUntilDelim(delimiters | RBRACE_DELIM_FLAG | LBRACE_DELIM_FLAG) .forEach((token) => { listOfTokens.push(token); }); @@ -387,7 +388,7 @@ export class CssParser { delimiters |= LBRACE_DELIM_FLAG; while (!characterContainsDelimiter(this._scanner.peek, delimiters)) { stepTokens.push(this._parseKeyframeLabel(delimiters | COMMA_DELIM_FLAG)); - if (this._scanner.peek != $LBRACE) { + if (this._scanner.peek != chars.$LBRACE) { this._consume(CssTokenType.Character, ','); } } @@ -415,7 +416,7 @@ export class CssParser { var startToken = this._consume(CssTokenType.Character, ':'); var tokens = [startToken]; - if (this._scanner.peek == $COLON) { // ::something + if (this._scanner.peek == chars.$COLON) { // ::something startToken = this._consume(CssTokenType.Character, ':'); tokens.push(startToken); } @@ -430,7 +431,7 @@ export class CssParser { tokens.push(pseudoSelectorToken); // host(), lang(), nth-child(), etc... - if (this._scanner.peek == $LPAREN) { + if (this._scanner.peek == chars.$LPAREN) { this._scanner.setMode(CssLexerMode.PSEUDO_SELECTOR_WITH_ARGUMENTS); var openParenToken = this._consume(CssTokenType.Character, '('); @@ -491,13 +492,13 @@ export class CssParser { var peek = this._scanner.peek; switch (peek) { - case $COLON: + case chars.$COLON: var innerPseudo = this._parsePseudoSelector(delimiters); pseudoSelectors.push(innerPseudo); this._scanner.setMode(CssLexerMode.SELECTOR); break; - case $LBRACKET: + case chars.$LBRACKET: // we set the mode after the scan because attribute mode does not // allow attribute [] values. And this also will catch any errors // if an extra "[" is used inside. @@ -505,7 +506,7 @@ export class CssParser { this._scanner.setMode(CssLexerMode.ATTRIBUTE_SELECTOR); break; - case $RBRACKET: + case chars.$RBRACKET: if (this._scanner.getMode() != CssLexerMode.ATTRIBUTE_SELECTOR) { hasAttributeError = true; } @@ -580,7 +581,7 @@ export class CssParser { case GT_CHARACTER: // >>> operator - if (this._scanner.peek == $GT && this._scanner.peekPeek == $GT) { + if (this._scanner.peek == chars.$GT && this._scanner.peekPeek == chars.$GT) { this._consume(CssTokenType.Character, GT_CHARACTER); this._consume(CssTokenType.Character, GT_CHARACTER); token = new CssToken( @@ -601,7 +602,7 @@ export class CssParser { // if we do come across one or more spaces inside of // the operators loop then an empty space is still a // valid operator to use if something else was not found - if (operator == null && operatorScanCount > 0 && this._scanner.peek != $LBRACE) { + if (operator == null && operatorScanCount > 0 && this._scanner.peek != chars.$LBRACE) { operator = lastOperatorToken; } @@ -647,7 +648,7 @@ export class CssParser { while (!characterContainsDelimiter(this._scanner.peek, delimiters)) { var token: CssToken; if (isPresent(previous) && previous.type == CssTokenType.Identifier && - this._scanner.peek == $LPAREN) { + this._scanner.peek == chars.$LPAREN) { token = this._consume(CssTokenType.Character, '('); tokens.push(token); @@ -676,9 +677,9 @@ export class CssParser { this._scanner.consumeWhitespace(); var code = this._scanner.peek; - if (code == $SEMICOLON) { + if (code == chars.$SEMICOLON) { this._consume(CssTokenType.Character, ';'); - } else if (code != $RBRACE) { + } else if (code != chars.$RBRACE) { this._error( generateErrorMessage( this._scanner.input, `The CSS key/value definition did not end with a semicolon`, @@ -734,7 +735,7 @@ export class CssParser { this._scanner.setMode(CssLexerMode.STYLE_BLOCK); var result = this._consume(CssTokenType.Character, '{'); - if (result.numValue != $LBRACE) { + if (result.numValue != chars.$LBRACE) { return null; } @@ -767,20 +768,20 @@ export class CssParser { // there are a few cases as to what could happen if it // is missing switch (this._scanner.peek) { - case $COLON: + case chars.$COLON: this._consume(CssTokenType.Character, ':'); parseValue = true; break; - case $SEMICOLON: - case $RBRACE: - case $EOF: + case chars.$SEMICOLON: + case chars.$RBRACE: + case chars.$EOF: parseValue = false; break; default: var propStr = [prop.strValue]; - if (this._scanner.peek != $COLON) { + if (this._scanner.peek != chars.$COLON) { // this will throw the error var nextValue = this._consume(CssTokenType.Character, ':'); propStr.push(nextValue.strValue); @@ -795,7 +796,7 @@ export class CssParser { } // this means we've reached the end of the definition and/or block - if (this._scanner.peek == $COLON) { + if (this._scanner.peek == chars.$COLON) { this._consume(CssTokenType.Character, ':'); parseValue = true; } else { @@ -960,8 +961,6 @@ export class CssSelectorAst extends CssSelectorPartAst { } export class CssSimpleSelectorAst extends CssSelectorPartAst { - public selectorStrValue: string; - constructor( start: number, end: number, public tokens: CssToken[], public strValue: string, public pseudoSelectors: CssPseudoSelectorAst[], public operator: CssToken) { diff --git a/modules/@angular/compiler/src/expression_parser/lexer.ts b/modules/@angular/compiler/src/expression_parser/lexer.ts index 2da9a14778..93f13698a1 100644 --- a/modules/@angular/compiler/src/expression_parser/lexer.ts +++ b/modules/@angular/compiler/src/expression_parser/lexer.ts @@ -1,5 +1,5 @@ import {Injectable} from '@angular/core'; - +import * as chars from '../chars'; import {SetWrapper} from '../facade/collection'; import {BaseException} from '../facade/exceptions'; import {NumberWrapper, StringJoiner, StringWrapper, isPresent} from '../facade/lang'; @@ -13,6 +13,8 @@ export enum TokenType { Number } +const KEYWORDS = ['var', 'let', 'null', 'undefined', 'true', 'false', 'if', 'else']; + @Injectable() export class Lexer { tokenize(text: string): any[] { @@ -109,58 +111,8 @@ function newNumberToken(index: number, n: number): Token { return new Token(index, TokenType.Number, n, ''); } - export var EOF: Token = new Token(-1, TokenType.Character, 0, ''); -export const $EOF = /*@ts2dart_const*/ 0; -export const $TAB = /*@ts2dart_const*/ 9; -export const $LF = /*@ts2dart_const*/ 10; -export const $VTAB = /*@ts2dart_const*/ 11; -export const $FF = /*@ts2dart_const*/ 12; -export const $CR = /*@ts2dart_const*/ 13; -export const $SPACE = /*@ts2dart_const*/ 32; -export const $BANG = /*@ts2dart_const*/ 33; -export const $DQ = /*@ts2dart_const*/ 34; -export const $HASH = /*@ts2dart_const*/ 35; -export const $$ = /*@ts2dart_const*/ 36; -export const $PERCENT = /*@ts2dart_const*/ 37; -export const $AMPERSAND = /*@ts2dart_const*/ 38; -export const $SQ = /*@ts2dart_const*/ 39; -export const $LPAREN = /*@ts2dart_const*/ 40; -export const $RPAREN = /*@ts2dart_const*/ 41; -export const $STAR = /*@ts2dart_const*/ 42; -export const $PLUS = /*@ts2dart_const*/ 43; -export const $COMMA = /*@ts2dart_const*/ 44; -export const $MINUS = /*@ts2dart_const*/ 45; -export const $PERIOD = /*@ts2dart_const*/ 46; -export const $SLASH = /*@ts2dart_const*/ 47; -export const $COLON = /*@ts2dart_const*/ 58; -export const $SEMICOLON = /*@ts2dart_const*/ 59; -export const $LT = /*@ts2dart_const*/ 60; -export const $EQ = /*@ts2dart_const*/ 61; -export const $GT = /*@ts2dart_const*/ 62; -export const $QUESTION = /*@ts2dart_const*/ 63; - -const $0 = /*@ts2dart_const*/ 48; -const $9 = /*@ts2dart_const*/ 57; - -const $A = /*@ts2dart_const*/ 65, $E = /*@ts2dart_const*/ 69, $Z = /*@ts2dart_const*/ 90; - -export const $LBRACKET = /*@ts2dart_const*/ 91; -export const $BACKSLASH = /*@ts2dart_const*/ 92; -export const $RBRACKET = /*@ts2dart_const*/ 93; -const $CARET = /*@ts2dart_const*/ 94; -const $_ = /*@ts2dart_const*/ 95; -export const $BT = /*@ts2dart_const*/ 96; -const $a = /*@ts2dart_const*/ 97, $e = /*@ts2dart_const*/ 101, $f = /*@ts2dart_const*/ 102; -const $n = /*@ts2dart_const*/ 110, $r = /*@ts2dart_const*/ 114, $t = /*@ts2dart_const*/ 116, - $u = /*@ts2dart_const*/ 117, $v = /*@ts2dart_const*/ 118, $z = /*@ts2dart_const*/ 122; - -export const $LBRACE = /*@ts2dart_const*/ 123; -export const $BAR = /*@ts2dart_const*/ 124; -export const $RBRACE = /*@ts2dart_const*/ 125; -const $NBSP = /*@ts2dart_const*/ 160; - export class ScannerError extends BaseException { constructor(public message: string) { super(); } @@ -179,16 +131,16 @@ class _Scanner { advance() { this.peek = - ++this.index >= this.length ? $EOF : StringWrapper.charCodeAt(this.input, this.index); + ++this.index >= this.length ? chars.$EOF : StringWrapper.charCodeAt(this.input, this.index); } scanToken(): Token { var input = this.input, length = this.length, peek = this.peek, index = this.index; // Skip whitespace. - while (peek <= $SPACE) { + while (peek <= chars.$SPACE) { if (++index >= length) { - peek = $EOF; + peek = chars.$EOF; break; } else { peek = StringWrapper.charCodeAt(input, index); @@ -204,49 +156,50 @@ class _Scanner { // Handle identifiers and numbers. if (isIdentifierStart(peek)) return this.scanIdentifier(); - if (isDigit(peek)) return this.scanNumber(index); + if (chars.isDigit(peek)) return this.scanNumber(index); var start: number = index; switch (peek) { - case $PERIOD: + case chars.$PERIOD: this.advance(); - return isDigit(this.peek) ? this.scanNumber(start) : newCharacterToken(start, $PERIOD); - case $LPAREN: - case $RPAREN: - case $LBRACE: - case $RBRACE: - case $LBRACKET: - case $RBRACKET: - case $COMMA: - case $COLON: - case $SEMICOLON: + return chars.isDigit(this.peek) ? this.scanNumber(start) : + newCharacterToken(start, chars.$PERIOD); + case chars.$LPAREN: + case chars.$RPAREN: + case chars.$LBRACE: + case chars.$RBRACE: + case chars.$LBRACKET: + case chars.$RBRACKET: + case chars.$COMMA: + case chars.$COLON: + case chars.$SEMICOLON: return this.scanCharacter(start, peek); - case $SQ: - case $DQ: + case chars.$SQ: + case chars.$DQ: return this.scanString(); - case $HASH: - case $PLUS: - case $MINUS: - case $STAR: - case $SLASH: - case $PERCENT: - case $CARET: + case chars.$HASH: + case chars.$PLUS: + case chars.$MINUS: + case chars.$STAR: + case chars.$SLASH: + case chars.$PERCENT: + case chars.$CARET: return this.scanOperator(start, StringWrapper.fromCharCode(peek)); - case $QUESTION: - return this.scanComplexOperator(start, '?', $PERIOD, '.'); - case $LT: - case $GT: - return this.scanComplexOperator(start, StringWrapper.fromCharCode(peek), $EQ, '='); - case $BANG: - case $EQ: + case chars.$QUESTION: + return this.scanComplexOperator(start, '?', chars.$PERIOD, '.'); + case chars.$LT: + case chars.$GT: + return this.scanComplexOperator(start, StringWrapper.fromCharCode(peek), chars.$EQ, '='); + case chars.$BANG: + case chars.$EQ: return this.scanComplexOperator( - start, StringWrapper.fromCharCode(peek), $EQ, '=', $EQ, '='); - case $AMPERSAND: - return this.scanComplexOperator(start, '&', $AMPERSAND, '&'); - case $BAR: - return this.scanComplexOperator(start, '|', $BAR, '|'); - case $NBSP: - while (isWhitespace(this.peek)) this.advance(); + start, StringWrapper.fromCharCode(peek), chars.$EQ, '=', chars.$EQ, '='); + case chars.$AMPERSAND: + return this.scanComplexOperator(start, '&', chars.$AMPERSAND, '&'); + case chars.$BAR: + return this.scanComplexOperator(start, '|', chars.$BAR, '|'); + case chars.$NBSP: + while (chars.isWhitespace(this.peek)) this.advance(); return this.scanToken(); } @@ -297,25 +250,22 @@ class _Scanner { this.advance(); while (isIdentifierPart(this.peek)) this.advance(); var str: string = this.input.substring(start, this.index); - if (SetWrapper.has(KEYWORDS, str)) { - return newKeywordToken(start, str); - } else { - return newIdentifierToken(start, str); - } + return KEYWORDS.indexOf(str) > -1 ? newKeywordToken(start, str) : + newIdentifierToken(start, str); } scanNumber(start: number): Token { var simple: boolean = (this.index === start); this.advance(); // Skip initial digit. while (true) { - if (isDigit(this.peek)) { + if (chars.isDigit(this.peek)) { // Do nothing. - } else if (this.peek == $PERIOD) { + } else if (this.peek == chars.$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); + if (!chars.isDigit(this.peek)) this.error('Invalid exponent', -1); simple = false; } else { break; @@ -323,7 +273,6 @@ class _Scanner { this.advance(); } var str: string = this.input.substring(start, this.index); - // TODO var value: number = simple ? NumberWrapper.parseIntAutoRadix(str) : NumberWrapper.parseFloat(str); return newNumberToken(start, value); @@ -339,12 +288,12 @@ class _Scanner { var input: string = this.input; while (this.peek != quote) { - if (this.peek == $BACKSLASH) { + if (this.peek == chars.$BACKSLASH) { if (buffer == null) buffer = new StringJoiner(); buffer.add(input.substring(marker, this.index)); this.advance(); var unescapedCode: number; - if (this.peek == $u) { + if (this.peek == chars.$u) { // 4 character hex code for unicode character. var hex: string = input.substring(this.index + 1, this.index + 5); try { @@ -361,7 +310,7 @@ class _Scanner { } buffer.add(StringWrapper.fromCharCode(unescapedCode)); marker = this.index; - } else if (this.peek == $EOF) { + } else if (this.peek == chars.$EOF) { this.error('Unterminated quote', 0); } else { this.advance(); @@ -387,12 +336,9 @@ class _Scanner { } } -function isWhitespace(code: number): boolean { - return (code >= $TAB && code <= $SPACE) || (code == $NBSP); -} - function isIdentifierStart(code: number): boolean { - return ($a <= code && code <= $z) || ($A <= code && code <= $Z) || (code == $_) || (code == $$); + return (chars.$a <= code && code <= chars.$z) || (chars.$A <= code && code <= chars.$Z) || + (code == chars.$_) || (code == chars.$$); } export function isIdentifier(input: string): boolean { @@ -400,7 +346,7 @@ export function isIdentifier(input: string): boolean { var scanner = new _Scanner(input); if (!isIdentifierStart(scanner.peek)) return false; scanner.advance(); - while (scanner.peek !== $EOF) { + while (scanner.peek !== chars.$EOF) { if (!isIdentifierPart(scanner.peek)) return false; scanner.advance(); } @@ -408,48 +354,35 @@ export function isIdentifier(input: string): boolean { } function isIdentifierPart(code: number): boolean { - return ($a <= code && code <= $z) || ($A <= code && code <= $Z) || ($0 <= code && code <= $9) || - (code == $_) || (code == $$); -} - -function isDigit(code: number): boolean { - return $0 <= code && code <= $9; + return chars.isAsciiLetter(code) || chars.isDigit(code) || (code == chars.$_) || + (code == chars.$$); } function isExponentStart(code: number): boolean { - return code == $e || code == $E; + return code == chars.$e || code == chars.$E; } function isExponentSign(code: number): boolean { - return code == $MINUS || code == $PLUS; + return code == chars.$MINUS || code == chars.$PLUS; } export function isQuote(code: number): boolean { - return code === $SQ || code === $DQ || code === $BT; + return code === chars.$SQ || code === chars.$DQ || code === chars.$BT; } function unescape(code: number): number { switch (code) { - case $n: - return $LF; - case $f: - return $FF; - case $r: - return $CR; - case $t: - return $TAB; - case $v: - return $VTAB; + case chars.$n: + return chars.$LF; + case chars.$f: + return chars.$FF; + case chars.$r: + return chars.$CR; + case chars.$t: + return chars.$TAB; + case chars.$v: + return chars.$VTAB; default: return code; } -} - -var OPERATORS = SetWrapper.createFromList([ - '+', '-', '*', '/', '%', '^', '=', '==', '!=', '===', '!==', '<', - '>', '<=', '>=', '&&', '||', '&', '|', '!', '?', '#', '?.' -]); - - -var KEYWORDS = - SetWrapper.createFromList(['var', 'let', 'null', 'undefined', 'true', 'false', 'if', 'else']); +} \ No newline at end of file diff --git a/modules/@angular/compiler/src/expression_parser/parser.ts b/modules/@angular/compiler/src/expression_parser/parser.ts index a4834f2e99..eff52a71e7 100644 --- a/modules/@angular/compiler/src/expression_parser/parser.ts +++ b/modules/@angular/compiler/src/expression_parser/parser.ts @@ -1,12 +1,13 @@ import {Injectable} from '@angular/core'; +import * as chars from '../chars'; import {ListWrapper} from '../facade/collection'; import {BaseException} from '../facade/exceptions'; import {RegExpWrapper, StringWrapper, escapeRegExp, isBlank, isPresent} from '../facade/lang'; import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../interpolation_config'; import {AST, ASTWithSource, AstVisitor, Binary, BindingPipe, Chain, Conditional, EmptyExpr, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead, TemplateBinding} from './ast'; -import {$COLON, $COMMA, $LBRACE, $LBRACKET, $LPAREN, $PERIOD, $RBRACE, $RBRACKET, $RPAREN, $SEMICOLON, $SLASH, EOF, Lexer, Token, isIdentifier, isQuote} from './lexer'; +import {EOF, Lexer, Token, isIdentifier, isQuote} from './lexer'; var _implicitReceiver = new ImplicitReceiver(); @@ -152,7 +153,7 @@ export class Parser { let char = StringWrapper.charCodeAt(input, i); let nextChar = StringWrapper.charCodeAt(input, i + 1); - if (char === $SLASH && nextChar == $SLASH && isBlank(outerQuote)) return i; + if (char === chars.$SLASH && nextChar == chars.$SLASH && isBlank(outerQuote)) return i; if (outerQuote === char) { outerQuote = null; @@ -267,11 +268,11 @@ export class _ParseAST { var expr = this.parsePipe(); exprs.push(expr); - if (this.optionalCharacter($SEMICOLON)) { + if (this.optionalCharacter(chars.$SEMICOLON)) { if (!this.parseAction) { this.error('Binding expression cannot contain chained expression'); } - while (this.optionalCharacter($SEMICOLON)) { + while (this.optionalCharacter(chars.$SEMICOLON)) { } // read all semicolons } else if (this.index < this.tokens.length) { this.error(`Unexpected token '${this.next}'`); @@ -292,7 +293,7 @@ export class _ParseAST { do { var name = this.expectIdentifierOrKeyword(); var args: AST[] = []; - while (this.optionalCharacter($COLON)) { + while (this.optionalCharacter(chars.$COLON)) { args.push(this.parseExpression()); } result = new BindingPipe(result, name, args); @@ -310,7 +311,7 @@ export class _ParseAST { if (this.optionalOperator('?')) { var yes = this.parsePipe(); - if (!this.optionalCharacter($COLON)) { + if (!this.optionalCharacter(chars.$COLON)) { var end = this.inputIndex; var expression = this.input.substring(start, end); this.error(`Conditional expression ${expression} requires all 3 expressions`); @@ -421,15 +422,15 @@ export class _ParseAST { parseCallChain(): AST { var result = this.parsePrimary(); while (true) { - if (this.optionalCharacter($PERIOD)) { + if (this.optionalCharacter(chars.$PERIOD)) { result = this.parseAccessMemberOrMethodCall(result, false); } else if (this.optionalOperator('?.')) { result = this.parseAccessMemberOrMethodCall(result, true); - } else if (this.optionalCharacter($LBRACKET)) { + } else if (this.optionalCharacter(chars.$LBRACKET)) { var key = this.parsePipe(); - this.expectCharacter($RBRACKET); + this.expectCharacter(chars.$RBRACKET); if (this.optionalOperator('=')) { var value = this.parseConditional(); result = new KeyedWrite(result, key, value); @@ -437,9 +438,9 @@ export class _ParseAST { result = new KeyedRead(result, key); } - } else if (this.optionalCharacter($LPAREN)) { + } else if (this.optionalCharacter(chars.$LPAREN)) { var args = this.parseCallArguments(); - this.expectCharacter($RPAREN); + this.expectCharacter(chars.$RPAREN); result = new FunctionCall(result, args); } else { @@ -449,9 +450,9 @@ export class _ParseAST { } parsePrimary(): AST { - if (this.optionalCharacter($LPAREN)) { + if (this.optionalCharacter(chars.$LPAREN)) { let result = this.parsePipe(); - this.expectCharacter($RPAREN); + this.expectCharacter(chars.$RPAREN); return result; } else if (this.next.isKeywordNull() || this.next.isKeywordUndefined()) { this.advance(); @@ -465,12 +466,12 @@ export class _ParseAST { this.advance(); return new LiteralPrimitive(false); - } else if (this.optionalCharacter($LBRACKET)) { - var elements = this.parseExpressionList($RBRACKET); - this.expectCharacter($RBRACKET); + } else if (this.optionalCharacter(chars.$LBRACKET)) { + var elements = this.parseExpressionList(chars.$RBRACKET); + this.expectCharacter(chars.$RBRACKET); return new LiteralArray(elements); - } else if (this.next.isCharacter($LBRACE)) { + } else if (this.next.isCharacter(chars.$LBRACE)) { return this.parseLiteralMap(); } else if (this.next.isIdentifier()) { @@ -501,7 +502,7 @@ export class _ParseAST { if (!this.next.isCharacter(terminator)) { do { result.push(this.parsePipe()); - } while (this.optionalCharacter($COMMA)); + } while (this.optionalCharacter(chars.$COMMA)); } return result; } @@ -509,15 +510,15 @@ export class _ParseAST { parseLiteralMap(): LiteralMap { var keys: string[] = []; var values: AST[] = []; - this.expectCharacter($LBRACE); - if (!this.optionalCharacter($RBRACE)) { + this.expectCharacter(chars.$LBRACE); + if (!this.optionalCharacter(chars.$RBRACE)) { do { var key = this.expectIdentifierOrKeywordOrString(); keys.push(key); - this.expectCharacter($COLON); + this.expectCharacter(chars.$COLON); values.push(this.parsePipe()); - } while (this.optionalCharacter($COMMA)); - this.expectCharacter($RBRACE); + } while (this.optionalCharacter(chars.$COMMA)); + this.expectCharacter(chars.$RBRACE); } return new LiteralMap(keys, values); } @@ -525,9 +526,9 @@ export class _ParseAST { parseAccessMemberOrMethodCall(receiver: AST, isSafe: boolean = false): AST { let id = this.expectIdentifierOrKeyword(); - if (this.optionalCharacter($LPAREN)) { + if (this.optionalCharacter(chars.$LPAREN)) { let args = this.parseCallArguments(); - this.expectCharacter($RPAREN); + this.expectCharacter(chars.$RPAREN); return isSafe ? new SafeMethodCall(receiver, id, args) : new MethodCall(receiver, id, args); } else { @@ -555,11 +556,11 @@ export class _ParseAST { } parseCallArguments(): BindingPipe[] { - if (this.next.isCharacter($RPAREN)) return []; + if (this.next.isCharacter(chars.$RPAREN)) return []; var positionals: AST[] = []; do { positionals.push(this.parsePipe()); - } while (this.optionalCharacter($COMMA)); + } while (this.optionalCharacter(chars.$COMMA)); return positionals as BindingPipe[]; } @@ -605,7 +606,7 @@ export class _ParseAST { key = prefix + key[0].toUpperCase() + key.substring(1); } } - this.optionalCharacter($COLON); + this.optionalCharacter(chars.$COLON); var name: string = null; var expression: ASTWithSource = null; if (keyIsVar) { @@ -623,8 +624,8 @@ export class _ParseAST { expression = new ASTWithSource(ast, source, this.location); } bindings.push(new TemplateBinding(key, keyIsVar, name, expression)); - if (!this.optionalCharacter($SEMICOLON)) { - this.optionalCharacter($COMMA); + if (!this.optionalCharacter(chars.$SEMICOLON)) { + this.optionalCharacter(chars.$COMMA); } } return new TemplateBindingParseResult(bindings, warnings); diff --git a/modules/@angular/compiler/src/html_lexer.ts b/modules/@angular/compiler/src/html_lexer.ts index 2211035b99..b10431dd13 100644 --- a/modules/@angular/compiler/src/html_lexer.ts +++ b/modules/@angular/compiler/src/html_lexer.ts @@ -266,13 +266,13 @@ class _HtmlTokenizer { } } - private _attemptCharCodeUntilFn(predicate: Function) { + private _attemptCharCodeUntilFn(predicate: (code: number) => boolean) { while (!predicate(this._peek)) { this._advance(); } } - private _requireCharCodeUntilFn(predicate: Function, len: number) { + private _requireCharCodeUntilFn(predicate: (code: number) => boolean, len: number) { var start = this._getLocation(); this._attemptCharCodeUntilFn(predicate); if (this._index - start.offset < len) { @@ -402,7 +402,7 @@ class _HtmlTokenizer { let savedPos = this._savePosition(); let lowercaseTagName: string; try { - if (!isAsciiLetter(this._peek)) { + if (!chars.isAsciiLetter(this._peek)) { throw this._createError(unexpectedCharacterErrorMsg(this._peek), this._getSpan()); } var nameStart = this._index; @@ -635,16 +635,12 @@ class _HtmlTokenizer { } function isNotWhitespace(code: number): boolean { - return !isWhitespace(code) || code === chars.$EOF; -} - -function isWhitespace(code: number): boolean { - return (code >= chars.$TAB && code <= chars.$SPACE) || (code === chars.$NBSP); + return !chars.isWhitespace(code) || code === chars.$EOF; } function isNameEnd(code: number): boolean { - return isWhitespace(code) || code === chars.$GT || code === chars.$SLASH || code === chars.$SQ || - code === chars.$DQ || code === chars.$EQ; + return chars.isWhitespace(code) || code === chars.$GT || code === chars.$SLASH || + code === chars.$SQ || code === chars.$DQ || code === chars.$EQ; } function isPrefixEnd(code: number): boolean { @@ -653,11 +649,11 @@ function isPrefixEnd(code: number): boolean { } function isDigitEntityEnd(code: number): boolean { - return code == chars.$SEMICOLON || code == chars.$EOF || !isAsciiHexDigit(code); + return code == chars.$SEMICOLON || code == chars.$EOF || !chars.isAsciiHexDigit(code); } function isNamedEntityEnd(code: number): boolean { - return code == chars.$SEMICOLON || code == chars.$EOF || !isAsciiLetter(code); + return code == chars.$SEMICOLON || code == chars.$EOF || !chars.isAsciiLetter(code); } function isExpansionFormStart(input: string, offset: number, interpolationStart: string): boolean { @@ -668,16 +664,7 @@ function isExpansionFormStart(input: string, offset: number, interpolationStart: } function isExpansionCaseStart(peek: number): boolean { - return peek === chars.$EQ || isAsciiLetter(peek); -} - -function isAsciiLetter(code: number): boolean { - return code >= chars.$a && code <= chars.$z || code >= chars.$A && code <= chars.$Z; -} - -function isAsciiHexDigit(code: number): boolean { - return code >= chars.$a && code <= chars.$f || code >= chars.$A && code <= chars.$F || - code >= chars.$0 && code <= chars.$9; + return peek === chars.$EQ || chars.isAsciiLetter(peek); } function compareCharCodeCaseInsensitive(code1: number, code2: number): boolean {