| Index: pkg/analyzer-experimental/lib/src/generated/scanner.dart
|
| diff --git a/pkg/analyzer-experimental/lib/src/generated/scanner.dart b/pkg/analyzer-experimental/lib/src/generated/scanner.dart
|
| index f2bd02d28705a58e4fb2e39c56f0f4bb54adcce3..51fdf35ea3d4a80e0f0ce7e496e4e21cf37827d5 100644
|
| --- a/pkg/analyzer-experimental/lib/src/generated/scanner.dart
|
| +++ b/pkg/analyzer-experimental/lib/src/generated/scanner.dart
|
| @@ -10,6 +10,163 @@ import 'error.dart';
|
| import 'instrumentation.dart';
|
|
|
| /**
|
| + * Instances of the abstract class {@code KeywordState} represent a state in a state machine used to
|
| + * scan keywords.
|
| + */
|
| +class KeywordState {
|
| + /**
|
| + * An empty transition table used by leaf states.
|
| + */
|
| + static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26);
|
| + /**
|
| + * The initial state in the state machine.
|
| + */
|
| + static KeywordState KEYWORD_STATE = createKeywordStateTable();
|
| + /**
|
| + * Create the next state in the state machine where we have already recognized the subset of
|
| + * strings in the given array of strings starting at the given offset and having the given length.
|
| + * All of these strings have a common prefix and the next character is at the given start index.
|
| + * @param start the index of the character in the strings used to transition to a new state
|
| + * @param strings an array containing all of the strings that will be recognized by the state
|
| + * machine
|
| + * @param offset the offset of the first string in the array that has the prefix that is assumed
|
| + * to have been recognized by the time we reach the state being built
|
| + * @param length the number of strings in the array that pass through the state being built
|
| + * @return the state that was created
|
| + */
|
| + static KeywordState computeKeywordStateTable(int start, List<String> strings, int offset, int length12) {
|
| + List<KeywordState> result = new List<KeywordState>(26);
|
| + assert(length12 != 0);
|
| + int chunk = 0x0;
|
| + int chunkStart = -1;
|
| + bool isLeaf = false;
|
| + for (int i = offset; i < offset + length12; i++) {
|
| + if (strings[i].length == start) {
|
| + isLeaf = true;
|
| + }
|
| + if (strings[i].length > start) {
|
| + int c = strings[i].codeUnitAt(start);
|
| + if (chunk != c) {
|
| + if (chunkStart != -1) {
|
| + result[chunk - 0x61] = computeKeywordStateTable(start + 1, strings, chunkStart, i - chunkStart);
|
| + }
|
| + chunkStart = i;
|
| + chunk = c;
|
| + }
|
| + }
|
| + }
|
| + if (chunkStart != -1) {
|
| + assert(result[chunk - 0x61] == null);
|
| + result[chunk - 0x61] = computeKeywordStateTable(start + 1, strings, chunkStart, offset + length12 - chunkStart);
|
| + } else {
|
| + assert(length12 == 1);
|
| + return new KeywordState(_EMPTY_TABLE, strings[offset]);
|
| + }
|
| + if (isLeaf) {
|
| + return new KeywordState(result, strings[offset]);
|
| + } else {
|
| + return new KeywordState(result, null);
|
| + }
|
| + }
|
| + /**
|
| + * Create the initial state in the state machine.
|
| + * @return the state that was created
|
| + */
|
| + static KeywordState createKeywordStateTable() {
|
| + List<Keyword> values2 = Keyword.values;
|
| + List<String> strings = new List<String>(values2.length);
|
| + for (int i = 0; i < values2.length; i++) {
|
| + strings[i] = values2[i].syntax;
|
| + }
|
| + strings.sort();
|
| + return computeKeywordStateTable(0, strings, 0, strings.length);
|
| + }
|
| + /**
|
| + * A table mapping characters to the states to which those characters will transition. (The index
|
| + * into the array is the offset from the character {@code 'a'} to the transitioning character.)
|
| + */
|
| + List<KeywordState> _table;
|
| + /**
|
| + * The keyword that is recognized by this state, or {@code null} if this state is not a terminal
|
| + * state.
|
| + */
|
| + Keyword _keyword2;
|
| + /**
|
| + * Initialize a newly created state to have the given transitions and to recognize the keyword
|
| + * with the given syntax.
|
| + * @param table a table mapping characters to the states to which those characters will transition
|
| + * @param syntax the syntax of the keyword that is recognized by the state
|
| + */
|
| + KeywordState(List<KeywordState> table, String syntax) {
|
| + this._table = table;
|
| + this._keyword2 = (syntax == null) ? null : Keyword.keywords[syntax];
|
| + }
|
| + /**
|
| + * Return the keyword that was recognized by this state, or {@code null} if this state does not
|
| + * recognized a keyword.
|
| + * @return the keyword that was matched by reaching this state
|
| + */
|
| + Keyword keyword() => _keyword2;
|
| + /**
|
| + * Return the state that follows this state on a transition of the given character, or{@code null} if there is no valid state reachable from this state with such a transition.
|
| + * @param c the character used to transition from this state to another state
|
| + * @return the state that follows this state on a transition of the given character
|
| + */
|
| + KeywordState next(int c) => _table[c - 0x61];
|
| +}
|
| +/**
|
| + * The enumeration {@code ScannerErrorCode} defines the error codes used for errors detected by the
|
| + * scanner.
|
| + */
|
| +class ScannerErrorCode implements ErrorCode {
|
| + static final ScannerErrorCode ILLEGAL_CHARACTER = new ScannerErrorCode('ILLEGAL_CHARACTER', 0, "Illegal character %x");
|
| + static final ScannerErrorCode MISSING_DIGIT = new ScannerErrorCode('MISSING_DIGIT', 1, "Decimal digit expected");
|
| + static final ScannerErrorCode MISSING_HEX_DIGIT = new ScannerErrorCode('MISSING_HEX_DIGIT', 2, "Hexidecimal digit expected");
|
| + static final ScannerErrorCode MISSING_QUOTE = new ScannerErrorCode('MISSING_QUOTE', 3, "Expected quote (' or \")");
|
| + static final ScannerErrorCode UNTERMINATED_MULTI_LINE_COMMENT = new ScannerErrorCode('UNTERMINATED_MULTI_LINE_COMMENT', 4, "Unterminated multi-line comment");
|
| + static final ScannerErrorCode UNTERMINATED_STRING_LITERAL = new ScannerErrorCode('UNTERMINATED_STRING_LITERAL', 5, "Unterminated string literal");
|
| + static final List<ScannerErrorCode> values = [ILLEGAL_CHARACTER, MISSING_DIGIT, MISSING_HEX_DIGIT, MISSING_QUOTE, UNTERMINATED_MULTI_LINE_COMMENT, UNTERMINATED_STRING_LITERAL];
|
| + final String __name;
|
| + final int __ordinal;
|
| + /**
|
| + * The message template used to create the message to be displayed for this error.
|
| + */
|
| + String _message;
|
| + /**
|
| + * Initialize a newly created error code to have the given message.
|
| + * @param message the message template used to create the message to be displayed for this error
|
| + */
|
| + ScannerErrorCode(this.__name, this.__ordinal, String message) {
|
| + this._message = message;
|
| + }
|
| + ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
|
| + String get message => _message;
|
| + ErrorType get type => ErrorType.SYNTACTIC_ERROR;
|
| + bool needsRecompilation() => true;
|
| + String toString() => __name;
|
| +}
|
| +/**
|
| + * Instances of the class {@code TokenWithComment} represent a string token that is preceded by
|
| + * comments.
|
| + */
|
| +class StringTokenWithComment extends StringToken {
|
| + /**
|
| + * The first comment in the list of comments that precede this token.
|
| + */
|
| + Token _precedingComment;
|
| + /**
|
| + * Initialize a newly created token to have the given type and offset and to be preceded by the
|
| + * comments reachable from the given comment.
|
| + * @param type the type of the token
|
| + * @param offset the offset from the beginning of the file to the first character in the token
|
| + * @param precedingComment the first comment in the list of comments that precede this token
|
| + */
|
| + StringTokenWithComment(TokenType type, String value, int offset, Token precedingComment) : super(type, value, offset) {
|
| + this._precedingComment = precedingComment;
|
| + }
|
| + Token get precedingComments => _precedingComment;
|
| +}
|
| +/**
|
| * The enumeration {@code Keyword} defines the keywords in the Dart programming language.
|
| */
|
| class Keyword {
|
| @@ -92,10 +249,10 @@ class Keyword {
|
| * @param syntax the lexeme for the keyword
|
| */
|
| Keyword.con1(String ___name, int ___ordinal, String syntax) {
|
| - _jtd_constructor_224_impl(___name, ___ordinal, syntax);
|
| + _jtd_constructor_259_impl(___name, ___ordinal, syntax);
|
| }
|
| - _jtd_constructor_224_impl(String ___name, int ___ordinal, String syntax) {
|
| - _jtd_constructor_225_impl(___name, ___ordinal, syntax, false);
|
| + _jtd_constructor_259_impl(String ___name, int ___ordinal, String syntax) {
|
| + _jtd_constructor_260_impl(___name, ___ordinal, syntax, false);
|
| }
|
| /**
|
| * Initialize a newly created keyword to have the given syntax. The keyword is a pseudo-keyword if
|
| @@ -104,9 +261,9 @@ class Keyword {
|
| * @param isPseudoKeyword {@code true} if this keyword is a pseudo-keyword
|
| */
|
| Keyword.con2(String ___name, int ___ordinal, String syntax2, bool isPseudoKeyword) {
|
| - _jtd_constructor_225_impl(___name, ___ordinal, syntax2, isPseudoKeyword);
|
| + _jtd_constructor_260_impl(___name, ___ordinal, syntax2, isPseudoKeyword);
|
| }
|
| - _jtd_constructor_225_impl(String ___name, int ___ordinal, String syntax2, bool isPseudoKeyword) {
|
| + _jtd_constructor_260_impl(String ___name, int ___ordinal, String syntax2, bool isPseudoKeyword) {
|
| __name = ___name;
|
| __ordinal = ___ordinal;
|
| this._syntax = syntax2;
|
| @@ -126,898 +283,192 @@ class Keyword {
|
| String toString() => __name;
|
| }
|
| /**
|
| - * Instances of the class {@code CharBufferScanner} implement a scanner that reads from a character
|
| - * buffer. The scanning logic is in the superclass.
|
| + * The abstract class {@code AbstractScanner} implements a scanner for Dart code. Subclasses are
|
| + * required to implement the interface used to access the characters being scanned.
|
| + * <p>
|
| + * The lexical structure of Dart is ambiguous without knowledge of the context in which a token is
|
| + * being scanned. For example, without context we cannot determine whether source of the form "<<"
|
| + * should be scanned as a single left-shift operator or as two left angle brackets. This scanner
|
| + * does not have any context, so it always resolves such conflicts by scanning the longest possible
|
| + * token.
|
| */
|
| -class CharBufferScanner extends AbstractScanner {
|
| +abstract class AbstractScanner {
|
| /**
|
| - * The buffer from which characters will be read.
|
| + * The source being scanned.
|
| */
|
| - CharBuffer _buffer;
|
| + Source _source;
|
| /**
|
| - * The number of characters in the buffer.
|
| + * The error listener that will be informed of any errors that are found during the scan.
|
| */
|
| - int _bufferLength = 0;
|
| + AnalysisErrorListener _errorListener;
|
| /**
|
| - * The index of the last character that was read.
|
| + * The token pointing to the head of the linked list of tokens.
|
| */
|
| - int _charOffset = 0;
|
| + Token _tokens;
|
| /**
|
| - * Initialize a newly created scanner to scan the characters in the given character buffer.
|
| - * @param source the source being scanned
|
| - * @param buffer the buffer from which characters will be read
|
| - * @param errorListener the error listener that will be informed of any errors that are found
|
| + * The last token that was scanned.
|
| */
|
| - CharBufferScanner(Source source, CharBuffer buffer, AnalysisErrorListener errorListener) : super(source, errorListener) {
|
| - this._buffer = buffer;
|
| - this._bufferLength = buffer.length();
|
| - this._charOffset = -1;
|
| - }
|
| - int get offset => _charOffset;
|
| - int advance() {
|
| - if (_charOffset + 1 >= _bufferLength) {
|
| - return -1;
|
| - }
|
| - return _buffer.charAt(++_charOffset);
|
| - }
|
| - String getString(int start, int endDelta) => _buffer.subSequence(start, _charOffset + 1 + endDelta).toString();
|
| - int peek() {
|
| - if (_charOffset + 1 >= _buffer.length()) {
|
| - return -1;
|
| - }
|
| - return _buffer.charAt(_charOffset + 1);
|
| - }
|
| -}
|
| -/**
|
| - * Instances of the class {@code TokenWithComment} represent a normal token that is preceded by
|
| - * comments.
|
| - */
|
| -class TokenWithComment extends Token {
|
| + Token _tail;
|
| /**
|
| - * The first comment in the list of comments that precede this token.
|
| + * The first token in the list of comment tokens found since the last non-comment token.
|
| */
|
| - Token _precedingComment;
|
| + Token _firstComment;
|
| /**
|
| - * Initialize a newly created token to have the given type and offset and to be preceded by the
|
| - * comments reachable from the given comment.
|
| - * @param type the type of the token
|
| - * @param offset the offset from the beginning of the file to the first character in the token
|
| - * @param precedingComment the first comment in the list of comments that precede this token
|
| + * The last token in the list of comment tokens found since the last non-comment token.
|
| */
|
| - TokenWithComment(TokenType type, int offset, Token precedingComment) : super(type, offset) {
|
| - this._precedingComment = precedingComment;
|
| - }
|
| - Token get precedingComments => _precedingComment;
|
| -}
|
| -/**
|
| - * Instances of the class {@code Token} represent a token that was scanned from the input. Each
|
| - * token knows which token follows it, acting as the head of a linked list of tokens.
|
| - */
|
| -class Token {
|
| + Token _lastComment;
|
| /**
|
| - * The type of the token.
|
| + * The index of the first character of the current token.
|
| */
|
| - TokenType _type;
|
| + int _tokenStart = 0;
|
| /**
|
| - * The offset from the beginning of the file to the first character in the token.
|
| + * A list containing the offsets of the first character of each line in the source code.
|
| */
|
| - int _offset = 0;
|
| + List<int> _lineStarts = new List<int>();
|
| /**
|
| - * The previous token in the token stream.
|
| + * A list, treated something like a stack, of tokens representing the beginning of a matched pair.
|
| + * It is used to pair the end tokens with the begin tokens.
|
| */
|
| - Token _previous;
|
| + List<BeginToken> _groupingStack = new List<BeginToken>();
|
| /**
|
| - * The next token in the token stream.
|
| + * A flag indicating whether any unmatched groups were found during the parse.
|
| */
|
| - Token _next;
|
| + bool _hasUnmatchedGroups2 = false;
|
| /**
|
| - * Initialize a newly created token to have the given type and offset.
|
| - * @param type the type of the token
|
| - * @param offset the offset from the beginning of the file to the first character in the token
|
| + * A non-breaking space, which is allowed by this scanner as a white-space character.
|
| */
|
| - Token(TokenType type, int offset) {
|
| - this._type = type;
|
| - this._offset = offset;
|
| - }
|
| - /**
|
| - * Return the offset from the beginning of the file to the character after last character of the
|
| - * token.
|
| - * @return the offset from the beginning of the file to the first character after last character
|
| - * of the token
|
| - */
|
| - int get end => _offset + length;
|
| - /**
|
| - * Return the number of characters in the node's source range.
|
| - * @return the number of characters in the node's source range
|
| - */
|
| - int get length => lexeme.length;
|
| - /**
|
| - * Return the lexeme that represents this token.
|
| - * @return the lexeme that represents this token
|
| - */
|
| - String get lexeme => _type.lexeme;
|
| - /**
|
| - * Return the next token in the token stream.
|
| - * @return the next token in the token stream
|
| - */
|
| - Token get next => _next;
|
| + static int _$NBSP = 160;
|
| /**
|
| - * Return the offset from the beginning of the file to the first character in the token.
|
| - * @return the offset from the beginning of the file to the first character in the token
|
| + * Initialize a newly created scanner.
|
| + * @param source the source being scanned
|
| + * @param errorListener the error listener that will be informed of any errors that are found
|
| */
|
| - int get offset => _offset;
|
| + AbstractScanner(Source source, AnalysisErrorListener errorListener) {
|
| + this._source = source;
|
| + this._errorListener = errorListener;
|
| + _tokens = new Token(TokenType.EOF, -1);
|
| + _tokens.setNext(_tokens);
|
| + _tail = _tokens;
|
| + _tokenStart = -1;
|
| + _lineStarts.add(0);
|
| + }
|
| /**
|
| - * Return the first comment in the list of comments that precede this token, or {@code null} if
|
| - * there are no comments preceding this token. Additional comments can be reached by following the
|
| - * token stream using {@link #getNext()} until {@code null} is returned.
|
| - * @return the first comment in the list of comments that precede this token
|
| + * Return an array containing the offsets of the first character of each line in the source code.
|
| + * @return an array containing the offsets of the first character of each line in the source code
|
| */
|
| - Token get precedingComments => null;
|
| + List<int> get lineStarts => _lineStarts;
|
| /**
|
| - * Return the previous token in the token stream.
|
| - * @return the previous token in the token stream
|
| + * Return the current offset relative to the beginning of the file. Return the initial offset if
|
| + * the scanner has not yet scanned the source code, and one (1) past the end of the source code if
|
| + * the source code has been scanned.
|
| + * @return the current offset of the scanner in the source
|
| */
|
| - Token get previous => _previous;
|
| + int get offset;
|
| /**
|
| - * Return the type of the token.
|
| - * @return the type of the token
|
| + * Return {@code true} if any unmatched groups were found during the parse.
|
| + * @return {@code true} if any unmatched groups were found during the parse
|
| */
|
| - TokenType get type => _type;
|
| + bool hasUnmatchedGroups() => _hasUnmatchedGroups2;
|
| /**
|
| - * Return {@code true} if this token represents an operator.
|
| - * @return {@code true} if this token represents an operator
|
| + * Scan the source code to produce a list of tokens representing the source.
|
| + * @return the first token in the list of tokens that were produced
|
| */
|
| - bool isOperator() => _type.isOperator();
|
| + Token tokenize() {
|
| + int next = advance();
|
| + while (next != -1) {
|
| + next = bigSwitch(next);
|
| + }
|
| + appendEofToken();
|
| + return firstToken();
|
| + }
|
| /**
|
| - * Return {@code true} if this token is a synthetic token. A synthetic token is a token that was
|
| - * introduced by the parser in order to recover from an error in the code. Synthetic tokens always
|
| - * have a length of zero ({@code 0}).
|
| - * @return {@code true} if this token is a synthetic token
|
| + * Advance the current position and return the character at the new current position.
|
| + * @return the character at the new current position
|
| */
|
| - bool isSynthetic() => length == 0;
|
| + int advance();
|
| /**
|
| - * Return {@code true} if this token represents an operator that can be defined by users.
|
| - * @return {@code true} if this token represents an operator that can be defined by users
|
| + * Return the substring of the source code between the start offset and the modified current
|
| + * position. The current position is modified by adding the end delta.
|
| + * @param start the offset to the beginning of the string, relative to the start of the file
|
| + * @param endDelta the number of character after the current location to be included in the
|
| + * string, or the number of characters before the current location to be excluded if the
|
| + * offset is negative
|
| + * @return the specified substring of the source code
|
| */
|
| - bool isUserDefinableOperator() => _type.isUserDefinableOperator();
|
| + String getString(int start, int endDelta);
|
| /**
|
| - * Set the next token in the token stream to the given token. This has the side-effect of setting
|
| - * this token to be the previous token for the given token.
|
| - * @param token the next token in the token stream
|
| - * @return the token that was passed in
|
| + * Return the character at the current position without changing the current position.
|
| + * @return the character at the current position
|
| */
|
| - Token setNext(Token token) {
|
| - _next = token;
|
| - token.previous = this;
|
| - return token;
|
| - }
|
| + int peek();
|
| /**
|
| - * Set the next token in the token stream to the given token without changing which token is the
|
| - * previous token for the given token.
|
| - * @param token the next token in the token stream
|
| - * @return the token that was passed in
|
| + * Record the fact that we are at the beginning of a new line in the source.
|
| */
|
| - Token setNextWithoutSettingPrevious(Token token) {
|
| - _next = token;
|
| - return token;
|
| + void recordStartOfLine() {
|
| + _lineStarts.add(offset);
|
| }
|
| - /**
|
| - * Set the offset from the beginning of the file to the first character in the token to the given
|
| - * offset.
|
| - * @param offset the offset from the beginning of the file to the first character in the token
|
| - */
|
| - void set offset(int offset3) {
|
| - this._offset = offset3;
|
| + void appendBeginToken(TokenType type) {
|
| + BeginToken token;
|
| + if (_firstComment == null) {
|
| + token = new BeginToken(type, _tokenStart);
|
| + } else {
|
| + token = new BeginTokenWithComment(type, _tokenStart, _firstComment);
|
| + _firstComment = null;
|
| + _lastComment = null;
|
| + }
|
| + _tail = _tail.setNext(token);
|
| + _groupingStack.add(token);
|
| }
|
| - String toString() => lexeme;
|
| - /**
|
| - * Return the value of this token. For keyword tokens, this is the keyword associated with the
|
| - * token, for other tokens it is the lexeme associated with the token.
|
| - * @return the value of this token
|
| - */
|
| - Object value() => _type.lexeme;
|
| - /**
|
| - * Set the previous token in the token stream to the given token.
|
| - * @param previous the previous token in the token stream
|
| - */
|
| - void set previous(Token previous2) {
|
| - this._previous = previous2;
|
| + void appendCommentToken(TokenType type, String value) {
|
| + if (_firstComment == null) {
|
| + _firstComment = new StringToken(type, value, _tokenStart);
|
| + _lastComment = _firstComment;
|
| + } else {
|
| + _lastComment = _lastComment.setNext(new StringToken(type, value, _tokenStart));
|
| + }
|
| }
|
| -}
|
| -/**
|
| - * Instances of the class {@code KeywordToken} represent a keyword in the language.
|
| - */
|
| -class KeywordToken extends Token {
|
| - /**
|
| - * The keyword being represented by this token.
|
| - */
|
| - Keyword _keyword;
|
| - /**
|
| - * Initialize a newly created token to represent the given keyword.
|
| - * @param keyword the keyword being represented by this token
|
| - * @param offset the offset from the beginning of the file to the first character in the token
|
| - */
|
| - KeywordToken(Keyword keyword, int offset) : super(TokenType.KEYWORD, offset) {
|
| - this._keyword = keyword;
|
| + void appendEndToken(TokenType type31, TokenType beginType) {
|
| + Token token;
|
| + if (_firstComment == null) {
|
| + token = new Token(type31, _tokenStart);
|
| + } else {
|
| + token = new TokenWithComment(type31, _tokenStart, _firstComment);
|
| + _firstComment = null;
|
| + _lastComment = null;
|
| + }
|
| + _tail = _tail.setNext(token);
|
| + int last = _groupingStack.length - 1;
|
| + if (last >= 0) {
|
| + BeginToken begin = _groupingStack[last];
|
| + if (identical(begin.type, beginType)) {
|
| + begin.endToken = token;
|
| + _groupingStack.removeAt(last);
|
| + }
|
| + }
|
| }
|
| - /**
|
| - * Return the keyword being represented by this token.
|
| - * @return the keyword being represented by this token
|
| - */
|
| - Keyword get keyword => _keyword;
|
| - String get lexeme => _keyword.syntax;
|
| - Keyword value() => _keyword;
|
| -}
|
| -/**
|
| - * Instances of the class {@code StringToken} represent a token whose value is independent of it's
|
| - * type.
|
| - */
|
| -class StringToken extends Token {
|
| - /**
|
| - * The lexeme represented by this token.
|
| - */
|
| - String _value2;
|
| - /**
|
| - * Initialize a newly created token to represent a token of the given type with the given value.
|
| - * @param type the type of the token
|
| - * @param value the lexeme represented by this token
|
| - * @param offset the offset from the beginning of the file to the first character in the token
|
| - */
|
| - StringToken(TokenType type, String value, int offset) : super(type, offset) {
|
| - this._value2 = value;
|
| + void appendEofToken() {
|
| + Token eofToken;
|
| + if (_firstComment == null) {
|
| + eofToken = new Token(TokenType.EOF, offset + 1);
|
| + } else {
|
| + eofToken = new TokenWithComment(TokenType.EOF, offset + 1, _firstComment);
|
| + _firstComment = null;
|
| + _lastComment = null;
|
| + }
|
| + eofToken.setNext(eofToken);
|
| + _tail = _tail.setNext(eofToken);
|
| + if (!_groupingStack.isEmpty) {
|
| + _hasUnmatchedGroups2 = true;
|
| + }
|
| }
|
| - String get lexeme => _value2;
|
| - String value() => _value2;
|
| -}
|
| -/**
|
| - * The enumeration {@code ScannerErrorCode} defines the error codes used for errors detected by the
|
| - * scanner.
|
| - */
|
| -class ScannerErrorCode implements ErrorCode {
|
| - static final ScannerErrorCode ILLEGAL_CHARACTER = new ScannerErrorCode('ILLEGAL_CHARACTER', 0, "Illegal character %x");
|
| - static final ScannerErrorCode MISSING_DIGIT = new ScannerErrorCode('MISSING_DIGIT', 1, "Decimal digit expected");
|
| - static final ScannerErrorCode MISSING_HEX_DIGIT = new ScannerErrorCode('MISSING_HEX_DIGIT', 2, "Hexidecimal digit expected");
|
| - static final ScannerErrorCode MISSING_QUOTE = new ScannerErrorCode('MISSING_QUOTE', 3, "Expected quote (' or \")");
|
| - static final ScannerErrorCode UNTERMINATED_MULTI_LINE_COMMENT = new ScannerErrorCode('UNTERMINATED_MULTI_LINE_COMMENT', 4, "Unterminated multi-line comment");
|
| - static final ScannerErrorCode UNTERMINATED_STRING_LITERAL = new ScannerErrorCode('UNTERMINATED_STRING_LITERAL', 5, "Unterminated string literal");
|
| - static final List<ScannerErrorCode> values = [ILLEGAL_CHARACTER, MISSING_DIGIT, MISSING_HEX_DIGIT, MISSING_QUOTE, UNTERMINATED_MULTI_LINE_COMMENT, UNTERMINATED_STRING_LITERAL];
|
| - final String __name;
|
| - final int __ordinal;
|
| - /**
|
| - * The message template used to create the message to be displayed for this error.
|
| - */
|
| - String _message;
|
| - /**
|
| - * Initialize a newly created error code to have the given message.
|
| - * @param message the message template used to create the message to be displayed for this error
|
| - */
|
| - ScannerErrorCode(this.__name, this.__ordinal, String message) {
|
| - this._message = message;
|
| - }
|
| - ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
|
| - String get message => _message;
|
| - ErrorType get type => ErrorType.SYNTACTIC_ERROR;
|
| - bool needsRecompilation() => true;
|
| - String toString() => __name;
|
| -}
|
| -/**
|
| - * Instances of the class {@code BeginTokenWithComment} represent a begin token that is preceded by
|
| - * comments.
|
| - */
|
| -class BeginTokenWithComment extends BeginToken {
|
| - /**
|
| - * The first comment in the list of comments that precede this token.
|
| - */
|
| - Token _precedingComment;
|
| - /**
|
| - * Initialize a newly created token to have the given type and offset and to be preceded by the
|
| - * comments reachable from the given comment.
|
| - * @param type the type of the token
|
| - * @param offset the offset from the beginning of the file to the first character in the token
|
| - * @param precedingComment the first comment in the list of comments that precede this token
|
| - */
|
| - BeginTokenWithComment(TokenType type, int offset, Token precedingComment) : super(type, offset) {
|
| - this._precedingComment = precedingComment;
|
| - }
|
| - Token get precedingComments => _precedingComment;
|
| -}
|
| -/**
|
| - * The enumeration {@code TokenType} defines the types of tokens that can be returned by the
|
| - * scanner.
|
| - */
|
| -class TokenType {
|
| - /**
|
| - * The type of the token that marks the end of the input.
|
| - */
|
| - static final TokenType EOF = new TokenType_EOF('EOF', 0, null, "");
|
| - static final TokenType DOUBLE = new TokenType.con1('DOUBLE', 1);
|
| - static final TokenType HEXADECIMAL = new TokenType.con1('HEXADECIMAL', 2);
|
| - static final TokenType IDENTIFIER = new TokenType.con1('IDENTIFIER', 3);
|
| - static final TokenType INT = new TokenType.con1('INT', 4);
|
| - static final TokenType KEYWORD = new TokenType.con1('KEYWORD', 5);
|
| - static final TokenType MULTI_LINE_COMMENT = new TokenType.con1('MULTI_LINE_COMMENT', 6);
|
| - static final TokenType SCRIPT_TAG = new TokenType.con1('SCRIPT_TAG', 7);
|
| - static final TokenType SINGLE_LINE_COMMENT = new TokenType.con1('SINGLE_LINE_COMMENT', 8);
|
| - static final TokenType STRING = new TokenType.con1('STRING', 9);
|
| - static final TokenType AMPERSAND = new TokenType.con2('AMPERSAND', 10, TokenClass.BITWISE_AND_OPERATOR, "&");
|
| - static final TokenType AMPERSAND_AMPERSAND = new TokenType.con2('AMPERSAND_AMPERSAND', 11, TokenClass.LOGICAL_AND_OPERATOR, "&&");
|
| - static final TokenType AMPERSAND_EQ = new TokenType.con2('AMPERSAND_EQ', 12, TokenClass.ASSIGNMENT_OPERATOR, "&=");
|
| - static final TokenType AT = new TokenType.con2('AT', 13, null, "@");
|
| - static final TokenType BANG = new TokenType.con2('BANG', 14, TokenClass.UNARY_PREFIX_OPERATOR, "!");
|
| - static final TokenType BANG_EQ = new TokenType.con2('BANG_EQ', 15, TokenClass.EQUALITY_OPERATOR, "!=");
|
| - static final TokenType BAR = new TokenType.con2('BAR', 16, TokenClass.BITWISE_OR_OPERATOR, "|");
|
| - static final TokenType BAR_BAR = new TokenType.con2('BAR_BAR', 17, TokenClass.LOGICAL_OR_OPERATOR, "||");
|
| - static final TokenType BAR_EQ = new TokenType.con2('BAR_EQ', 18, TokenClass.ASSIGNMENT_OPERATOR, "|=");
|
| - static final TokenType COLON = new TokenType.con2('COLON', 19, null, ":");
|
| - static final TokenType COMMA = new TokenType.con2('COMMA', 20, null, ",");
|
| - static final TokenType CARET = new TokenType.con2('CARET', 21, TokenClass.BITWISE_XOR_OPERATOR, "^");
|
| - static final TokenType CARET_EQ = new TokenType.con2('CARET_EQ', 22, TokenClass.ASSIGNMENT_OPERATOR, "^=");
|
| - static final TokenType CLOSE_CURLY_BRACKET = new TokenType.con2('CLOSE_CURLY_BRACKET', 23, null, "}");
|
| - static final TokenType CLOSE_PAREN = new TokenType.con2('CLOSE_PAREN', 24, null, ")");
|
| - static final TokenType CLOSE_SQUARE_BRACKET = new TokenType.con2('CLOSE_SQUARE_BRACKET', 25, null, "]");
|
| - static final TokenType EQ = new TokenType.con2('EQ', 26, TokenClass.ASSIGNMENT_OPERATOR, "=");
|
| - static final TokenType EQ_EQ = new TokenType.con2('EQ_EQ', 27, TokenClass.EQUALITY_OPERATOR, "==");
|
| - static final TokenType FUNCTION = new TokenType.con2('FUNCTION', 28, null, "=>");
|
| - static final TokenType GT = new TokenType.con2('GT', 29, TokenClass.RELATIONAL_OPERATOR, ">");
|
| - static final TokenType GT_EQ = new TokenType.con2('GT_EQ', 30, TokenClass.RELATIONAL_OPERATOR, ">=");
|
| - static final TokenType GT_GT = new TokenType.con2('GT_GT', 31, TokenClass.SHIFT_OPERATOR, ">>");
|
| - static final TokenType GT_GT_EQ = new TokenType.con2('GT_GT_EQ', 32, TokenClass.ASSIGNMENT_OPERATOR, ">>=");
|
| - static final TokenType HASH = new TokenType.con2('HASH', 33, null, "#");
|
| - static final TokenType INDEX = new TokenType.con2('INDEX', 34, TokenClass.UNARY_POSTFIX_OPERATOR, "[]");
|
| - static final TokenType INDEX_EQ = new TokenType.con2('INDEX_EQ', 35, TokenClass.UNARY_POSTFIX_OPERATOR, "[]=");
|
| - static final TokenType IS = new TokenType.con2('IS', 36, TokenClass.RELATIONAL_OPERATOR, "is");
|
| - static final TokenType LT = new TokenType.con2('LT', 37, TokenClass.RELATIONAL_OPERATOR, "<");
|
| - static final TokenType LT_EQ = new TokenType.con2('LT_EQ', 38, TokenClass.RELATIONAL_OPERATOR, "<=");
|
| - static final TokenType LT_LT = new TokenType.con2('LT_LT', 39, TokenClass.SHIFT_OPERATOR, "<<");
|
| - static final TokenType LT_LT_EQ = new TokenType.con2('LT_LT_EQ', 40, TokenClass.ASSIGNMENT_OPERATOR, "<<=");
|
| - static final TokenType MINUS = new TokenType.con2('MINUS', 41, TokenClass.ADDITIVE_OPERATOR, "-");
|
| - static final TokenType MINUS_EQ = new TokenType.con2('MINUS_EQ', 42, TokenClass.ASSIGNMENT_OPERATOR, "-=");
|
| - static final TokenType MINUS_MINUS = new TokenType.con2('MINUS_MINUS', 43, TokenClass.UNARY_PREFIX_OPERATOR, "--");
|
| - static final TokenType OPEN_CURLY_BRACKET = new TokenType.con2('OPEN_CURLY_BRACKET', 44, null, "{");
|
| - static final TokenType OPEN_PAREN = new TokenType.con2('OPEN_PAREN', 45, TokenClass.UNARY_POSTFIX_OPERATOR, "(");
|
| - static final TokenType OPEN_SQUARE_BRACKET = new TokenType.con2('OPEN_SQUARE_BRACKET', 46, TokenClass.UNARY_POSTFIX_OPERATOR, "[");
|
| - static final TokenType PERCENT = new TokenType.con2('PERCENT', 47, TokenClass.MULTIPLICATIVE_OPERATOR, "%");
|
| - static final TokenType PERCENT_EQ = new TokenType.con2('PERCENT_EQ', 48, TokenClass.ASSIGNMENT_OPERATOR, "%=");
|
| - static final TokenType PERIOD = new TokenType.con2('PERIOD', 49, TokenClass.UNARY_POSTFIX_OPERATOR, ".");
|
| - static final TokenType PERIOD_PERIOD = new TokenType.con2('PERIOD_PERIOD', 50, TokenClass.CASCADE_OPERATOR, "..");
|
| - static final TokenType PLUS = new TokenType.con2('PLUS', 51, TokenClass.ADDITIVE_OPERATOR, "+");
|
| - static final TokenType PLUS_EQ = new TokenType.con2('PLUS_EQ', 52, TokenClass.ASSIGNMENT_OPERATOR, "+=");
|
| - static final TokenType PLUS_PLUS = new TokenType.con2('PLUS_PLUS', 53, TokenClass.UNARY_PREFIX_OPERATOR, "++");
|
| - static final TokenType QUESTION = new TokenType.con2('QUESTION', 54, TokenClass.CONDITIONAL_OPERATOR, "?");
|
| - static final TokenType SEMICOLON = new TokenType.con2('SEMICOLON', 55, null, ";");
|
| - static final TokenType SLASH = new TokenType.con2('SLASH', 56, TokenClass.MULTIPLICATIVE_OPERATOR, "/");
|
| - static final TokenType SLASH_EQ = new TokenType.con2('SLASH_EQ', 57, TokenClass.ASSIGNMENT_OPERATOR, "/=");
|
| - static final TokenType STAR = new TokenType.con2('STAR', 58, TokenClass.MULTIPLICATIVE_OPERATOR, "*");
|
| - static final TokenType STAR_EQ = new TokenType.con2('STAR_EQ', 59, TokenClass.ASSIGNMENT_OPERATOR, "*=");
|
| - static final TokenType STRING_INTERPOLATION_EXPRESSION = new TokenType.con2('STRING_INTERPOLATION_EXPRESSION', 60, null, "\${");
|
| - static final TokenType STRING_INTERPOLATION_IDENTIFIER = new TokenType.con2('STRING_INTERPOLATION_IDENTIFIER', 61, null, "\$");
|
| - static final TokenType TILDE = new TokenType.con2('TILDE', 62, TokenClass.UNARY_PREFIX_OPERATOR, "~");
|
| - static final TokenType TILDE_SLASH = new TokenType.con2('TILDE_SLASH', 63, TokenClass.MULTIPLICATIVE_OPERATOR, "~/");
|
| - static final TokenType TILDE_SLASH_EQ = new TokenType.con2('TILDE_SLASH_EQ', 64, TokenClass.ASSIGNMENT_OPERATOR, "~/=");
|
| - static final TokenType BACKPING = new TokenType.con2('BACKPING', 65, null, "`");
|
| - static final TokenType BACKSLASH = new TokenType.con2('BACKSLASH', 66, null, "\\");
|
| - static final TokenType PERIOD_PERIOD_PERIOD = new TokenType.con2('PERIOD_PERIOD_PERIOD', 67, null, "...");
|
| - static final List<TokenType> values = [EOF, DOUBLE, HEXADECIMAL, IDENTIFIER, INT, KEYWORD, MULTI_LINE_COMMENT, SCRIPT_TAG, SINGLE_LINE_COMMENT, STRING, AMPERSAND, AMPERSAND_AMPERSAND, AMPERSAND_EQ, AT, BANG, BANG_EQ, BAR, BAR_BAR, BAR_EQ, COLON, COMMA, CARET, CARET_EQ, CLOSE_CURLY_BRACKET, CLOSE_PAREN, CLOSE_SQUARE_BRACKET, EQ, EQ_EQ, FUNCTION, GT, GT_EQ, GT_GT, GT_GT_EQ, HASH, INDEX, INDEX_EQ, IS, LT, LT_EQ, LT_LT, LT_LT_EQ, MINUS, MINUS_EQ, MINUS_MINUS, OPEN_CURLY_BRACKET, OPEN_PAREN, OPEN_SQUARE_BRACKET, PERCENT, PERCENT_EQ, PERIOD, PERIOD_PERIOD, PLUS, PLUS_EQ, PLUS_PLUS, QUESTION, SEMICOLON, SLASH, SLASH_EQ, STAR, STAR_EQ, STRING_INTERPOLATION_EXPRESSION, STRING_INTERPOLATION_IDENTIFIER, TILDE, TILDE_SLASH, TILDE_SLASH_EQ, BACKPING, BACKSLASH, PERIOD_PERIOD_PERIOD];
|
| - String __name;
|
| - int __ordinal = 0;
|
| - /**
|
| - * The class of the token.
|
| - */
|
| - TokenClass _tokenClass;
|
| - /**
|
| - * The lexeme that defines this type of token, or {@code null} if there is more than one possible
|
| - * lexeme for this type of token.
|
| - */
|
| - String _lexeme;
|
| - TokenType.con1(String ___name, int ___ordinal) {
|
| - _jtd_constructor_236_impl(___name, ___ordinal);
|
| - }
|
| - _jtd_constructor_236_impl(String ___name, int ___ordinal) {
|
| - _jtd_constructor_237_impl(___name, ___ordinal, TokenClass.NO_CLASS, null);
|
| - }
|
| - TokenType.con2(String ___name, int ___ordinal, TokenClass tokenClass2, String lexeme2) {
|
| - _jtd_constructor_237_impl(___name, ___ordinal, tokenClass2, lexeme2);
|
| - }
|
| - _jtd_constructor_237_impl(String ___name, int ___ordinal, TokenClass tokenClass2, String lexeme2) {
|
| - __name = ___name;
|
| - __ordinal = ___ordinal;
|
| - this._tokenClass = tokenClass2 == null ? TokenClass.NO_CLASS : tokenClass2;
|
| - this._lexeme = lexeme2;
|
| - }
|
| - /**
|
| - * Return the lexeme that defines this type of token, or {@code null} if there is more than one
|
| - * possible lexeme for this type of token.
|
| - * @return the lexeme that defines this type of token
|
| - */
|
| - String get lexeme => _lexeme;
|
| - /**
|
| - * Return the precedence of the token, or {@code 0} if the token does not represent an operator.
|
| - * @return the precedence of the token
|
| - */
|
| - int get precedence => _tokenClass.precedence;
|
| - /**
|
| - * Return {@code true} if this type of token represents an additive operator.
|
| - * @return {@code true} if this type of token represents an additive operator
|
| - */
|
| - bool isAdditiveOperator() => identical(_tokenClass, TokenClass.ADDITIVE_OPERATOR);
|
| - /**
|
| - * Return {@code true} if this type of token represents an assignment operator.
|
| - * @return {@code true} if this type of token represents an assignment operator
|
| - */
|
| - bool isAssignmentOperator() => identical(_tokenClass, TokenClass.ASSIGNMENT_OPERATOR);
|
| - /**
|
| - * Return {@code true} if this type of token represents an associative operator. An associative
|
| - * operator is an operator for which the following equality is true:{@code (a * b) * c == a * (b * c)}. In other words, if the result of applying the operator to
|
| - * multiple operands does not depend on the order in which those applications occur.
|
| - * <p>
|
| - * Note: This method considers the logical-and and logical-or operators to be associative, even
|
| - * though the order in which the application of those operators can have an effect because
|
| - * evaluation of the right-hand operand is conditional.
|
| - * @return {@code true} if this type of token represents an associative operator
|
| - */
|
| - bool isAssociativeOperator() => identical(this, AMPERSAND) || identical(this, AMPERSAND_AMPERSAND) || identical(this, BAR) || identical(this, BAR_BAR) || identical(this, CARET) || identical(this, PLUS) || identical(this, STAR);
|
| - /**
|
| - * Return {@code true} if this type of token represents an equality operator.
|
| - * @return {@code true} if this type of token represents an equality operator
|
| - */
|
| - bool isEqualityOperator() => identical(_tokenClass, TokenClass.EQUALITY_OPERATOR);
|
| - /**
|
| - * Return {@code true} if this type of token represents an increment operator.
|
| - * @return {@code true} if this type of token represents an increment operator
|
| - */
|
| - bool isIncrementOperator() => identical(_lexeme, "++") || identical(_lexeme, "--");
|
| - /**
|
| - * Return {@code true} if this type of token represents a multiplicative operator.
|
| - * @return {@code true} if this type of token represents a multiplicative operator
|
| - */
|
| - bool isMultiplicativeOperator() => identical(_tokenClass, TokenClass.MULTIPLICATIVE_OPERATOR);
|
| - /**
|
| - * Return {@code true} if this token type represents an operator.
|
| - * @return {@code true} if this token type represents an operator
|
| - */
|
| - bool isOperator() => _tokenClass != TokenClass.NO_CLASS && this != OPEN_PAREN && this != OPEN_SQUARE_BRACKET && this != PERIOD;
|
| - /**
|
| - * Return {@code true} if this type of token represents a relational operator.
|
| - * @return {@code true} if this type of token represents a relational operator
|
| - */
|
| - bool isRelationalOperator() => identical(_tokenClass, TokenClass.RELATIONAL_OPERATOR);
|
| - /**
|
| - * Return {@code true} if this type of token represents a shift operator.
|
| - * @return {@code true} if this type of token represents a shift operator
|
| - */
|
| - bool isShiftOperator() => identical(_tokenClass, TokenClass.SHIFT_OPERATOR);
|
| - /**
|
| - * Return {@code true} if this type of token represents a unary postfix operator.
|
| - * @return {@code true} if this type of token represents a unary postfix operator
|
| - */
|
| - bool isUnaryPostfixOperator() => identical(_tokenClass, TokenClass.UNARY_POSTFIX_OPERATOR);
|
| - /**
|
| - * Return {@code true} if this type of token represents a unary prefix operator.
|
| - * @return {@code true} if this type of token represents a unary prefix operator
|
| - */
|
| - bool isUnaryPrefixOperator() => identical(_tokenClass, TokenClass.UNARY_PREFIX_OPERATOR);
|
| - /**
|
| - * Return {@code true} if this token type represents an operator that can be defined by users.
|
| - * @return {@code true} if this token type represents an operator that can be defined by users
|
| - */
|
| - bool isUserDefinableOperator() => identical(_lexeme, "==") || identical(_lexeme, "~") || identical(_lexeme, "[]") || identical(_lexeme, "[]=") || identical(_lexeme, "*") || identical(_lexeme, "/") || identical(_lexeme, "%") || identical(_lexeme, "~/") || identical(_lexeme, "+") || identical(_lexeme, "-") || identical(_lexeme, "<<") || identical(_lexeme, ">>") || identical(_lexeme, ">=") || identical(_lexeme, ">") || identical(_lexeme, "<=") || identical(_lexeme, "<") || identical(_lexeme, "&") || identical(_lexeme, "^") || identical(_lexeme, "|");
|
| - String toString() => __name;
|
| -}
|
| -class TokenType_EOF extends TokenType {
|
| - TokenType_EOF(String ___name, int ___ordinal, TokenClass arg0, String arg1) : super.con2(___name, ___ordinal, arg0, arg1);
|
| - String toString() => "-eof-";
|
| -}
|
| -/**
|
| - * Instances of the class {@code TokenWithComment} represent a string token that is preceded by
|
| - * comments.
|
| - */
|
| -class StringTokenWithComment extends StringToken {
|
| - /**
|
| - * The first comment in the list of comments that precede this token.
|
| - */
|
| - Token _precedingComment;
|
| - /**
|
| - * Initialize a newly created token to have the given type and offset and to be preceded by the
|
| - * comments reachable from the given comment.
|
| - * @param type the type of the token
|
| - * @param offset the offset from the beginning of the file to the first character in the token
|
| - * @param precedingComment the first comment in the list of comments that precede this token
|
| - */
|
| - StringTokenWithComment(TokenType type, String value, int offset, Token precedingComment) : super(type, value, offset) {
|
| - this._precedingComment = precedingComment;
|
| - }
|
| - Token get precedingComments => _precedingComment;
|
| -}
|
| -/**
|
| - * Instances of the class {@code BeginToken} represent the opening half of a grouping pair of
|
| - * tokens. This is used for curly brackets ('{'), parentheses ('('), and square brackets ('[').
|
| - */
|
| -class BeginToken extends Token {
|
| - /**
|
| - * The token that corresponds to this token.
|
| - */
|
| - Token _endToken;
|
| - /**
|
| - * Initialize a newly created token representing the opening half of a grouping pair of tokens.
|
| - * @param type the type of the token
|
| - * @param offset the offset from the beginning of the file to the first character in the token
|
| - */
|
| - BeginToken(TokenType type, int offset) : super(type, offset) {
|
| - assert((identical(type, TokenType.OPEN_CURLY_BRACKET) || identical(type, TokenType.OPEN_PAREN) || identical(type, TokenType.OPEN_SQUARE_BRACKET) || identical(type, TokenType.STRING_INTERPOLATION_EXPRESSION)));
|
| - }
|
| - /**
|
| - * Return the token that corresponds to this token.
|
| - * @return the token that corresponds to this token
|
| - */
|
| - Token get endToken => _endToken;
|
| - /**
|
| - * Set the token that corresponds to this token to the given token.
|
| - * @param token the token that corresponds to this token
|
| - */
|
| - void set endToken(Token token) {
|
| - this._endToken = token;
|
| - }
|
| -}
|
| -/**
|
| - * The enumeration {@code TokenClass} represents classes (or groups) of tokens with a similar use.
|
| - */
|
| -class TokenClass {
|
| - /**
|
| - * A value used to indicate that the token type is not part of any specific class of token.
|
| - */
|
| - static final TokenClass NO_CLASS = new TokenClass.con1('NO_CLASS', 0);
|
| - /**
|
| - * A value used to indicate that the token type is an additive operator.
|
| - */
|
| - static final TokenClass ADDITIVE_OPERATOR = new TokenClass.con2('ADDITIVE_OPERATOR', 1, 12);
|
| - /**
|
| - * A value used to indicate that the token type is an assignment operator.
|
| - */
|
| - static final TokenClass ASSIGNMENT_OPERATOR = new TokenClass.con2('ASSIGNMENT_OPERATOR', 2, 1);
|
| - /**
|
| - * A value used to indicate that the token type is a bitwise-and operator.
|
| - */
|
| - static final TokenClass BITWISE_AND_OPERATOR = new TokenClass.con2('BITWISE_AND_OPERATOR', 3, 8);
|
| - /**
|
| - * A value used to indicate that the token type is a bitwise-or operator.
|
| - */
|
| - static final TokenClass BITWISE_OR_OPERATOR = new TokenClass.con2('BITWISE_OR_OPERATOR', 4, 6);
|
| - /**
|
| - * A value used to indicate that the token type is a bitwise-xor operator.
|
| - */
|
| - static final TokenClass BITWISE_XOR_OPERATOR = new TokenClass.con2('BITWISE_XOR_OPERATOR', 5, 7);
|
| - /**
|
| - * A value used to indicate that the token type is a cascade operator.
|
| - */
|
| - static final TokenClass CASCADE_OPERATOR = new TokenClass.con2('CASCADE_OPERATOR', 6, 2);
|
| - /**
|
| - * A value used to indicate that the token type is a conditional operator.
|
| - */
|
| - static final TokenClass CONDITIONAL_OPERATOR = new TokenClass.con2('CONDITIONAL_OPERATOR', 7, 3);
|
| - /**
|
| - * A value used to indicate that the token type is an equality operator.
|
| - */
|
| - static final TokenClass EQUALITY_OPERATOR = new TokenClass.con2('EQUALITY_OPERATOR', 8, 9);
|
| - /**
|
| - * A value used to indicate that the token type is a logical-and operator.
|
| - */
|
| - static final TokenClass LOGICAL_AND_OPERATOR = new TokenClass.con2('LOGICAL_AND_OPERATOR', 9, 5);
|
| - /**
|
| - * A value used to indicate that the token type is a logical-or operator.
|
| - */
|
| - static final TokenClass LOGICAL_OR_OPERATOR = new TokenClass.con2('LOGICAL_OR_OPERATOR', 10, 4);
|
| - /**
|
| - * A value used to indicate that the token type is a multiplicative operator.
|
| - */
|
| - static final TokenClass MULTIPLICATIVE_OPERATOR = new TokenClass.con2('MULTIPLICATIVE_OPERATOR', 11, 13);
|
| - /**
|
| - * A value used to indicate that the token type is a relational operator.
|
| - */
|
| - static final TokenClass RELATIONAL_OPERATOR = new TokenClass.con2('RELATIONAL_OPERATOR', 12, 10);
|
| - /**
|
| - * A value used to indicate that the token type is a shift operator.
|
| - */
|
| - static final TokenClass SHIFT_OPERATOR = new TokenClass.con2('SHIFT_OPERATOR', 13, 11);
|
| - /**
|
| - * A value used to indicate that the token type is a unary operator.
|
| - */
|
| - static final TokenClass UNARY_POSTFIX_OPERATOR = new TokenClass.con2('UNARY_POSTFIX_OPERATOR', 14, 15);
|
| - /**
|
| - * A value used to indicate that the token type is a unary operator.
|
| - */
|
| - static final TokenClass UNARY_PREFIX_OPERATOR = new TokenClass.con2('UNARY_PREFIX_OPERATOR', 15, 14);
|
| - static final List<TokenClass> values = [NO_CLASS, ADDITIVE_OPERATOR, ASSIGNMENT_OPERATOR, BITWISE_AND_OPERATOR, BITWISE_OR_OPERATOR, BITWISE_XOR_OPERATOR, CASCADE_OPERATOR, CONDITIONAL_OPERATOR, EQUALITY_OPERATOR, LOGICAL_AND_OPERATOR, LOGICAL_OR_OPERATOR, MULTIPLICATIVE_OPERATOR, RELATIONAL_OPERATOR, SHIFT_OPERATOR, UNARY_POSTFIX_OPERATOR, UNARY_PREFIX_OPERATOR];
|
| - String __name;
|
| - int __ordinal = 0;
|
| - /**
|
| - * The precedence of tokens of this class, or {@code 0} if the such tokens do not represent an
|
| - * operator.
|
| - */
|
| - int _precedence = 0;
|
| - TokenClass.con1(String ___name, int ___ordinal) {
|
| - _jtd_constructor_234_impl(___name, ___ordinal);
|
| - }
|
| - _jtd_constructor_234_impl(String ___name, int ___ordinal) {
|
| - _jtd_constructor_235_impl(___name, ___ordinal, 0);
|
| - }
|
| - TokenClass.con2(String ___name, int ___ordinal, int precedence2) {
|
| - _jtd_constructor_235_impl(___name, ___ordinal, precedence2);
|
| - }
|
| - _jtd_constructor_235_impl(String ___name, int ___ordinal, int precedence2) {
|
| - __name = ___name;
|
| - __ordinal = ___ordinal;
|
| - this._precedence = precedence2;
|
| - }
|
| - /**
|
| - * Return the precedence of tokens of this class, or {@code 0} if the such tokens do not represent
|
| - * an operator.
|
| - * @return the precedence of tokens of this class
|
| - */
|
| - int get precedence => _precedence;
|
| - String toString() => __name;
|
| -}
|
| -/**
|
| - * Instances of the class {@code StringScanner} implement a scanner that reads from a string. The
|
| - * scanning logic is in the superclass.
|
| - */
|
| -class StringScanner extends AbstractScanner {
|
| - /**
|
| - * The offset from the beginning of the file to the beginning of the source being scanned.
|
| - */
|
| - int _offsetDelta = 0;
|
| - /**
|
| - * The string from which characters will be read.
|
| - */
|
| - String _string;
|
| - /**
|
| - * The number of characters in the string.
|
| - */
|
| - int _stringLength = 0;
|
| - /**
|
| - * The index, relative to the string, of the last character that was read.
|
| - */
|
| - int _charOffset = 0;
|
| - /**
|
| - * Initialize a newly created scanner to scan the characters in the given string.
|
| - * @param source the source being scanned
|
| - * @param string the string from which characters will be read
|
| - * @param errorListener the error listener that will be informed of any errors that are found
|
| - */
|
| - StringScanner(Source source, String string, AnalysisErrorListener errorListener) : super(source, errorListener) {
|
| - this._offsetDelta = 0;
|
| - this._string = string;
|
| - this._stringLength = string.length;
|
| - this._charOffset = -1;
|
| - }
|
| - int get offset => _offsetDelta + _charOffset;
|
| - /**
|
| - * Record that the source begins on the given line and column at the given offset. The line starts
|
| - * for lines before the given line will not be correct.
|
| - * <p>
|
| - * This method must be invoked at most one time and must be invoked before scanning begins. The
|
| - * values provided must be sensible. The results are undefined if these conditions are violated.
|
| - * @param line the one-based index of the line containing the first character of the source
|
| - * @param column the one-based index of the column in which the first character of the source
|
| - * occurs
|
| - * @param offset the zero-based offset from the beginning of the larger context to the first
|
| - * character of the source
|
| - */
|
| - void setSourceStart(int line, int column, int offset) {
|
| - if (line < 1 || column < 1 || offset < 0 || (line + column - 2) >= offset) {
|
| - return;
|
| - }
|
| - _offsetDelta = 1;
|
| - for (int i = 2; i < line; i++) {
|
| - recordStartOfLine();
|
| - }
|
| - _offsetDelta = offset - column + 1;
|
| - recordStartOfLine();
|
| - _offsetDelta = offset;
|
| - }
|
| - int advance() {
|
| - if (_charOffset + 1 >= _stringLength) {
|
| - return -1;
|
| - }
|
| - return _string.codeUnitAt(++_charOffset);
|
| - }
|
| - String getString(int start, int endDelta) => _string.substring(start - _offsetDelta, _charOffset + 1 + endDelta);
|
| - int peek() {
|
| - if (_charOffset + 1 >= _string.length) {
|
| - return -1;
|
| - }
|
| - return _string.codeUnitAt(_charOffset + 1);
|
| - }
|
| -}
|
| -/**
|
| - * The abstract class {@code AbstractScanner} implements a scanner for Dart code. Subclasses are
|
| - * required to implement the interface used to access the characters being scanned.
|
| - * <p>
|
| - * The lexical structure of Dart is ambiguous without knowledge of the context in which a token is
|
| - * being scanned. For example, without context we cannot determine whether source of the form "<<"
|
| - * should be scanned as a single left-shift operator or as two left angle brackets. This scanner
|
| - * does not have any context, so it always resolves such conflicts by scanning the longest possible
|
| - * token.
|
| - */
|
| -abstract class AbstractScanner {
|
| - /**
|
| - * The source being scanned.
|
| - */
|
| - Source _source;
|
| - /**
|
| - * The error listener that will be informed of any errors that are found during the scan.
|
| - */
|
| - AnalysisErrorListener _errorListener;
|
| - /**
|
| - * The token pointing to the head of the linked list of tokens.
|
| - */
|
| - Token _tokens;
|
| - /**
|
| - * The last token that was scanned.
|
| - */
|
| - Token _tail;
|
| - /**
|
| - * The first token in the list of comment tokens found since the last non-comment token.
|
| - */
|
| - Token _firstComment;
|
| - /**
|
| - * The last token in the list of comment tokens found since the last non-comment token.
|
| - */
|
| - Token _lastComment;
|
| - /**
|
| - * The index of the first character of the current token.
|
| - */
|
| - int _tokenStart = 0;
|
| - /**
|
| - * A list containing the offsets of the first character of each line in the source code.
|
| - */
|
| - List<int> _lineStarts = new List<int>();
|
| - /**
|
| - * A list, treated something like a stack, of tokens representing the beginning of a matched pair.
|
| - * It is used to pair the end tokens with the begin tokens.
|
| - */
|
| - List<BeginToken> _groupingStack = new List<BeginToken>();
|
| - /**
|
| - * A flag indicating whether any unmatched groups were found during the parse.
|
| - */
|
| - bool _hasUnmatchedGroups2 = false;
|
| - /**
|
| - * A non-breaking space, which is allowed by this scanner as a white-space character.
|
| - */
|
| - static int _$NBSP = 160;
|
| - /**
|
| - * Initialize a newly created scanner.
|
| - * @param source the source being scanned
|
| - * @param errorListener the error listener that will be informed of any errors that are found
|
| - */
|
| - AbstractScanner(Source source, AnalysisErrorListener errorListener) {
|
| - this._source = source;
|
| - this._errorListener = errorListener;
|
| - _tokens = new Token(TokenType.EOF, -1);
|
| - _tokens.setNext(_tokens);
|
| - _tail = _tokens;
|
| - _tokenStart = -1;
|
| - _lineStarts.add(0);
|
| - }
|
| - /**
|
| - * Return an array containing the offsets of the first character of each line in the source code.
|
| - * @return an array containing the offsets of the first character of each line in the source code
|
| - */
|
| - List<int> get lineStarts => _lineStarts;
|
| - /**
|
| - * Return the current offset relative to the beginning of the file. Return the initial offset if
|
| - * the scanner has not yet scanned the source code, and one (1) past the end of the source code if
|
| - * the source code has been scanned.
|
| - * @return the current offset of the scanner in the source
|
| - */
|
| - int get offset;
|
| - /**
|
| - * Return {@code true} if any unmatched groups were found during the parse.
|
| - * @return {@code true} if any unmatched groups were found during the parse
|
| - */
|
| - bool hasUnmatchedGroups() => _hasUnmatchedGroups2;
|
| - /**
|
| - * Scan the source code to produce a list of tokens representing the source.
|
| - * @return the first token in the list of tokens that were produced
|
| - */
|
| - Token tokenize() {
|
| - int startTime = System.currentTimeMillis();
|
| - int next = advance();
|
| - while (next != -1) {
|
| - next = bigSwitch(next);
|
| - }
|
| - appendEofToken();
|
| - int endTime = System.currentTimeMillis();
|
| - Instrumentation.metric2("Engine-Scanner", endTime - startTime).with3("chars", offset).log();
|
| - return firstToken();
|
| - }
|
| - /**
|
| - * Advance the current position and return the character at the new current position.
|
| - * @return the character at the new current position
|
| - */
|
| - int advance();
|
| - /**
|
| - * Return the substring of the source code between the start offset and the modified current
|
| - * position. The current position is modified by adding the end delta.
|
| - * @param start the offset to the beginning of the string, relative to the start of the file
|
| - * @param endDelta the number of character after the current location to be included in the
|
| - * string, or the number of characters before the current location to be excluded if the
|
| - * offset is negative
|
| - * @return the specified substring of the source code
|
| - */
|
| - String getString(int start, int endDelta);
|
| - /**
|
| - * Return the character at the current position without changing the current position.
|
| - * @return the character at the current position
|
| - */
|
| - int peek();
|
| - /**
|
| - * Record the fact that we are at the beginning of a new line in the source.
|
| - */
|
| - void recordStartOfLine() {
|
| - _lineStarts.add(offset);
|
| - }
|
| - void appendBeginToken(TokenType type) {
|
| - BeginToken token;
|
| - if (_firstComment == null) {
|
| - token = new BeginToken(type, _tokenStart);
|
| - } else {
|
| - token = new BeginTokenWithComment(type, _tokenStart, _firstComment);
|
| - _firstComment = null;
|
| - _lastComment = null;
|
| - }
|
| - _tail = _tail.setNext(token);
|
| - _groupingStack.add(token);
|
| - }
|
| - void appendCommentToken(TokenType type, String value) {
|
| - if (_firstComment == null) {
|
| - _firstComment = new StringToken(type, value, _tokenStart);
|
| - _lastComment = _firstComment;
|
| - } else {
|
| - _lastComment = _lastComment.setNext(new StringToken(type, value, _tokenStart));
|
| - }
|
| - }
|
| - void appendEndToken(TokenType type26, TokenType beginType) {
|
| - Token token;
|
| - if (_firstComment == null) {
|
| - token = new Token(type26, _tokenStart);
|
| - } else {
|
| - token = new TokenWithComment(type26, _tokenStart, _firstComment);
|
| - _firstComment = null;
|
| - _lastComment = null;
|
| - }
|
| - _tail = _tail.setNext(token);
|
| - int last = _groupingStack.length - 1;
|
| - if (last >= 0) {
|
| - BeginToken begin = _groupingStack[last];
|
| - if (identical(begin.type, beginType)) {
|
| - begin.endToken = token;
|
| - _groupingStack.removeAt(last);
|
| - }
|
| - }
|
| - }
|
| - void appendEofToken() {
|
| - Token eofToken;
|
| - if (_firstComment == null) {
|
| - eofToken = new Token(TokenType.EOF, offset + 1);
|
| - } else {
|
| - eofToken = new TokenWithComment(TokenType.EOF, offset + 1, _firstComment);
|
| - _firstComment = null;
|
| - _lastComment = null;
|
| - }
|
| - eofToken.setNext(eofToken);
|
| - _tail = _tail.setNext(eofToken);
|
| - if (!_groupingStack.isEmpty) {
|
| - _hasUnmatchedGroups2 = true;
|
| - }
|
| - }
|
| - void appendKeywordToken(Keyword keyword) {
|
| - if (_firstComment == null) {
|
| - _tail = _tail.setNext(new KeywordToken(keyword, _tokenStart));
|
| - } else {
|
| - _tail = _tail.setNext(new KeywordTokenWithComment(keyword, _tokenStart, _firstComment));
|
| - _firstComment = null;
|
| - _lastComment = null;
|
| - }
|
| + void appendKeywordToken(Keyword keyword) {
|
| + if (_firstComment == null) {
|
| + _tail = _tail.setNext(new KeywordToken(keyword, _tokenStart));
|
| + } else {
|
| + _tail = _tail.setNext(new KeywordTokenWithComment(keyword, _tokenStart, _firstComment));
|
| + _firstComment = null;
|
| + _lastComment = null;
|
| + }
|
| }
|
| void appendStringToken(TokenType type, String value) {
|
| if (_firstComment == null) {
|
| @@ -1588,159 +1039,624 @@ abstract class AbstractScanner {
|
| appendStringToken(TokenType.STRING, getString(start, 0));
|
| return advance();
|
| }
|
| - int tokenizeMultiply(int next) => select(0x3D, TokenType.STAR_EQ, TokenType.STAR);
|
| - int tokenizeNumber(int next) {
|
| - int start = offset;
|
| - while (true) {
|
| - next = advance();
|
| - if (0x30 <= next && next <= 0x39) {
|
| - continue;
|
| - } else if (next == 0x2E) {
|
| - return tokenizeFractionPart(advance(), start);
|
| - } else if (next == 0x64 || next == 0x44) {
|
| - appendStringToken(TokenType.DOUBLE, getString(start, 0));
|
| - return advance();
|
| - } else if (next == 0x65 || next == 0x45) {
|
| - return tokenizeFractionPart(next, start);
|
| - } else {
|
| - appendStringToken(TokenType.INT, getString(start, next < 0 ? 0 : -1));
|
| - return next;
|
| - }
|
| + int tokenizeMultiply(int next) => select(0x3D, TokenType.STAR_EQ, TokenType.STAR);
|
| + int tokenizeNumber(int next) {
|
| + int start = offset;
|
| + while (true) {
|
| + next = advance();
|
| + if (0x30 <= next && next <= 0x39) {
|
| + continue;
|
| + } else if (next == 0x2E) {
|
| + return tokenizeFractionPart(advance(), start);
|
| + } else if (next == 0x64 || next == 0x44) {
|
| + appendStringToken(TokenType.DOUBLE, getString(start, 0));
|
| + return advance();
|
| + } else if (next == 0x65 || next == 0x45) {
|
| + return tokenizeFractionPart(next, start);
|
| + } else {
|
| + appendStringToken(TokenType.INT, getString(start, next < 0 ? 0 : -1));
|
| + return next;
|
| + }
|
| + }
|
| + }
|
| + int tokenizeOpenSquareBracket(int next) {
|
| + next = advance();
|
| + if (next == 0x5D) {
|
| + return select(0x3D, TokenType.INDEX_EQ, TokenType.INDEX);
|
| + } else {
|
| + appendBeginToken(TokenType.OPEN_SQUARE_BRACKET);
|
| + return next;
|
| + }
|
| + }
|
| + int tokenizePercent(int next) => select(0x3D, TokenType.PERCENT_EQ, TokenType.PERCENT);
|
| + int tokenizePlus(int next) {
|
| + next = advance();
|
| + if (0x2B == next) {
|
| + appendToken(TokenType.PLUS_PLUS);
|
| + return advance();
|
| + } else if (0x3D == next) {
|
| + appendToken(TokenType.PLUS_EQ);
|
| + return advance();
|
| + } else {
|
| + appendToken(TokenType.PLUS);
|
| + return next;
|
| + }
|
| + }
|
| + int tokenizeSingleLineComment(int next) {
|
| + while (true) {
|
| + next = advance();
|
| + if (0xA == next || 0xD == next || -1 == next) {
|
| + appendCommentToken(TokenType.SINGLE_LINE_COMMENT, getString(_tokenStart, 0));
|
| + return next;
|
| + }
|
| + }
|
| + }
|
| + int tokenizeSingleLineRawString(int next, int quoteChar, int start) {
|
| + next = advance();
|
| + while (next != -1) {
|
| + if (next == quoteChar) {
|
| + appendStringToken(TokenType.STRING, getString(start, 0));
|
| + return advance();
|
| + } else if (next == 0xD || next == 0xA) {
|
| + reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
|
| + appendStringToken(TokenType.STRING, getString(start, 0));
|
| + return advance();
|
| + }
|
| + next = advance();
|
| + }
|
| + reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
|
| + appendStringToken(TokenType.STRING, getString(start, 0));
|
| + return advance();
|
| + }
|
| + int tokenizeSingleLineString(int next, int quoteChar, int start) {
|
| + while (next != quoteChar) {
|
| + if (next == 0x5C) {
|
| + next = advance();
|
| + } else if (next == 0x24) {
|
| + appendStringToken(TokenType.STRING, getString(start, -1));
|
| + beginToken();
|
| + next = tokenizeStringInterpolation(start);
|
| + start = offset;
|
| + continue;
|
| + }
|
| + if (next <= 0xD && (next == 0xA || next == 0xD || next == -1)) {
|
| + reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
|
| + appendStringToken(TokenType.STRING, getString(start, 0));
|
| + return advance();
|
| + }
|
| + next = advance();
|
| + }
|
| + appendStringToken(TokenType.STRING, getString(start, 0));
|
| + return advance();
|
| + }
|
| + int tokenizeSlashOrComment(int next) {
|
| + next = advance();
|
| + if (0x2A == next) {
|
| + return tokenizeMultiLineComment(next);
|
| + } else if (0x2F == next) {
|
| + return tokenizeSingleLineComment(next);
|
| + } else if (0x3D == next) {
|
| + appendToken(TokenType.SLASH_EQ);
|
| + return advance();
|
| + } else {
|
| + appendToken(TokenType.SLASH);
|
| + return next;
|
| + }
|
| + }
|
| + int tokenizeString(int next, int start, bool raw) {
|
| + int quoteChar = next;
|
| + next = advance();
|
| + if (quoteChar == next) {
|
| + next = advance();
|
| + if (quoteChar == next) {
|
| + return tokenizeMultiLineString(quoteChar, start, raw);
|
| + } else {
|
| + appendStringToken(TokenType.STRING, getString(start, -1));
|
| + return next;
|
| + }
|
| + }
|
| + if (raw) {
|
| + return tokenizeSingleLineRawString(next, quoteChar, start);
|
| + } else {
|
| + return tokenizeSingleLineString(next, quoteChar, start);
|
| + }
|
| + }
|
| + int tokenizeStringInterpolation(int start) {
|
| + beginToken();
|
| + int next = advance();
|
| + if (next == 0x7B) {
|
| + return tokenizeInterpolatedExpression(next, start);
|
| + } else {
|
| + return tokenizeInterpolatedIdentifier(next, start);
|
| + }
|
| + }
|
| + int tokenizeTag(int next) {
|
| + if (offset == 0) {
|
| + if (peek() == 0x21) {
|
| + do {
|
| + next = advance();
|
| + } while (next != 0xA && next != 0xD && next > 0);
|
| + appendStringToken(TokenType.SCRIPT_TAG, getString(_tokenStart, 0));
|
| + return next;
|
| + }
|
| + }
|
| + appendToken(TokenType.HASH);
|
| + return advance();
|
| + }
|
| + int tokenizeTilde(int next) {
|
| + next = advance();
|
| + if (next == 0x2F) {
|
| + return select(0x3D, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH);
|
| + } else {
|
| + appendToken(TokenType.TILDE);
|
| + return next;
|
| + }
|
| + }
|
| +}
|
| +/**
|
| + * Instances of the class {@code StringToken} represent a token whose value is independent of it's
|
| + * type.
|
| + */
|
| +class StringToken extends Token {
|
| + /**
|
| + * The lexeme represented by this token.
|
| + */
|
| + String _value2;
|
| + /**
|
| + * Initialize a newly created token to represent a token of the given type with the given value.
|
| + * @param type the type of the token
|
| + * @param value the lexeme represented by this token
|
| + * @param offset the offset from the beginning of the file to the first character in the token
|
| + */
|
| + StringToken(TokenType type, String value, int offset) : super(type, offset) {
|
| + this._value2 = value;
|
| + }
|
| + String get lexeme => _value2;
|
| + String value() => _value2;
|
| +}
|
| +/**
|
| + * Instances of the class {@code CharBufferScanner} implement a scanner that reads from a character
|
| + * buffer. The scanning logic is in the superclass.
|
| + */
|
| +class CharBufferScanner extends AbstractScanner {
|
| + /**
|
| + * The buffer from which characters will be read.
|
| + */
|
| + CharBuffer _buffer;
|
| + /**
|
| + * The number of characters in the buffer.
|
| + */
|
| + int _bufferLength = 0;
|
| + /**
|
| + * The index of the last character that was read.
|
| + */
|
| + int _charOffset = 0;
|
| + /**
|
| + * Initialize a newly created scanner to scan the characters in the given character buffer.
|
| + * @param source the source being scanned
|
| + * @param buffer the buffer from which characters will be read
|
| + * @param errorListener the error listener that will be informed of any errors that are found
|
| + */
|
| + CharBufferScanner(Source source, CharBuffer buffer, AnalysisErrorListener errorListener) : super(source, errorListener) {
|
| + this._buffer = buffer;
|
| + this._bufferLength = buffer.length();
|
| + this._charOffset = -1;
|
| + }
|
| + int get offset => _charOffset;
|
| + int advance() {
|
| + if (_charOffset + 1 >= _bufferLength) {
|
| + return -1;
|
| }
|
| + return _buffer.charAt(++_charOffset);
|
| }
|
| - int tokenizeOpenSquareBracket(int next) {
|
| - next = advance();
|
| - if (next == 0x5D) {
|
| - return select(0x3D, TokenType.INDEX_EQ, TokenType.INDEX);
|
| - } else {
|
| - appendBeginToken(TokenType.OPEN_SQUARE_BRACKET);
|
| - return next;
|
| + String getString(int start, int endDelta) => _buffer.subSequence(start, _charOffset + 1 + endDelta).toString();
|
| + int peek() {
|
| + if (_charOffset + 1 >= _buffer.length()) {
|
| + return -1;
|
| }
|
| + return _buffer.charAt(_charOffset + 1);
|
| }
|
| - int tokenizePercent(int next) => select(0x3D, TokenType.PERCENT_EQ, TokenType.PERCENT);
|
| - int tokenizePlus(int next) {
|
| - next = advance();
|
| - if (0x2B == next) {
|
| - appendToken(TokenType.PLUS_PLUS);
|
| - return advance();
|
| - } else if (0x3D == next) {
|
| - appendToken(TokenType.PLUS_EQ);
|
| - return advance();
|
| - } else {
|
| - appendToken(TokenType.PLUS);
|
| - return next;
|
| - }
|
| +}
|
| +/**
|
| + * Instances of the class {@code TokenWithComment} represent a normal token that is preceded by
|
| + * comments.
|
| + */
|
| +class TokenWithComment extends Token {
|
| + /**
|
| + * The first comment in the list of comments that precede this token.
|
| + */
|
| + Token _precedingComment;
|
| + /**
|
| + * Initialize a newly created token to have the given type and offset and to be preceded by the
|
| + * comments reachable from the given comment.
|
| + * @param type the type of the token
|
| + * @param offset the offset from the beginning of the file to the first character in the token
|
| + * @param precedingComment the first comment in the list of comments that precede this token
|
| + */
|
| + TokenWithComment(TokenType type, int offset, Token precedingComment) : super(type, offset) {
|
| + this._precedingComment = precedingComment;
|
| }
|
| - int tokenizeSingleLineComment(int next) {
|
| - while (true) {
|
| - next = advance();
|
| - if (0xA == next || 0xD == next || -1 == next) {
|
| - appendCommentToken(TokenType.SINGLE_LINE_COMMENT, getString(_tokenStart, 0));
|
| - return next;
|
| - }
|
| + Token get precedingComments => _precedingComment;
|
| +}
|
| +/**
|
| + * Instances of the class {@code Token} represent a token that was scanned from the input. Each
|
| + * token knows which token follows it, acting as the head of a linked list of tokens.
|
| + */
|
| +class Token {
|
| + /**
|
| + * The type of the token.
|
| + */
|
| + TokenType _type;
|
| + /**
|
| + * The offset from the beginning of the file to the first character in the token.
|
| + */
|
| + int _offset = 0;
|
| + /**
|
| + * The previous token in the token stream.
|
| + */
|
| + Token _previous;
|
| + /**
|
| + * The next token in the token stream.
|
| + */
|
| + Token _next;
|
| + /**
|
| + * Initialize a newly created token to have the given type and offset.
|
| + * @param type the type of the token
|
| + * @param offset the offset from the beginning of the file to the first character in the token
|
| + */
|
| + Token(TokenType type, int offset) {
|
| + this._type = type;
|
| + this._offset = offset;
|
| + }
|
| + /**
|
| + * Return the offset from the beginning of the file to the character after last character of the
|
| + * token.
|
| + * @return the offset from the beginning of the file to the first character after last character
|
| + * of the token
|
| + */
|
| + int get end => _offset + length;
|
| + /**
|
| + * Return the number of characters in the node's source range.
|
| + * @return the number of characters in the node's source range
|
| + */
|
| + int get length => lexeme.length;
|
| + /**
|
| + * Return the lexeme that represents this token.
|
| + * @return the lexeme that represents this token
|
| + */
|
| + String get lexeme => _type.lexeme;
|
| + /**
|
| + * Return the next token in the token stream.
|
| + * @return the next token in the token stream
|
| + */
|
| + Token get next => _next;
|
| + /**
|
| + * Return the offset from the beginning of the file to the first character in the token.
|
| + * @return the offset from the beginning of the file to the first character in the token
|
| + */
|
| + int get offset => _offset;
|
| + /**
|
| + * Return the first comment in the list of comments that precede this token, or {@code null} if
|
| + * there are no comments preceding this token. Additional comments can be reached by following the
|
| + * token stream using {@link #getNext()} until {@code null} is returned.
|
| + * @return the first comment in the list of comments that precede this token
|
| + */
|
| + Token get precedingComments => null;
|
| + /**
|
| + * Return the previous token in the token stream.
|
| + * @return the previous token in the token stream
|
| + */
|
| + Token get previous => _previous;
|
| + /**
|
| + * Return the type of the token.
|
| + * @return the type of the token
|
| + */
|
| + TokenType get type => _type;
|
| + /**
|
| + * Return {@code true} if this token represents an operator.
|
| + * @return {@code true} if this token represents an operator
|
| + */
|
| + bool isOperator() => _type.isOperator();
|
| + /**
|
| + * Return {@code true} if this token is a synthetic token. A synthetic token is a token that was
|
| + * introduced by the parser in order to recover from an error in the code. Synthetic tokens always
|
| + * have a length of zero ({@code 0}).
|
| + * @return {@code true} if this token is a synthetic token
|
| + */
|
| + bool isSynthetic() => length == 0;
|
| + /**
|
| + * Return {@code true} if this token represents an operator that can be defined by users.
|
| + * @return {@code true} if this token represents an operator that can be defined by users
|
| + */
|
| + bool isUserDefinableOperator() => _type.isUserDefinableOperator();
|
| + /**
|
| + * Set the next token in the token stream to the given token. This has the side-effect of setting
|
| + * this token to be the previous token for the given token.
|
| + * @param token the next token in the token stream
|
| + * @return the token that was passed in
|
| + */
|
| + Token setNext(Token token) {
|
| + _next = token;
|
| + token.previous = this;
|
| + return token;
|
| + }
|
| + /**
|
| + * Set the next token in the token stream to the given token without changing which token is the
|
| + * previous token for the given token.
|
| + * @param token the next token in the token stream
|
| + * @return the token that was passed in
|
| + */
|
| + Token setNextWithoutSettingPrevious(Token token) {
|
| + _next = token;
|
| + return token;
|
| + }
|
| + /**
|
| + * Set the offset from the beginning of the file to the first character in the token to the given
|
| + * offset.
|
| + * @param offset the offset from the beginning of the file to the first character in the token
|
| + */
|
| + void set offset(int offset4) {
|
| + this._offset = offset4;
|
| + }
|
| + String toString() => lexeme;
|
| + /**
|
| + * Return the value of this token. For keyword tokens, this is the keyword associated with the
|
| + * token, for other tokens it is the lexeme associated with the token.
|
| + * @return the value of this token
|
| + */
|
| + Object value() => _type.lexeme;
|
| + /**
|
| + * Set the previous token in the token stream to the given token.
|
| + * @param previous the previous token in the token stream
|
| + */
|
| + void set previous(Token previous3) {
|
| + this._previous = previous3;
|
| + }
|
| +}
|
| +/**
|
| + * Instances of the class {@code StringScanner} implement a scanner that reads from a string. The
|
| + * scanning logic is in the superclass.
|
| + */
|
| +class StringScanner extends AbstractScanner {
|
| + /**
|
| + * The offset from the beginning of the file to the beginning of the source being scanned.
|
| + */
|
| + int _offsetDelta = 0;
|
| + /**
|
| + * The string from which characters will be read.
|
| + */
|
| + String _string;
|
| + /**
|
| + * The number of characters in the string.
|
| + */
|
| + int _stringLength = 0;
|
| + /**
|
| + * The index, relative to the string, of the last character that was read.
|
| + */
|
| + int _charOffset = 0;
|
| + /**
|
| + * Initialize a newly created scanner to scan the characters in the given string.
|
| + * @param source the source being scanned
|
| + * @param string the string from which characters will be read
|
| + * @param errorListener the error listener that will be informed of any errors that are found
|
| + */
|
| + StringScanner(Source source, String string, AnalysisErrorListener errorListener) : super(source, errorListener) {
|
| + this._offsetDelta = 0;
|
| + this._string = string;
|
| + this._stringLength = string.length;
|
| + this._charOffset = -1;
|
| + }
|
| + int get offset => _offsetDelta + _charOffset;
|
| + /**
|
| + * Record that the source begins on the given line and column at the given offset. The line starts
|
| + * for lines before the given line will not be correct.
|
| + * <p>
|
| + * This method must be invoked at most one time and must be invoked before scanning begins. The
|
| + * values provided must be sensible. The results are undefined if these conditions are violated.
|
| + * @param line the one-based index of the line containing the first character of the source
|
| + * @param column the one-based index of the column in which the first character of the source
|
| + * occurs
|
| + * @param offset the zero-based offset from the beginning of the larger context to the first
|
| + * character of the source
|
| + */
|
| + void setSourceStart(int line, int column, int offset) {
|
| + if (line < 1 || column < 1 || offset < 0 || (line + column - 2) >= offset) {
|
| + return;
|
| }
|
| - }
|
| - int tokenizeSingleLineRawString(int next, int quoteChar, int start) {
|
| - next = advance();
|
| - while (next != -1) {
|
| - if (next == quoteChar) {
|
| - appendStringToken(TokenType.STRING, getString(start, 0));
|
| - return advance();
|
| - } else if (next == 0xD || next == 0xA) {
|
| - reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
|
| - appendStringToken(TokenType.STRING, getString(start, 0));
|
| - return advance();
|
| - }
|
| - next = advance();
|
| + _offsetDelta = 1;
|
| + for (int i = 2; i < line; i++) {
|
| + recordStartOfLine();
|
| }
|
| - reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
|
| - appendStringToken(TokenType.STRING, getString(start, 0));
|
| - return advance();
|
| + _offsetDelta = offset - column + 1;
|
| + recordStartOfLine();
|
| + _offsetDelta = offset;
|
| }
|
| - int tokenizeSingleLineString(int next, int quoteChar, int start) {
|
| - while (next != quoteChar) {
|
| - if (next == 0x5C) {
|
| - next = advance();
|
| - } else if (next == 0x24) {
|
| - appendStringToken(TokenType.STRING, getString(start, -1));
|
| - beginToken();
|
| - next = tokenizeStringInterpolation(start);
|
| - start = offset;
|
| - continue;
|
| - }
|
| - if (next <= 0xD && (next == 0xA || next == 0xD || next == -1)) {
|
| - reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, []);
|
| - appendStringToken(TokenType.STRING, getString(start, 0));
|
| - return advance();
|
| - }
|
| - next = advance();
|
| + int advance() {
|
| + if (_charOffset + 1 >= _stringLength) {
|
| + return -1;
|
| }
|
| - appendStringToken(TokenType.STRING, getString(start, 0));
|
| - return advance();
|
| + return _string.codeUnitAt(++_charOffset);
|
| }
|
| - int tokenizeSlashOrComment(int next) {
|
| - next = advance();
|
| - if (0x2A == next) {
|
| - return tokenizeMultiLineComment(next);
|
| - } else if (0x2F == next) {
|
| - return tokenizeSingleLineComment(next);
|
| - } else if (0x3D == next) {
|
| - appendToken(TokenType.SLASH_EQ);
|
| - return advance();
|
| - } else {
|
| - appendToken(TokenType.SLASH);
|
| - return next;
|
| + String getString(int start, int endDelta) => _string.substring(start - _offsetDelta, _charOffset + 1 + endDelta);
|
| + int peek() {
|
| + if (_charOffset + 1 >= _string.length) {
|
| + return -1;
|
| }
|
| + return _string.codeUnitAt(_charOffset + 1);
|
| }
|
| - int tokenizeString(int next, int start, bool raw) {
|
| - int quoteChar = next;
|
| - next = advance();
|
| - if (quoteChar == next) {
|
| - next = advance();
|
| - if (quoteChar == next) {
|
| - return tokenizeMultiLineString(quoteChar, start, raw);
|
| - } else {
|
| - appendStringToken(TokenType.STRING, getString(start, -1));
|
| - return next;
|
| - }
|
| - }
|
| - if (raw) {
|
| - return tokenizeSingleLineRawString(next, quoteChar, start);
|
| - } else {
|
| - return tokenizeSingleLineString(next, quoteChar, start);
|
| - }
|
| +}
|
| +/**
|
| + * Instances of the class {@code BeginTokenWithComment} represent a begin token that is preceded by
|
| + * comments.
|
| + */
|
| +class BeginTokenWithComment extends BeginToken {
|
| + /**
|
| + * The first comment in the list of comments that precede this token.
|
| + */
|
| + Token _precedingComment;
|
| + /**
|
| + * Initialize a newly created token to have the given type and offset and to be preceded by the
|
| + * comments reachable from the given comment.
|
| + * @param type the type of the token
|
| + * @param offset the offset from the beginning of the file to the first character in the token
|
| + * @param precedingComment the first comment in the list of comments that precede this token
|
| + */
|
| + BeginTokenWithComment(TokenType type, int offset, Token precedingComment) : super(type, offset) {
|
| + this._precedingComment = precedingComment;
|
| }
|
| - int tokenizeStringInterpolation(int start) {
|
| - beginToken();
|
| - int next = advance();
|
| - if (next == 0x7B) {
|
| - return tokenizeInterpolatedExpression(next, start);
|
| - } else {
|
| - return tokenizeInterpolatedIdentifier(next, start);
|
| - }
|
| + Token get precedingComments => _precedingComment;
|
| +}
|
| +/**
|
| + * Instances of the class {@code KeywordToken} represent a keyword in the language.
|
| + */
|
| +class KeywordToken extends Token {
|
| + /**
|
| + * The keyword being represented by this token.
|
| + */
|
| + Keyword _keyword;
|
| + /**
|
| + * Initialize a newly created token to represent the given keyword.
|
| + * @param keyword the keyword being represented by this token
|
| + * @param offset the offset from the beginning of the file to the first character in the token
|
| + */
|
| + KeywordToken(Keyword keyword, int offset) : super(TokenType.KEYWORD, offset) {
|
| + this._keyword = keyword;
|
| }
|
| - int tokenizeTag(int next) {
|
| - if (offset == 0) {
|
| - if (peek() == 0x21) {
|
| - do {
|
| - next = advance();
|
| - } while (next != 0xA && next != 0xD && next > 0);
|
| - appendStringToken(TokenType.SCRIPT_TAG, getString(_tokenStart, 0));
|
| - return next;
|
| - }
|
| - }
|
| - appendToken(TokenType.HASH);
|
| - return advance();
|
| + /**
|
| + * Return the keyword being represented by this token.
|
| + * @return the keyword being represented by this token
|
| + */
|
| + Keyword get keyword => _keyword;
|
| + String get lexeme => _keyword.syntax;
|
| + Keyword value() => _keyword;
|
| +}
|
| +/**
|
| + * Instances of the class {@code BeginToken} represent the opening half of a grouping pair of
|
| + * tokens. This is used for curly brackets ('{'), parentheses ('('), and square brackets ('[').
|
| + */
|
| +class BeginToken extends Token {
|
| + /**
|
| + * The token that corresponds to this token.
|
| + */
|
| + Token _endToken;
|
| + /**
|
| + * Initialize a newly created token representing the opening half of a grouping pair of tokens.
|
| + * @param type the type of the token
|
| + * @param offset the offset from the beginning of the file to the first character in the token
|
| + */
|
| + BeginToken(TokenType type, int offset) : super(type, offset) {
|
| + assert((identical(type, TokenType.OPEN_CURLY_BRACKET) || identical(type, TokenType.OPEN_PAREN) || identical(type, TokenType.OPEN_SQUARE_BRACKET) || identical(type, TokenType.STRING_INTERPOLATION_EXPRESSION)));
|
| }
|
| - int tokenizeTilde(int next) {
|
| - next = advance();
|
| - if (next == 0x2F) {
|
| - return select(0x3D, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH);
|
| - } else {
|
| - appendToken(TokenType.TILDE);
|
| - return next;
|
| - }
|
| + /**
|
| + * Return the token that corresponds to this token.
|
| + * @return the token that corresponds to this token
|
| + */
|
| + Token get endToken => _endToken;
|
| + /**
|
| + * Set the token that corresponds to this token to the given token.
|
| + * @param token the token that corresponds to this token
|
| + */
|
| + void set endToken(Token token) {
|
| + this._endToken = token;
|
| + }
|
| +}
|
| +/**
|
| + * The enumeration {@code TokenClass} represents classes (or groups) of tokens with a similar use.
|
| + */
|
| +class TokenClass {
|
| + /**
|
| + * A value used to indicate that the token type is not part of any specific class of token.
|
| + */
|
| + static final TokenClass NO_CLASS = new TokenClass.con1('NO_CLASS', 0);
|
| + /**
|
| + * A value used to indicate that the token type is an additive operator.
|
| + */
|
| + static final TokenClass ADDITIVE_OPERATOR = new TokenClass.con2('ADDITIVE_OPERATOR', 1, 12);
|
| + /**
|
| + * A value used to indicate that the token type is an assignment operator.
|
| + */
|
| + static final TokenClass ASSIGNMENT_OPERATOR = new TokenClass.con2('ASSIGNMENT_OPERATOR', 2, 1);
|
| + /**
|
| + * A value used to indicate that the token type is a bitwise-and operator.
|
| + */
|
| + static final TokenClass BITWISE_AND_OPERATOR = new TokenClass.con2('BITWISE_AND_OPERATOR', 3, 8);
|
| + /**
|
| + * A value used to indicate that the token type is a bitwise-or operator.
|
| + */
|
| + static final TokenClass BITWISE_OR_OPERATOR = new TokenClass.con2('BITWISE_OR_OPERATOR', 4, 6);
|
| + /**
|
| + * A value used to indicate that the token type is a bitwise-xor operator.
|
| + */
|
| + static final TokenClass BITWISE_XOR_OPERATOR = new TokenClass.con2('BITWISE_XOR_OPERATOR', 5, 7);
|
| + /**
|
| + * A value used to indicate that the token type is a cascade operator.
|
| + */
|
| + static final TokenClass CASCADE_OPERATOR = new TokenClass.con2('CASCADE_OPERATOR', 6, 2);
|
| + /**
|
| + * A value used to indicate that the token type is a conditional operator.
|
| + */
|
| + static final TokenClass CONDITIONAL_OPERATOR = new TokenClass.con2('CONDITIONAL_OPERATOR', 7, 3);
|
| + /**
|
| + * A value used to indicate that the token type is an equality operator.
|
| + */
|
| + static final TokenClass EQUALITY_OPERATOR = new TokenClass.con2('EQUALITY_OPERATOR', 8, 9);
|
| + /**
|
| + * A value used to indicate that the token type is a logical-and operator.
|
| + */
|
| + static final TokenClass LOGICAL_AND_OPERATOR = new TokenClass.con2('LOGICAL_AND_OPERATOR', 9, 5);
|
| + /**
|
| + * A value used to indicate that the token type is a logical-or operator.
|
| + */
|
| + static final TokenClass LOGICAL_OR_OPERATOR = new TokenClass.con2('LOGICAL_OR_OPERATOR', 10, 4);
|
| + /**
|
| + * A value used to indicate that the token type is a multiplicative operator.
|
| + */
|
| + static final TokenClass MULTIPLICATIVE_OPERATOR = new TokenClass.con2('MULTIPLICATIVE_OPERATOR', 11, 13);
|
| + /**
|
| + * A value used to indicate that the token type is a relational operator.
|
| + */
|
| + static final TokenClass RELATIONAL_OPERATOR = new TokenClass.con2('RELATIONAL_OPERATOR', 12, 10);
|
| + /**
|
| + * A value used to indicate that the token type is a shift operator.
|
| + */
|
| + static final TokenClass SHIFT_OPERATOR = new TokenClass.con2('SHIFT_OPERATOR', 13, 11);
|
| + /**
|
| + * A value used to indicate that the token type is a unary operator.
|
| + */
|
| + static final TokenClass UNARY_POSTFIX_OPERATOR = new TokenClass.con2('UNARY_POSTFIX_OPERATOR', 14, 15);
|
| + /**
|
| + * A value used to indicate that the token type is a unary operator.
|
| + */
|
| + static final TokenClass UNARY_PREFIX_OPERATOR = new TokenClass.con2('UNARY_PREFIX_OPERATOR', 15, 14);
|
| + static final List<TokenClass> values = [NO_CLASS, ADDITIVE_OPERATOR, ASSIGNMENT_OPERATOR, BITWISE_AND_OPERATOR, BITWISE_OR_OPERATOR, BITWISE_XOR_OPERATOR, CASCADE_OPERATOR, CONDITIONAL_OPERATOR, EQUALITY_OPERATOR, LOGICAL_AND_OPERATOR, LOGICAL_OR_OPERATOR, MULTIPLICATIVE_OPERATOR, RELATIONAL_OPERATOR, SHIFT_OPERATOR, UNARY_POSTFIX_OPERATOR, UNARY_PREFIX_OPERATOR];
|
| + String __name;
|
| + int __ordinal = 0;
|
| + /**
|
| + * The precedence of tokens of this class, or {@code 0} if the such tokens do not represent an
|
| + * operator.
|
| + */
|
| + int _precedence = 0;
|
| + TokenClass.con1(String ___name, int ___ordinal) {
|
| + _jtd_constructor_269_impl(___name, ___ordinal);
|
| + }
|
| + _jtd_constructor_269_impl(String ___name, int ___ordinal) {
|
| + _jtd_constructor_270_impl(___name, ___ordinal, 0);
|
| + }
|
| + TokenClass.con2(String ___name, int ___ordinal, int precedence2) {
|
| + _jtd_constructor_270_impl(___name, ___ordinal, precedence2);
|
| + }
|
| + _jtd_constructor_270_impl(String ___name, int ___ordinal, int precedence2) {
|
| + __name = ___name;
|
| + __ordinal = ___ordinal;
|
| + this._precedence = precedence2;
|
| }
|
| + /**
|
| + * Return the precedence of tokens of this class, or {@code 0} if the such tokens do not represent
|
| + * an operator.
|
| + * @return the precedence of tokens of this class
|
| + */
|
| + int get precedence => _precedence;
|
| + String toString() => __name;
|
| }
|
| /**
|
| * Instances of the class {@code KeywordTokenWithComment} implement a keyword token that is preceded
|
| @@ -1764,107 +1680,188 @@ class KeywordTokenWithComment extends KeywordToken {
|
| Token get precedingComments => _precedingComment;
|
| }
|
| /**
|
| - * Instances of the abstract class {@code KeywordState} represent a state in a state machine used to
|
| - * scan keywords.
|
| + * The enumeration {@code TokenType} defines the types of tokens that can be returned by the
|
| + * scanner.
|
| */
|
| -class KeywordState {
|
| +class TokenType {
|
| /**
|
| - * An empty transition table used by leaf states.
|
| + * The type of the token that marks the end of the input.
|
| */
|
| - static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26);
|
| + static final TokenType EOF = new TokenType_EOF('EOF', 0, null, "");
|
| + static final TokenType DOUBLE = new TokenType.con1('DOUBLE', 1);
|
| + static final TokenType HEXADECIMAL = new TokenType.con1('HEXADECIMAL', 2);
|
| + static final TokenType IDENTIFIER = new TokenType.con1('IDENTIFIER', 3);
|
| + static final TokenType INT = new TokenType.con1('INT', 4);
|
| + static final TokenType KEYWORD = new TokenType.con1('KEYWORD', 5);
|
| + static final TokenType MULTI_LINE_COMMENT = new TokenType.con1('MULTI_LINE_COMMENT', 6);
|
| + static final TokenType SCRIPT_TAG = new TokenType.con1('SCRIPT_TAG', 7);
|
| + static final TokenType SINGLE_LINE_COMMENT = new TokenType.con1('SINGLE_LINE_COMMENT', 8);
|
| + static final TokenType STRING = new TokenType.con1('STRING', 9);
|
| + static final TokenType AMPERSAND = new TokenType.con2('AMPERSAND', 10, TokenClass.BITWISE_AND_OPERATOR, "&");
|
| + static final TokenType AMPERSAND_AMPERSAND = new TokenType.con2('AMPERSAND_AMPERSAND', 11, TokenClass.LOGICAL_AND_OPERATOR, "&&");
|
| + static final TokenType AMPERSAND_EQ = new TokenType.con2('AMPERSAND_EQ', 12, TokenClass.ASSIGNMENT_OPERATOR, "&=");
|
| + static final TokenType AT = new TokenType.con2('AT', 13, null, "@");
|
| + static final TokenType BANG = new TokenType.con2('BANG', 14, TokenClass.UNARY_PREFIX_OPERATOR, "!");
|
| + static final TokenType BANG_EQ = new TokenType.con2('BANG_EQ', 15, TokenClass.EQUALITY_OPERATOR, "!=");
|
| + static final TokenType BAR = new TokenType.con2('BAR', 16, TokenClass.BITWISE_OR_OPERATOR, "|");
|
| + static final TokenType BAR_BAR = new TokenType.con2('BAR_BAR', 17, TokenClass.LOGICAL_OR_OPERATOR, "||");
|
| + static final TokenType BAR_EQ = new TokenType.con2('BAR_EQ', 18, TokenClass.ASSIGNMENT_OPERATOR, "|=");
|
| + static final TokenType COLON = new TokenType.con2('COLON', 19, null, ":");
|
| + static final TokenType COMMA = new TokenType.con2('COMMA', 20, null, ",");
|
| + static final TokenType CARET = new TokenType.con2('CARET', 21, TokenClass.BITWISE_XOR_OPERATOR, "^");
|
| + static final TokenType CARET_EQ = new TokenType.con2('CARET_EQ', 22, TokenClass.ASSIGNMENT_OPERATOR, "^=");
|
| + static final TokenType CLOSE_CURLY_BRACKET = new TokenType.con2('CLOSE_CURLY_BRACKET', 23, null, "}");
|
| + static final TokenType CLOSE_PAREN = new TokenType.con2('CLOSE_PAREN', 24, null, ")");
|
| + static final TokenType CLOSE_SQUARE_BRACKET = new TokenType.con2('CLOSE_SQUARE_BRACKET', 25, null, "]");
|
| + static final TokenType EQ = new TokenType.con2('EQ', 26, TokenClass.ASSIGNMENT_OPERATOR, "=");
|
| + static final TokenType EQ_EQ = new TokenType.con2('EQ_EQ', 27, TokenClass.EQUALITY_OPERATOR, "==");
|
| + static final TokenType FUNCTION = new TokenType.con2('FUNCTION', 28, null, "=>");
|
| + static final TokenType GT = new TokenType.con2('GT', 29, TokenClass.RELATIONAL_OPERATOR, ">");
|
| + static final TokenType GT_EQ = new TokenType.con2('GT_EQ', 30, TokenClass.RELATIONAL_OPERATOR, ">=");
|
| + static final TokenType GT_GT = new TokenType.con2('GT_GT', 31, TokenClass.SHIFT_OPERATOR, ">>");
|
| + static final TokenType GT_GT_EQ = new TokenType.con2('GT_GT_EQ', 32, TokenClass.ASSIGNMENT_OPERATOR, ">>=");
|
| + static final TokenType HASH = new TokenType.con2('HASH', 33, null, "#");
|
| + static final TokenType INDEX = new TokenType.con2('INDEX', 34, TokenClass.UNARY_POSTFIX_OPERATOR, "[]");
|
| + static final TokenType INDEX_EQ = new TokenType.con2('INDEX_EQ', 35, TokenClass.UNARY_POSTFIX_OPERATOR, "[]=");
|
| + static final TokenType IS = new TokenType.con2('IS', 36, TokenClass.RELATIONAL_OPERATOR, "is");
|
| + static final TokenType LT = new TokenType.con2('LT', 37, TokenClass.RELATIONAL_OPERATOR, "<");
|
| + static final TokenType LT_EQ = new TokenType.con2('LT_EQ', 38, TokenClass.RELATIONAL_OPERATOR, "<=");
|
| + static final TokenType LT_LT = new TokenType.con2('LT_LT', 39, TokenClass.SHIFT_OPERATOR, "<<");
|
| + static final TokenType LT_LT_EQ = new TokenType.con2('LT_LT_EQ', 40, TokenClass.ASSIGNMENT_OPERATOR, "<<=");
|
| + static final TokenType MINUS = new TokenType.con2('MINUS', 41, TokenClass.ADDITIVE_OPERATOR, "-");
|
| + static final TokenType MINUS_EQ = new TokenType.con2('MINUS_EQ', 42, TokenClass.ASSIGNMENT_OPERATOR, "-=");
|
| + static final TokenType MINUS_MINUS = new TokenType.con2('MINUS_MINUS', 43, TokenClass.UNARY_PREFIX_OPERATOR, "--");
|
| + static final TokenType OPEN_CURLY_BRACKET = new TokenType.con2('OPEN_CURLY_BRACKET', 44, null, "{");
|
| + static final TokenType OPEN_PAREN = new TokenType.con2('OPEN_PAREN', 45, TokenClass.UNARY_POSTFIX_OPERATOR, "(");
|
| + static final TokenType OPEN_SQUARE_BRACKET = new TokenType.con2('OPEN_SQUARE_BRACKET', 46, TokenClass.UNARY_POSTFIX_OPERATOR, "[");
|
| + static final TokenType PERCENT = new TokenType.con2('PERCENT', 47, TokenClass.MULTIPLICATIVE_OPERATOR, "%");
|
| + static final TokenType PERCENT_EQ = new TokenType.con2('PERCENT_EQ', 48, TokenClass.ASSIGNMENT_OPERATOR, "%=");
|
| + static final TokenType PERIOD = new TokenType.con2('PERIOD', 49, TokenClass.UNARY_POSTFIX_OPERATOR, ".");
|
| + static final TokenType PERIOD_PERIOD = new TokenType.con2('PERIOD_PERIOD', 50, TokenClass.CASCADE_OPERATOR, "..");
|
| + static final TokenType PLUS = new TokenType.con2('PLUS', 51, TokenClass.ADDITIVE_OPERATOR, "+");
|
| + static final TokenType PLUS_EQ = new TokenType.con2('PLUS_EQ', 52, TokenClass.ASSIGNMENT_OPERATOR, "+=");
|
| + static final TokenType PLUS_PLUS = new TokenType.con2('PLUS_PLUS', 53, TokenClass.UNARY_PREFIX_OPERATOR, "++");
|
| + static final TokenType QUESTION = new TokenType.con2('QUESTION', 54, TokenClass.CONDITIONAL_OPERATOR, "?");
|
| + static final TokenType SEMICOLON = new TokenType.con2('SEMICOLON', 55, null, ";");
|
| + static final TokenType SLASH = new TokenType.con2('SLASH', 56, TokenClass.MULTIPLICATIVE_OPERATOR, "/");
|
| + static final TokenType SLASH_EQ = new TokenType.con2('SLASH_EQ', 57, TokenClass.ASSIGNMENT_OPERATOR, "/=");
|
| + static final TokenType STAR = new TokenType.con2('STAR', 58, TokenClass.MULTIPLICATIVE_OPERATOR, "*");
|
| + static final TokenType STAR_EQ = new TokenType.con2('STAR_EQ', 59, TokenClass.ASSIGNMENT_OPERATOR, "*=");
|
| + static final TokenType STRING_INTERPOLATION_EXPRESSION = new TokenType.con2('STRING_INTERPOLATION_EXPRESSION', 60, null, "\${");
|
| + static final TokenType STRING_INTERPOLATION_IDENTIFIER = new TokenType.con2('STRING_INTERPOLATION_IDENTIFIER', 61, null, "\$");
|
| + static final TokenType TILDE = new TokenType.con2('TILDE', 62, TokenClass.UNARY_PREFIX_OPERATOR, "~");
|
| + static final TokenType TILDE_SLASH = new TokenType.con2('TILDE_SLASH', 63, TokenClass.MULTIPLICATIVE_OPERATOR, "~/");
|
| + static final TokenType TILDE_SLASH_EQ = new TokenType.con2('TILDE_SLASH_EQ', 64, TokenClass.ASSIGNMENT_OPERATOR, "~/=");
|
| + static final TokenType BACKPING = new TokenType.con2('BACKPING', 65, null, "`");
|
| + static final TokenType BACKSLASH = new TokenType.con2('BACKSLASH', 66, null, "\\");
|
| + static final TokenType PERIOD_PERIOD_PERIOD = new TokenType.con2('PERIOD_PERIOD_PERIOD', 67, null, "...");
|
| + static final List<TokenType> values = [EOF, DOUBLE, HEXADECIMAL, IDENTIFIER, INT, KEYWORD, MULTI_LINE_COMMENT, SCRIPT_TAG, SINGLE_LINE_COMMENT, STRING, AMPERSAND, AMPERSAND_AMPERSAND, AMPERSAND_EQ, AT, BANG, BANG_EQ, BAR, BAR_BAR, BAR_EQ, COLON, COMMA, CARET, CARET_EQ, CLOSE_CURLY_BRACKET, CLOSE_PAREN, CLOSE_SQUARE_BRACKET, EQ, EQ_EQ, FUNCTION, GT, GT_EQ, GT_GT, GT_GT_EQ, HASH, INDEX, INDEX_EQ, IS, LT, LT_EQ, LT_LT, LT_LT_EQ, MINUS, MINUS_EQ, MINUS_MINUS, OPEN_CURLY_BRACKET, OPEN_PAREN, OPEN_SQUARE_BRACKET, PERCENT, PERCENT_EQ, PERIOD, PERIOD_PERIOD, PLUS, PLUS_EQ, PLUS_PLUS, QUESTION, SEMICOLON, SLASH, SLASH_EQ, STAR, STAR_EQ, STRING_INTERPOLATION_EXPRESSION, STRING_INTERPOLATION_IDENTIFIER, TILDE, TILDE_SLASH, TILDE_SLASH_EQ, BACKPING, BACKSLASH, PERIOD_PERIOD_PERIOD];
|
| + String __name;
|
| + int __ordinal = 0;
|
| /**
|
| - * The initial state in the state machine.
|
| + * The class of the token.
|
| */
|
| - static KeywordState KEYWORD_STATE = createKeywordStateTable();
|
| + TokenClass _tokenClass;
|
| /**
|
| - * Create the next state in the state machine where we have already recognized the subset of
|
| - * strings in the given array of strings starting at the given offset and having the given length.
|
| - * All of these strings have a common prefix and the next character is at the given start index.
|
| - * @param start the index of the character in the strings used to transition to a new state
|
| - * @param strings an array containing all of the strings that will be recognized by the state
|
| - * machine
|
| - * @param offset the offset of the first string in the array that has the prefix that is assumed
|
| - * to have been recognized by the time we reach the state being built
|
| - * @param length the number of strings in the array that pass through the state being built
|
| - * @return the state that was created
|
| + * The lexeme that defines this type of token, or {@code null} if there is more than one possible
|
| + * lexeme for this type of token.
|
| */
|
| - static KeywordState computeKeywordStateTable(int start, List<String> strings, int offset, int length12) {
|
| - List<KeywordState> result = new List<KeywordState>(26);
|
| - assert(length12 != 0);
|
| - int chunk = 0x0;
|
| - int chunkStart = -1;
|
| - bool isLeaf = false;
|
| - for (int i = offset; i < offset + length12; i++) {
|
| - if (strings[i].length == start) {
|
| - isLeaf = true;
|
| - }
|
| - if (strings[i].length > start) {
|
| - int c = strings[i].codeUnitAt(start);
|
| - if (chunk != c) {
|
| - if (chunkStart != -1) {
|
| - result[chunk - 0x61] = computeKeywordStateTable(start + 1, strings, chunkStart, i - chunkStart);
|
| - }
|
| - chunkStart = i;
|
| - chunk = c;
|
| - }
|
| - }
|
| - }
|
| - if (chunkStart != -1) {
|
| - assert(result[chunk - 0x61] == null);
|
| - result[chunk - 0x61] = computeKeywordStateTable(start + 1, strings, chunkStart, offset + length12 - chunkStart);
|
| - } else {
|
| - assert(length12 == 1);
|
| - return new KeywordState(_EMPTY_TABLE, strings[offset]);
|
| - }
|
| - if (isLeaf) {
|
| - return new KeywordState(result, strings[offset]);
|
| - } else {
|
| - return new KeywordState(result, null);
|
| - }
|
| + String _lexeme;
|
| + TokenType.con1(String ___name, int ___ordinal) {
|
| + _jtd_constructor_271_impl(___name, ___ordinal);
|
| + }
|
| + _jtd_constructor_271_impl(String ___name, int ___ordinal) {
|
| + _jtd_constructor_272_impl(___name, ___ordinal, TokenClass.NO_CLASS, null);
|
| + }
|
| + TokenType.con2(String ___name, int ___ordinal, TokenClass tokenClass2, String lexeme2) {
|
| + _jtd_constructor_272_impl(___name, ___ordinal, tokenClass2, lexeme2);
|
| + }
|
| + _jtd_constructor_272_impl(String ___name, int ___ordinal, TokenClass tokenClass2, String lexeme2) {
|
| + __name = ___name;
|
| + __ordinal = ___ordinal;
|
| + this._tokenClass = tokenClass2 == null ? TokenClass.NO_CLASS : tokenClass2;
|
| + this._lexeme = lexeme2;
|
| }
|
| /**
|
| - * Create the initial state in the state machine.
|
| - * @return the state that was created
|
| + * Return the lexeme that defines this type of token, or {@code null} if there is more than one
|
| + * possible lexeme for this type of token.
|
| + * @return the lexeme that defines this type of token
|
| */
|
| - static KeywordState createKeywordStateTable() {
|
| - List<Keyword> values2 = Keyword.values;
|
| - List<String> strings = new List<String>(values2.length);
|
| - for (int i = 0; i < values2.length; i++) {
|
| - strings[i] = values2[i].syntax;
|
| - }
|
| - strings.sort();
|
| - return computeKeywordStateTable(0, strings, 0, strings.length);
|
| - }
|
| + String get lexeme => _lexeme;
|
| /**
|
| - * A table mapping characters to the states to which those characters will transition. (The index
|
| - * into the array is the offset from the character {@code 'a'} to the transitioning character.)
|
| + * Return the precedence of the token, or {@code 0} if the token does not represent an operator.
|
| + * @return the precedence of the token
|
| */
|
| - List<KeywordState> _table;
|
| + int get precedence => _tokenClass.precedence;
|
| /**
|
| - * The keyword that is recognized by this state, or {@code null} if this state is not a terminal
|
| - * state.
|
| + * Return {@code true} if this type of token represents an additive operator.
|
| + * @return {@code true} if this type of token represents an additive operator
|
| */
|
| - Keyword _keyword2;
|
| + bool isAdditiveOperator() => identical(_tokenClass, TokenClass.ADDITIVE_OPERATOR);
|
| /**
|
| - * Initialize a newly created state to have the given transitions and to recognize the keyword
|
| - * with the given syntax.
|
| - * @param table a table mapping characters to the states to which those characters will transition
|
| - * @param syntax the syntax of the keyword that is recognized by the state
|
| + * Return {@code true} if this type of token represents an assignment operator.
|
| + * @return {@code true} if this type of token represents an assignment operator
|
| */
|
| - KeywordState(List<KeywordState> table, String syntax) {
|
| - this._table = table;
|
| - this._keyword2 = (syntax == null) ? null : Keyword.keywords[syntax];
|
| - }
|
| + bool isAssignmentOperator() => identical(_tokenClass, TokenClass.ASSIGNMENT_OPERATOR);
|
| /**
|
| - * Return the keyword that was recognized by this state, or {@code null} if this state does not
|
| - * recognized a keyword.
|
| - * @return the keyword that was matched by reaching this state
|
| + * Return {@code true} if this type of token represents an associative operator. An associative
|
| + * operator is an operator for which the following equality is true:{@code (a * b) * c == a * (b * c)}. In other words, if the result of applying the operator to
|
| + * multiple operands does not depend on the order in which those applications occur.
|
| + * <p>
|
| + * Note: This method considers the logical-and and logical-or operators to be associative, even
|
| + * though the order in which the application of those operators can have an effect because
|
| + * evaluation of the right-hand operand is conditional.
|
| + * @return {@code true} if this type of token represents an associative operator
|
| */
|
| - Keyword keyword() => _keyword2;
|
| + bool isAssociativeOperator() => identical(this, AMPERSAND) || identical(this, AMPERSAND_AMPERSAND) || identical(this, BAR) || identical(this, BAR_BAR) || identical(this, CARET) || identical(this, PLUS) || identical(this, STAR);
|
| /**
|
| - * Return the state that follows this state on a transition of the given character, or{@code null} if there is no valid state reachable from this state with such a transition.
|
| - * @param c the character used to transition from this state to another state
|
| - * @return the state that follows this state on a transition of the given character
|
| + * Return {@code true} if this type of token represents an equality operator.
|
| + * @return {@code true} if this type of token represents an equality operator
|
| */
|
| - KeywordState next(int c) => _table[c - 0x61];
|
| + bool isEqualityOperator() => identical(_tokenClass, TokenClass.EQUALITY_OPERATOR);
|
| + /**
|
| + * Return {@code true} if this type of token represents an increment operator.
|
| + * @return {@code true} if this type of token represents an increment operator
|
| + */
|
| + bool isIncrementOperator() => identical(_lexeme, "++") || identical(_lexeme, "--");
|
| + /**
|
| + * Return {@code true} if this type of token represents a multiplicative operator.
|
| + * @return {@code true} if this type of token represents a multiplicative operator
|
| + */
|
| + bool isMultiplicativeOperator() => identical(_tokenClass, TokenClass.MULTIPLICATIVE_OPERATOR);
|
| + /**
|
| + * Return {@code true} if this token type represents an operator.
|
| + * @return {@code true} if this token type represents an operator
|
| + */
|
| + bool isOperator() => _tokenClass != TokenClass.NO_CLASS && this != OPEN_PAREN && this != OPEN_SQUARE_BRACKET && this != PERIOD;
|
| + /**
|
| + * Return {@code true} if this type of token represents a relational operator.
|
| + * @return {@code true} if this type of token represents a relational operator
|
| + */
|
| + bool isRelationalOperator() => identical(_tokenClass, TokenClass.RELATIONAL_OPERATOR);
|
| + /**
|
| + * Return {@code true} if this type of token represents a shift operator.
|
| + * @return {@code true} if this type of token represents a shift operator
|
| + */
|
| + bool isShiftOperator() => identical(_tokenClass, TokenClass.SHIFT_OPERATOR);
|
| + /**
|
| + * Return {@code true} if this type of token represents a unary postfix operator.
|
| + * @return {@code true} if this type of token represents a unary postfix operator
|
| + */
|
| + bool isUnaryPostfixOperator() => identical(_tokenClass, TokenClass.UNARY_POSTFIX_OPERATOR);
|
| + /**
|
| + * Return {@code true} if this type of token represents a unary prefix operator.
|
| + * @return {@code true} if this type of token represents a unary prefix operator
|
| + */
|
| + bool isUnaryPrefixOperator() => identical(_tokenClass, TokenClass.UNARY_PREFIX_OPERATOR);
|
| + /**
|
| + * Return {@code true} if this token type represents an operator that can be defined by users.
|
| + * @return {@code true} if this token type represents an operator that can be defined by users
|
| + */
|
| + bool isUserDefinableOperator() => identical(_lexeme, "==") || identical(_lexeme, "~") || identical(_lexeme, "[]") || identical(_lexeme, "[]=") || identical(_lexeme, "*") || identical(_lexeme, "/") || identical(_lexeme, "%") || identical(_lexeme, "~/") || identical(_lexeme, "+") || identical(_lexeme, "-") || identical(_lexeme, "<<") || identical(_lexeme, ">>") || identical(_lexeme, ">=") || identical(_lexeme, ">") || identical(_lexeme, "<=") || identical(_lexeme, "<") || identical(_lexeme, "&") || identical(_lexeme, "^") || identical(_lexeme, "|");
|
| + String toString() => __name;
|
| }
|
| +class TokenType_EOF extends TokenType {
|
| + TokenType_EOF(String ___name, int ___ordinal, TokenClass arg0, String arg1) : super.con2(___name, ___ordinal, arg0, arg1);
|
| + String toString() => "-eof-";
|
| +}
|
|
|