219 lines
6.6 KiB
C++
219 lines
6.6 KiB
C++
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
//
|
|
// Scanner class for the Dart language. The scanner reads source text
|
|
// and produces a stream of tokens which is used by the parser.
|
|
//
|
|
|
|
#ifndef RUNTIME_VM_SCANNER_H_
|
|
#define RUNTIME_VM_SCANNER_H_
|
|
|
|
#include "vm/growable_array.h"
|
|
#include "vm/token.h"
|
|
|
|
namespace dart {
|
|
|
|
// Forward declarations.
|
|
class Array;
|
|
class Library;
|
|
class RawString;
|
|
class ScanContext;
|
|
class String;
|
|
|
|
// A call to Scan() scans the source one token at at time.
|
|
// The scanned token is returned by current_token().
|
|
// GetStream() scans the entire source text and returns a stream of tokens.
|
|
class Scanner : ValueObject {
|
|
public:
|
|
typedef uint16_t (*CharAtFunc)(const String& str, intptr_t index);
|
|
|
|
// SourcePosition describes a text location in user friendly
|
|
// terms of line number and column.
|
|
struct SourcePosition {
|
|
int line;
|
|
int column;
|
|
};
|
|
|
|
// TokenDesc defines the kind of a token and its location in
|
|
// the source text.
|
|
struct TokenDescriptor {
|
|
Token::Kind kind;
|
|
int offset; // Offset in source string.
|
|
SourcePosition position; // Text position in source.
|
|
const String* literal; // Identifier, number or string literal.
|
|
};
|
|
|
|
class TokenCollector : public ValueObject {
|
|
public:
|
|
TokenCollector() {}
|
|
virtual ~TokenCollector() {}
|
|
virtual void AddToken(const TokenDescriptor& token) {}
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(TokenCollector);
|
|
};
|
|
|
|
// Initializes scanner to scan string source.
|
|
Scanner(const String& source, const String& private_key);
|
|
~Scanner();
|
|
|
|
// Scans one token at a time.
|
|
void Scan();
|
|
|
|
// Scans the entire source and collects tokens in the provided collector.
|
|
void ScanAll(TokenCollector* collector);
|
|
|
|
// Scans to specified token position.
|
|
// Use CurrentPosition() to extract line and column number.
|
|
void ScanTo(intptr_t token_index);
|
|
|
|
// Info about most recently recognized token.
|
|
const TokenDescriptor& current_token() const { return current_token_; }
|
|
|
|
// Was there a line break before the current token?
|
|
bool NewlineBeforeToken() const { return newline_seen_; }
|
|
|
|
// Source code line number and column of current token.
|
|
const SourcePosition& CurrentPosition() const {
|
|
return current_token_.position;
|
|
}
|
|
|
|
static void InitOnce();
|
|
|
|
// Return true if str is an identifier.
|
|
bool IsIdent(const String& str);
|
|
|
|
// Does the token stream contain a valid integer literal.
|
|
static bool IsValidInteger(const String& str,
|
|
bool* is_positive,
|
|
const String** value);
|
|
|
|
static bool IsIdentStartChar(int32_t c);
|
|
static bool IsIdentChar(int32_t c);
|
|
|
|
private:
|
|
friend class ScanContext;
|
|
|
|
static const int kNumLowercaseChars = 26;
|
|
|
|
struct KeywordTable {
|
|
Token::Kind kind;
|
|
const char* keyword_chars;
|
|
int keyword_len;
|
|
const String* keyword_symbol;
|
|
};
|
|
|
|
// Rewind scanner position to token 0.
|
|
void Reset();
|
|
|
|
// Reads next lookahead character.
|
|
void ReadChar();
|
|
|
|
// Read and discard characters up to end of line.
|
|
void SkipLine();
|
|
|
|
// Recognizes token 'kind' and reads next character in input.
|
|
void Recognize(Token::Kind kind) {
|
|
ReadChar();
|
|
current_token_.kind = kind;
|
|
}
|
|
|
|
int32_t LookaheadChar(int how_many);
|
|
|
|
void ErrorMsg(const char* msg);
|
|
|
|
// These functions return true if the given character is a letter,
|
|
// a decimal digit, a hexadecimal digit, etc.
|
|
static bool IsLetter(int32_t c);
|
|
static bool IsDecimalDigit(int32_t c);
|
|
static bool IsNumberStart(int32_t);
|
|
static bool IsHexDigit(int32_t c);
|
|
|
|
// Skips up to next non-whitespace character.
|
|
void ConsumeWhiteSpace();
|
|
|
|
// Skips characters up to end of line.
|
|
void ConsumeLineComment();
|
|
|
|
// Skips characters up to matching '*/'.
|
|
void ConsumeBlockComment();
|
|
|
|
// Is this scanner currently scanning a string literal.
|
|
bool IsScanningString() const { return string_delimiter_ != '\0'; }
|
|
void BeginStringLiteral(const char delimiter);
|
|
void EndStringLiteral();
|
|
|
|
// Is this scanner currently scanning a string interpolation expression.
|
|
bool IsNestedContext() const { return saved_context_ != NULL; }
|
|
void PushContext();
|
|
void PopContext();
|
|
|
|
// Starts reading a string literal.
|
|
void ScanLiteralString(bool is_raw);
|
|
|
|
// Read the characters of a string literal. Remove whitespace up to
|
|
// and including the first newline character if remove_whitespace
|
|
// is true.
|
|
void ScanLiteralStringChars(bool is_raw, bool remove_whitespace);
|
|
|
|
// Reads a fixed number of hexadecimal digits.
|
|
bool ScanHexDigits(int digits, int32_t* value);
|
|
|
|
// Reads a variable number of hexadecimal digits.
|
|
bool ScanHexDigits(int min_digits, int max_digits, int32_t* value);
|
|
|
|
// Reads an escaped code point from within a string literal.
|
|
void ScanEscapedCodePoint(int32_t* escaped_char);
|
|
|
|
// Reads identifier.
|
|
void ScanIdentChars(bool allow_dollar);
|
|
void ScanIdent() { ScanIdentChars(true); }
|
|
void ScanIdentNoDollar() { ScanIdentChars(false); }
|
|
|
|
// Reads a number literal.
|
|
void ScanNumber(bool dec_point_seen);
|
|
|
|
void ScanScriptTag();
|
|
|
|
CharAtFunc CallCharAt() const { return char_at_func_; }
|
|
|
|
Thread* thread() const { return thread_; }
|
|
Zone* zone() const { return zone_; }
|
|
|
|
TokenDescriptor current_token_; // Current token.
|
|
TokenDescriptor newline_token_; // Newline token.
|
|
TokenDescriptor empty_string_token_; // Token for "".
|
|
const String& source_; // The source text being tokenized.
|
|
intptr_t source_length_; // The length of the source text.
|
|
intptr_t lookahead_pos_; // Position of lookahead character
|
|
// within source_.
|
|
intptr_t token_start_; // Begin of current token in src_.
|
|
int32_t c0_; // Lookahead character.
|
|
bool newline_seen_; // Newline before current token.
|
|
intptr_t prev_token_line_; // Line number of the previous token.
|
|
|
|
// The following fields keep track whether we are scanning a string literal
|
|
// and its interpolated expressions.
|
|
ScanContext* saved_context_;
|
|
int32_t string_delimiter_;
|
|
bool string_is_multiline_;
|
|
int brace_level_;
|
|
|
|
const String& private_key_;
|
|
|
|
SourcePosition c0_pos_; // Source position of lookahead character c0_.
|
|
|
|
const CharAtFunc char_at_func_;
|
|
|
|
Thread* thread_;
|
|
Zone* zone_;
|
|
|
|
static KeywordTable keywords_[Token::kNumKeywords];
|
|
static int keywords_char_offset_[kNumLowercaseChars];
|
|
};
|
|
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_VM_SCANNER_H_
|