scan method
Implementation
Token scan() {
seenLinebreak = false;
scanLoop:
while (true) {
int x = current;
tokenStart = index;
tokenLine = currentLine;
switch (x) {
case char.NULL:
return emitToken(Token
.EOF); // (will produce infinite EOF tokens if pressed for more tokens)
case char
.SPACE: // Note: Exotic whitespace symbols are handled in the default clause.
case char.TAB:
++index;
continue;
case char.CR:
seenLinebreak = true;
++currentLine;
x = next();
if (x == char.LF) {
++index; // count as single linebreak
}
continue;
case char.LF:
case char.LS:
case char.PS:
seenLinebreak = true;
++currentLine;
++index;
continue;
case char.SLASH:
x = next(); // consume "/"
if (x == char.SLASH) {
// "//" comment
x = next();
while (!isEOL(x)) {
x = next();
}
continue; // line number will be when reading the LF,CR,LS,PS or EOF
}
if (x == char.STAR) {
// "/*" comment
x = current;
while (true) {
switch (x) {
case char.STAR:
x = next();
if (x == char.SLASH) {
++index; // skip final slash
continue scanLoop; // Finished block comment.
}
break;
case char.NULL:
fail("Unterminated block comment");
break;
case char.CR:
++currentLine;
x = next();
if (x == char.LF) {
x = next(); // count as one line break
}
break;
case char.LS:
case char.LF:
case char.PS:
++currentLine;
x = next();
break;
default:
x = next();
}
}
}
// parser will recognize these as potential regexp heads
if (x == char.EQ) {
// "/="
++index;
return emitToken(Token.ASSIGN, '/=');
}
return emitToken(Token.BINARY, '/')
..binaryPrecedence = Precedence.MULTIPLICATIVE;
case char.PLUS:
x = next();
if (x == char.PLUS) {
++index;
return emitToken(Token.UPDATE, '++');
}
if (x == char.EQ) {
++index;
return emitToken(Token.ASSIGN, '+=');
}
return emitToken(Token.UNARY, '+')
..binaryPrecedence = Precedence.ADDITIVE;
case char.MINUS:
x = next();
if (x == char.MINUS) {
++index;
return emitToken(Token.UPDATE, '--');
}
if (x == char.EQ) {
++index;
return emitToken(Token.ASSIGN, '-=');
}
return emitToken(Token.UNARY, '-')
..binaryPrecedence = Precedence.ADDITIVE;
case char.STAR:
x = next();
if (x == char.EQ) {
++index;
return emitToken(Token.ASSIGN, '*=');
}
return emitToken(Token.BINARY, '*')
..binaryPrecedence = Precedence.MULTIPLICATIVE;
case char.PERCENT:
x = next();
if (x == char.EQ) {
++index;
return emitToken(Token.ASSIGN, '%=');
}
return emitToken(Token.BINARY, '%')
..binaryPrecedence = Precedence.MULTIPLICATIVE;
case char.LT:
x = next();
if (x == char.LT) {
x = next();
if (x == char.EQ) {
++index;
return emitToken(Token.ASSIGN, '<<=');
}
return emitToken(Token.BINARY, '<<')
..binaryPrecedence = Precedence.SHIFT;
}
if (x == char.EQ) {
++index;
return emitToken(Token.BINARY, '<=')
..binaryPrecedence = Precedence.RELATIONAL;
}
return emitToken(Token.BINARY, '<')
..binaryPrecedence = Precedence.RELATIONAL;
case char.GT:
x = next();
if (x == char.GT) {
x = next();
if (x == char.GT) {
x = next();
if (x == char.EQ) {
++index;
return emitToken(Token.ASSIGN, '>>>=');
}
return emitToken(Token.BINARY, '>>>')
..binaryPrecedence = Precedence.SHIFT;
}
if (x == char.EQ) {
++index;
return emitToken(Token.ASSIGN, '>>=');
}
return emitToken(Token.BINARY, '>>')
..binaryPrecedence = Precedence.SHIFT;
}
if (x == char.EQ) {
++index;
return emitToken(Token.BINARY, '>=')
..binaryPrecedence = Precedence.RELATIONAL;
}
return emitToken(Token.BINARY, '>')
..binaryPrecedence = Precedence.RELATIONAL;
case char.HAT:
x = next();
if (x == char.EQ) {
++index;
return emitToken(Token.ASSIGN, '^=');
}
return emitToken(Token.BINARY, '^')
..binaryPrecedence = Precedence.BITWISE_XOR;
case char.TILDE:
++index;
return emitToken(Token.UNARY, '~');
case char.BAR:
x = next();
if (x == char.BAR) {
++index;
return emitToken(Token.BINARY, '||')
..binaryPrecedence = Precedence.LOGICAL_OR;
}
if (x == char.EQ) {
++index;
return emitToken(Token.ASSIGN, '|=');
}
return emitToken(Token.BINARY, '|')
..binaryPrecedence = Precedence.BITWISE_OR;
case char.AMPERSAND:
x = next();
if (x == char.AMPERSAND) {
++index;
return emitToken(Token.BINARY, '&&')
..binaryPrecedence = Precedence.LOGICAL_AND;
}
if (x == char.EQ) {
++index;
return emitToken(Token.ASSIGN, '&=');
}
return emitToken(Token.BINARY, '&')
..binaryPrecedence = Precedence.BITWISE_AND;
case char.EQ:
x = next();
if (x == char.EQ) {
x = next();
if (x == char.EQ) {
++index;
return emitToken(Token.BINARY, '===')
..binaryPrecedence = Precedence.EQUALITY;
}
return emitToken(Token.BINARY, '==')
..binaryPrecedence = Precedence.EQUALITY;
}
return emitToken(Token.ASSIGN, '=');
case char.BANG:
x = next();
if (x == char.EQ) {
x = next();
if (x == char.EQ) {
++index;
return emitToken(Token.BINARY, '!==')
..binaryPrecedence = Precedence.EQUALITY;
}
return emitToken(Token.BINARY, '!=')
..binaryPrecedence = Precedence.EQUALITY;
}
return emitToken(Token.UNARY, '!');
case char.DOT:
x = next();
if (isDigit(x)) {
return scanDecimalPart(x);
}
return emitToken(Token.DOT);
case char.SQUOTE:
case char.DQUOTE:
case char.BACKTICK:
return scanStringLiteral(x);
case char.LPAREN:
case char.RPAREN:
case char.LBRACKET:
case char.RBRACKET:
case char.LBRACE:
case char.RBRACE:
case char.COMMA:
case char.COLON:
case char.SEMICOLON:
case char.QUESTION:
++index;
return emitToken(x);
case char.BACKSLASH:
return scanComplexName(x);
default:
if (isNameStart(x)) return scanName(x);
if (isDigit(x)) return scanNumber(x);
if (isWhitespace(x)) {
++index;
continue;
}
fail(
"Unrecognized character: '${new String.fromCharCode(x)}' (UTF+${x.toRadixString(16)})");
}
}
}