Skip to content

Commit 79f3f3b

Browse files
committed
refactor(Lexer): refactor scanComplexOperator()
1 parent d1b35f9 commit 79f3f3b

File tree

1 file changed

+62
-38
lines changed
  • modules/angular2/src/change_detection/parser

1 file changed

+62
-38
lines changed

modules/angular2/src/change_detection/parser/lexer.ts

Lines changed: 62 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import {Injectable} from 'angular2/src/di/decorators';
22
import {List, ListWrapper, SetWrapper} from "angular2/src/facade/collection";
3-
import {NumberWrapper, StringJoiner, StringWrapper, BaseException} from "angular2/src/facade/lang";
3+
import {
4+
NumberWrapper,
5+
StringJoiner,
6+
StringWrapper,
7+
BaseException,
8+
isPresent
9+
} from "angular2/src/facade/lang";
410

511
export const TOKEN_TYPE_CHARACTER = 1;
612
export const TOKEN_TYPE_IDENTIFIER = 2;
@@ -24,10 +30,10 @@ export class Lexer {
2430
}
2531

2632
export class Token {
27-
constructor(public index: int, public type: int, public numValue: number,
33+
constructor(public index: number, public type: number, public numValue: number,
2834
public strValue: string) {}
2935

30-
isCharacter(code: int): boolean {
36+
isCharacter(code: number): boolean {
3137
return (this.type == TOKEN_TYPE_CHARACTER && this.numValue == code);
3238
}
3339

@@ -63,7 +69,7 @@ export class Token {
6369
}
6470

6571
toString(): string {
66-
var t: int = this.type;
72+
var t: number = this.type;
6773
if (t >= TOKEN_TYPE_CHARACTER && t <= TOKEN_TYPE_STRING) {
6874
return this.strValue;
6975
} else if (t == TOKEN_TYPE_NUMBER) {
@@ -74,27 +80,27 @@ export class Token {
7480
}
7581
}
7682

77-
function newCharacterToken(index: int, code: int): Token {
83+
function newCharacterToken(index: number, code: number): Token {
7884
return new Token(index, TOKEN_TYPE_CHARACTER, code, StringWrapper.fromCharCode(code));
7985
}
8086

81-
function newIdentifierToken(index: int, text: string): Token {
87+
function newIdentifierToken(index: number, text: string): Token {
8288
return new Token(index, TOKEN_TYPE_IDENTIFIER, 0, text);
8389
}
8490

85-
function newKeywordToken(index: int, text: string): Token {
91+
function newKeywordToken(index: number, text: string): Token {
8692
return new Token(index, TOKEN_TYPE_KEYWORD, 0, text);
8793
}
8894

89-
function newOperatorToken(index: int, text: string): Token {
95+
function newOperatorToken(index: number, text: string): Token {
9096
return new Token(index, TOKEN_TYPE_OPERATOR, 0, text);
9197
}
9298

93-
function newStringToken(index: int, text: string): Token {
99+
function newStringToken(index: number, text: string): Token {
94100
return new Token(index, TOKEN_TYPE_STRING, 0, text);
95101
}
96102

97-
function newNumberToken(index: int, n: number): Token {
103+
function newNumberToken(index: number, n: number): Token {
98104
return new Token(index, TOKEN_TYPE_NUMBER, n, "");
99105
}
100106

@@ -160,9 +166,9 @@ export class ScannerError extends BaseException {
160166
}
161167

162168
class _Scanner {
163-
length: int;
164-
peek: int;
165-
index: int;
169+
length: number;
170+
peek: number;
171+
index: number;
166172

167173
constructor(public input: string) {
168174
this.length = input.length;
@@ -200,7 +206,7 @@ class _Scanner {
200206
if (isIdentifierStart(peek)) return this.scanIdentifier();
201207
if (isDigit(peek)) return this.scanNumber(index);
202208

203-
var start: int = index;
209+
var start: number = index;
204210
switch (peek) {
205211
case $PERIOD:
206212
this.advance();
@@ -227,16 +233,18 @@ class _Scanner {
227233
case $CARET:
228234
return this.scanOperator(start, StringWrapper.fromCharCode(peek));
229235
case $QUESTION:
230-
return this.scanComplexOperator(start, $PERIOD, '?', '.');
236+
return this.scanComplexOperator(start, '?', $PERIOD, '.');
231237
case $LT:
232238
case $GT:
239+
return this.scanComplexOperator(start, StringWrapper.fromCharCode(peek), $EQ, '=');
233240
case $BANG:
234241
case $EQ:
235-
return this.scanComplexOperator(start, $EQ, StringWrapper.fromCharCode(peek), '=');
242+
return this.scanComplexOperator(start, StringWrapper.fromCharCode(peek), $EQ, '=', $EQ,
243+
'=');
236244
case $AMPERSAND:
237-
return this.scanComplexOperator(start, $AMPERSAND, '&', '&');
245+
return this.scanComplexOperator(start, '&', $AMPERSAND, '&');
238246
case $BAR:
239-
return this.scanComplexOperator(start, $BAR, '|', '|');
247+
return this.scanComplexOperator(start, '|', $BAR, '|');
240248
case $NBSP:
241249
while (isWhitespace(this.peek)) this.advance();
242250
return this.scanToken();
@@ -246,35 +254,51 @@ class _Scanner {
246254
return null;
247255
}
248256

249-
scanCharacter(start: int, code: int): Token {
257+
scanCharacter(start: number, code: number): Token {
250258
assert(this.peek == code);
251259
this.advance();
252260
return newCharacterToken(start, code);
253261
}
254262

255263

256-
scanOperator(start: int, str: string): Token {
264+
scanOperator(start: number, str: string): Token {
257265
assert(this.peek == StringWrapper.charCodeAt(str, 0));
258266
assert(SetWrapper.has(OPERATORS, str));
259267
this.advance();
260268
return newOperatorToken(start, str);
261269
}
262270

263-
scanComplexOperator(start: int, code: int, one: string, two: string): Token {
271+
/**
272+
* Tokenize a 2/3 char long operator
273+
*
274+
* @param start start index in the expression
275+
* @param one first symbol (always part of the operator)
276+
* @param twoCode code point for the second symbol
277+
* @param two second symbol (part of the operator when the second code point matches)
278+
* @param threeCode code point for the third symbol
279+
* @param three third symbol (part of the operator when provided and matches source expression)
280+
* @returns {Token}
281+
*/
282+
scanComplexOperator(start: number, one: string, twoCode: number, two: string, threeCode?: number,
283+
three?: string): Token {
264284
assert(this.peek == StringWrapper.charCodeAt(one, 0));
265285
this.advance();
266286
var str: string = one;
267-
while (this.peek == code) {
287+
if (this.peek == twoCode) {
268288
this.advance();
269289
str += two;
270290
}
291+
if (isPresent(threeCode) && this.peek == threeCode) {
292+
this.advance();
293+
str += three;
294+
}
271295
assert(SetWrapper.has(OPERATORS, str));
272296
return newOperatorToken(start, str);
273297
}
274298

275299
scanIdentifier(): Token {
276300
assert(isIdentifierStart(this.peek));
277-
var start: int = this.index;
301+
var start: number = this.index;
278302
this.advance();
279303
while (isIdentifierPart(this.peek)) this.advance();
280304
var str: string = this.input.substring(start, this.index);
@@ -285,7 +309,7 @@ class _Scanner {
285309
}
286310
}
287311

288-
scanNumber(start: int): Token {
312+
scanNumber(start: number): Token {
289313
assert(isDigit(this.peek));
290314
var simple: boolean = (this.index === start);
291315
this.advance(); // Skip initial digit.
@@ -313,20 +337,20 @@ class _Scanner {
313337

314338
scanString(): Token {
315339
assert(this.peek == $SQ || this.peek == $DQ);
316-
var start: int = this.index;
317-
var quote: int = this.peek;
340+
var start: number = this.index;
341+
var quote: number = this.peek;
318342
this.advance(); // Skip initial quote.
319343

320344
var buffer: StringJoiner;
321-
var marker: int = this.index;
345+
var marker: number = this.index;
322346
var input: string = this.input;
323347

324348
while (this.peek != quote) {
325349
if (this.peek == $BACKSLASH) {
326350
if (buffer == null) buffer = new StringJoiner();
327351
buffer.add(input.substring(marker, this.index));
328352
this.advance();
329-
var unescapedCode: int;
353+
var unescapedCode: number;
330354
if (this.peek == $u) {
331355
// 4 character hex code for unicode character.
332356
var hex: string = input.substring(this.index + 1, this.index + 5);
@@ -335,7 +359,7 @@ class _Scanner {
335359
} catch (e) {
336360
this.error(`Invalid unicode escape [\\u${hex}]`, 0);
337361
}
338-
for (var i: int = 0; i < 5; i++) {
362+
for (var i: number = 0; i < 5; i++) {
339363
this.advance();
340364
}
341365
} else {
@@ -363,39 +387,39 @@ class _Scanner {
363387
return newStringToken(start, unescaped);
364388
}
365389

366-
error(message: string, offset: int) {
367-
var position: int = this.index + offset;
390+
error(message: string, offset: number) {
391+
var position: number = this.index + offset;
368392
throw new ScannerError(
369393
`Lexer Error: ${message} at column ${position} in expression [${this.input}]`);
370394
}
371395
}
372396

373-
function isWhitespace(code: int): boolean {
397+
function isWhitespace(code: number): boolean {
374398
return (code >= $TAB && code <= $SPACE) || (code == $NBSP);
375399
}
376400

377-
function isIdentifierStart(code: int): boolean {
401+
function isIdentifierStart(code: number): boolean {
378402
return ($a <= code && code <= $z) || ($A <= code && code <= $Z) || (code == $_) || (code == $$);
379403
}
380404

381-
function isIdentifierPart(code: int): boolean {
405+
function isIdentifierPart(code: number): boolean {
382406
return ($a <= code && code <= $z) || ($A <= code && code <= $Z) || ($0 <= code && code <= $9) ||
383407
(code == $_) || (code == $$);
384408
}
385409

386-
function isDigit(code: int): boolean {
410+
function isDigit(code: number): boolean {
387411
return $0 <= code && code <= $9;
388412
}
389413

390-
function isExponentStart(code: int): boolean {
414+
function isExponentStart(code: number): boolean {
391415
return code == $e || code == $E;
392416
}
393417

394-
function isExponentSign(code: int): boolean {
418+
function isExponentSign(code: number): boolean {
395419
return code == $MINUS || code == $PLUS;
396420
}
397421

398-
function unescape(code: int): int {
422+
function unescape(code: number): number {
399423
switch (code) {
400424
case $n:
401425
return $LF;

0 commit comments

Comments
 (0)