blob: 30bc81eb3aadaf0c440d92ad3b35427bc5114b90 [file] [log] [blame]
// 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 VM_SCANNER_H_
#define 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);
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);
static bool IsIdentStartChar(int32_t c);
static bool IsIdentChar(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 // VM_SCANNER_H_