Move part of scanner.* into scanner-base.* for reuse in preparser scanner.
Make checks.h not depend on flags.h or global.h (or anything else except include/v8stdint.h). Only checks.cc has the dependencies (so another implementation of checks.cc can be provided by the preparser). Now files depending on checks.h (using ASSERT macros) can include it directly without depending on all of v8. Review URL: http://codereview.chromium.org/4576001 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5775 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
8838fdea66
commit
f386f97476
@ -95,6 +95,7 @@ SOURCES = {
|
||||
register-allocator.cc
|
||||
rewriter.cc
|
||||
runtime.cc
|
||||
scanner-base.cc
|
||||
scanner.cc
|
||||
scopeinfo.cc
|
||||
scopes.cc
|
||||
|
@ -98,3 +98,12 @@ void API_Fatal(const char* location, const char* format, ...) {
|
||||
i::OS::PrintError("\n#\n\n");
|
||||
i::OS::Abort();
|
||||
}
|
||||
|
||||
|
||||
namespace v8 { namespace internal {
|
||||
|
||||
bool EnableSlowAsserts() { return FLAG_enable_slow_asserts; }
|
||||
|
||||
intptr_t HeapObjectTagMask() { return kHeapObjectTagMask; }
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
19
src/checks.h
19
src/checks.h
@ -30,7 +30,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "flags.h"
|
||||
#include "../include/v8stdint.h"
|
||||
|
||||
extern "C" void V8_Fatal(const char* file, int line, const char* format, ...);
|
||||
void API_Fatal(const char* location, const char* format, ...);
|
||||
@ -279,6 +279,12 @@ template <int> class StaticAssertionHelper { };
|
||||
SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__)
|
||||
|
||||
|
||||
namespace v8 { namespace internal {
|
||||
|
||||
bool EnableSlowAsserts();
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
||||
// The ASSERT macro is equivalent to CHECK except that it only
|
||||
// generates code in debug builds.
|
||||
#ifdef DEBUG
|
||||
@ -287,7 +293,7 @@ template <int> class StaticAssertionHelper { };
|
||||
#define ASSERT_EQ(v1, v2) CHECK_EQ(v1, v2)
|
||||
#define ASSERT_NE(v1, v2) CHECK_NE(v1, v2)
|
||||
#define ASSERT_GE(v1, v2) CHECK_GE(v1, v2)
|
||||
#define SLOW_ASSERT(condition) if (FLAG_enable_slow_asserts) CHECK(condition)
|
||||
#define SLOW_ASSERT(condition) if (EnableSlowAsserts()) CHECK(condition)
|
||||
#else
|
||||
#define ASSERT_RESULT(expr) (expr)
|
||||
#define ASSERT(condition) ((void) 0)
|
||||
@ -303,11 +309,16 @@ template <int> class StaticAssertionHelper { };
|
||||
// and release compilation modes behaviour.
|
||||
#define STATIC_ASSERT(test) STATIC_CHECK(test)
|
||||
|
||||
namespace v8 { namespace internal {
|
||||
|
||||
intptr_t HeapObjectTagMask();
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
||||
#define ASSERT_TAG_ALIGNED(address) \
|
||||
ASSERT((reinterpret_cast<intptr_t>(address) & kHeapObjectTagMask) == 0)
|
||||
ASSERT((reinterpret_cast<intptr_t>(address) & HeapObjectTagMask()) == 0)
|
||||
|
||||
#define ASSERT_SIZE_TAG_ALIGNED(size) ASSERT((size & kHeapObjectTagMask) == 0)
|
||||
#define ASSERT_SIZE_TAG_ALIGNED(size) ASSERT((size & HeapObjectTagMask()) == 0)
|
||||
|
||||
#define ASSERT_NOT_NULL(p) ASSERT_NE(NULL, p)
|
||||
|
||||
|
447
src/preparser.h
447
src/preparser.h
File diff suppressed because it is too large
Load Diff
167
src/scanner-base.cc
Normal file
167
src/scanner-base.cc
Normal file
@ -0,0 +1,167 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Features shared by parsing and pre-parsing scanners.
|
||||
|
||||
#include "scanner-base.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Keyword Matcher
|
||||
|
||||
KeywordMatcher::FirstState KeywordMatcher::first_states_[] = {
|
||||
{ "break", KEYWORD_PREFIX, Token::BREAK },
|
||||
{ NULL, C, Token::ILLEGAL },
|
||||
{ NULL, D, Token::ILLEGAL },
|
||||
{ "else", KEYWORD_PREFIX, Token::ELSE },
|
||||
{ NULL, F, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, I, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, N, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ "return", KEYWORD_PREFIX, Token::RETURN },
|
||||
{ "switch", KEYWORD_PREFIX, Token::SWITCH },
|
||||
{ NULL, T, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, V, Token::ILLEGAL },
|
||||
{ NULL, W, Token::ILLEGAL }
|
||||
};
|
||||
|
||||
|
||||
void KeywordMatcher::Step(unibrow::uchar input) {
|
||||
switch (state_) {
|
||||
case INITIAL: {
|
||||
// matching the first character is the only state with significant fanout.
|
||||
// Match only lower-case letters in range 'b'..'w'.
|
||||
unsigned int offset = input - kFirstCharRangeMin;
|
||||
if (offset < kFirstCharRangeLength) {
|
||||
state_ = first_states_[offset].state;
|
||||
if (state_ == KEYWORD_PREFIX) {
|
||||
keyword_ = first_states_[offset].keyword;
|
||||
counter_ = 1;
|
||||
keyword_token_ = first_states_[offset].token;
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KEYWORD_PREFIX:
|
||||
if (static_cast<unibrow::uchar>(keyword_[counter_]) == input) {
|
||||
counter_++;
|
||||
if (keyword_[counter_] == '\0') {
|
||||
state_ = KEYWORD_MATCHED;
|
||||
token_ = keyword_token_;
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case KEYWORD_MATCHED:
|
||||
token_ = Token::IDENTIFIER;
|
||||
break;
|
||||
case C:
|
||||
if (MatchState(input, 'a', CA)) return;
|
||||
if (MatchState(input, 'o', CO)) return;
|
||||
break;
|
||||
case CA:
|
||||
if (MatchKeywordStart(input, "case", 2, Token::CASE)) return;
|
||||
if (MatchKeywordStart(input, "catch", 2, Token::CATCH)) return;
|
||||
break;
|
||||
case CO:
|
||||
if (MatchState(input, 'n', CON)) return;
|
||||
break;
|
||||
case CON:
|
||||
if (MatchKeywordStart(input, "const", 3, Token::CONST)) return;
|
||||
if (MatchKeywordStart(input, "continue", 3, Token::CONTINUE)) return;
|
||||
break;
|
||||
case D:
|
||||
if (MatchState(input, 'e', DE)) return;
|
||||
if (MatchKeyword(input, 'o', KEYWORD_MATCHED, Token::DO)) return;
|
||||
break;
|
||||
case DE:
|
||||
if (MatchKeywordStart(input, "debugger", 2, Token::DEBUGGER)) return;
|
||||
if (MatchKeywordStart(input, "default", 2, Token::DEFAULT)) return;
|
||||
if (MatchKeywordStart(input, "delete", 2, Token::DELETE)) return;
|
||||
break;
|
||||
case F:
|
||||
if (MatchKeywordStart(input, "false", 1, Token::FALSE_LITERAL)) return;
|
||||
if (MatchKeywordStart(input, "finally", 1, Token::FINALLY)) return;
|
||||
if (MatchKeywordStart(input, "for", 1, Token::FOR)) return;
|
||||
if (MatchKeywordStart(input, "function", 1, Token::FUNCTION)) return;
|
||||
break;
|
||||
case I:
|
||||
if (MatchKeyword(input, 'f', KEYWORD_MATCHED, Token::IF)) return;
|
||||
if (MatchKeyword(input, 'n', IN, Token::IN)) return;
|
||||
break;
|
||||
case IN:
|
||||
token_ = Token::IDENTIFIER;
|
||||
if (MatchKeywordStart(input, "instanceof", 2, Token::INSTANCEOF)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case N:
|
||||
if (MatchKeywordStart(input, "native", 1, Token::NATIVE)) return;
|
||||
if (MatchKeywordStart(input, "new", 1, Token::NEW)) return;
|
||||
if (MatchKeywordStart(input, "null", 1, Token::NULL_LITERAL)) return;
|
||||
break;
|
||||
case T:
|
||||
if (MatchState(input, 'h', TH)) return;
|
||||
if (MatchState(input, 'r', TR)) return;
|
||||
if (MatchKeywordStart(input, "typeof", 1, Token::TYPEOF)) return;
|
||||
break;
|
||||
case TH:
|
||||
if (MatchKeywordStart(input, "this", 2, Token::THIS)) return;
|
||||
if (MatchKeywordStart(input, "throw", 2, Token::THROW)) return;
|
||||
break;
|
||||
case TR:
|
||||
if (MatchKeywordStart(input, "true", 2, Token::TRUE_LITERAL)) return;
|
||||
if (MatchKeyword(input, 'y', KEYWORD_MATCHED, Token::TRY)) return;
|
||||
break;
|
||||
case V:
|
||||
if (MatchKeywordStart(input, "var", 1, Token::VAR)) return;
|
||||
if (MatchKeywordStart(input, "void", 1, Token::VOID)) return;
|
||||
break;
|
||||
case W:
|
||||
if (MatchKeywordStart(input, "while", 1, Token::WHILE)) return;
|
||||
if (MatchKeywordStart(input, "with", 1, Token::WITH)) return;
|
||||
break;
|
||||
case UNMATCHABLE:
|
||||
break;
|
||||
}
|
||||
// On fallthrough, it's a failure.
|
||||
state_ = UNMATCHABLE;
|
||||
}
|
||||
|
||||
} } // namespace v8::internal
|
165
src/scanner-base.h
Normal file
165
src/scanner-base.h
Normal file
@ -0,0 +1,165 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Features shared by parsing and pre-parsing scanners.
|
||||
|
||||
#ifndef V8_SCANNER_BASE_H_
|
||||
#define V8_SCANNER_BASE_H_
|
||||
|
||||
#include "token.h"
|
||||
#include "unicode.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class KeywordMatcher {
|
||||
// Incrementally recognize keywords.
|
||||
//
|
||||
// Recognized keywords:
|
||||
// break case catch const* continue debugger* default delete do else
|
||||
// finally false for function if in instanceof native* new null
|
||||
// return switch this throw true try typeof var void while with
|
||||
//
|
||||
// *: Actually "future reserved keywords". These are the only ones we
|
||||
// recognized, the remaining are allowed as identifiers.
|
||||
public:
|
||||
KeywordMatcher()
|
||||
: state_(INITIAL),
|
||||
token_(Token::IDENTIFIER),
|
||||
keyword_(NULL),
|
||||
counter_(0),
|
||||
keyword_token_(Token::ILLEGAL) {}
|
||||
|
||||
Token::Value token() { return token_; }
|
||||
|
||||
inline void AddChar(unibrow::uchar input) {
|
||||
if (state_ != UNMATCHABLE) {
|
||||
Step(input);
|
||||
}
|
||||
}
|
||||
|
||||
void Fail() {
|
||||
token_ = Token::IDENTIFIER;
|
||||
state_ = UNMATCHABLE;
|
||||
}
|
||||
|
||||
private:
|
||||
enum State {
|
||||
UNMATCHABLE,
|
||||
INITIAL,
|
||||
KEYWORD_PREFIX,
|
||||
KEYWORD_MATCHED,
|
||||
C,
|
||||
CA,
|
||||
CO,
|
||||
CON,
|
||||
D,
|
||||
DE,
|
||||
F,
|
||||
I,
|
||||
IN,
|
||||
N,
|
||||
T,
|
||||
TH,
|
||||
TR,
|
||||
V,
|
||||
W
|
||||
};
|
||||
|
||||
struct FirstState {
|
||||
const char* keyword;
|
||||
State state;
|
||||
Token::Value token;
|
||||
};
|
||||
|
||||
// Range of possible first characters of a keyword.
|
||||
static const unsigned int kFirstCharRangeMin = 'b';
|
||||
static const unsigned int kFirstCharRangeMax = 'w';
|
||||
static const unsigned int kFirstCharRangeLength =
|
||||
kFirstCharRangeMax - kFirstCharRangeMin + 1;
|
||||
// State map for first keyword character range.
|
||||
static FirstState first_states_[kFirstCharRangeLength];
|
||||
|
||||
// If input equals keyword's character at position, continue matching keyword
|
||||
// from that position.
|
||||
inline bool MatchKeywordStart(unibrow::uchar input,
|
||||
const char* keyword,
|
||||
int position,
|
||||
Token::Value token_if_match) {
|
||||
if (input == static_cast<unibrow::uchar>(keyword[position])) {
|
||||
state_ = KEYWORD_PREFIX;
|
||||
this->keyword_ = keyword;
|
||||
this->counter_ = position + 1;
|
||||
this->keyword_token_ = token_if_match;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// If input equals match character, transition to new state and return true.
|
||||
inline bool MatchState(unibrow::uchar input, char match, State new_state) {
|
||||
if (input == static_cast<unibrow::uchar>(match)) {
|
||||
state_ = new_state;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool MatchKeyword(unibrow::uchar input,
|
||||
char match,
|
||||
State new_state,
|
||||
Token::Value keyword_token) {
|
||||
if (input != static_cast<unibrow::uchar>(match)) {
|
||||
return false;
|
||||
}
|
||||
state_ = new_state;
|
||||
token_ = keyword_token;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Step(unibrow::uchar input);
|
||||
|
||||
// Current state.
|
||||
State state_;
|
||||
// Token for currently added characters.
|
||||
Token::Value token_;
|
||||
|
||||
// Matching a specific keyword string (there is only one possible valid
|
||||
// keyword with the current prefix).
|
||||
const char* keyword_;
|
||||
int counter_;
|
||||
Token::Value keyword_token_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
||||
#endif // V8_SCANNER_BASE_H_
|
136
src/scanner.cc
136
src/scanner.cc
@ -184,142 +184,6 @@ void ExternalStringUTF16Buffer<StringType, CharType>::SeekForward(int pos) {
|
||||
pos_ = pos;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Keyword Matcher
|
||||
|
||||
KeywordMatcher::FirstState KeywordMatcher::first_states_[] = {
|
||||
{ "break", KEYWORD_PREFIX, Token::BREAK },
|
||||
{ NULL, C, Token::ILLEGAL },
|
||||
{ NULL, D, Token::ILLEGAL },
|
||||
{ "else", KEYWORD_PREFIX, Token::ELSE },
|
||||
{ NULL, F, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, I, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, N, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ "return", KEYWORD_PREFIX, Token::RETURN },
|
||||
{ "switch", KEYWORD_PREFIX, Token::SWITCH },
|
||||
{ NULL, T, Token::ILLEGAL },
|
||||
{ NULL, UNMATCHABLE, Token::ILLEGAL },
|
||||
{ NULL, V, Token::ILLEGAL },
|
||||
{ NULL, W, Token::ILLEGAL }
|
||||
};
|
||||
|
||||
|
||||
void KeywordMatcher::Step(uc32 input) {
|
||||
switch (state_) {
|
||||
case INITIAL: {
|
||||
// matching the first character is the only state with significant fanout.
|
||||
// Match only lower-case letters in range 'b'..'w'.
|
||||
unsigned int offset = input - kFirstCharRangeMin;
|
||||
if (offset < kFirstCharRangeLength) {
|
||||
state_ = first_states_[offset].state;
|
||||
if (state_ == KEYWORD_PREFIX) {
|
||||
keyword_ = first_states_[offset].keyword;
|
||||
counter_ = 1;
|
||||
keyword_token_ = first_states_[offset].token;
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KEYWORD_PREFIX:
|
||||
if (keyword_[counter_] == input) {
|
||||
ASSERT_NE(input, '\0');
|
||||
counter_++;
|
||||
if (keyword_[counter_] == '\0') {
|
||||
state_ = KEYWORD_MATCHED;
|
||||
token_ = keyword_token_;
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case KEYWORD_MATCHED:
|
||||
token_ = Token::IDENTIFIER;
|
||||
break;
|
||||
case C:
|
||||
if (MatchState(input, 'a', CA)) return;
|
||||
if (MatchState(input, 'o', CO)) return;
|
||||
break;
|
||||
case CA:
|
||||
if (MatchKeywordStart(input, "case", 2, Token::CASE)) return;
|
||||
if (MatchKeywordStart(input, "catch", 2, Token::CATCH)) return;
|
||||
break;
|
||||
case CO:
|
||||
if (MatchState(input, 'n', CON)) return;
|
||||
break;
|
||||
case CON:
|
||||
if (MatchKeywordStart(input, "const", 3, Token::CONST)) return;
|
||||
if (MatchKeywordStart(input, "continue", 3, Token::CONTINUE)) return;
|
||||
break;
|
||||
case D:
|
||||
if (MatchState(input, 'e', DE)) return;
|
||||
if (MatchKeyword(input, 'o', KEYWORD_MATCHED, Token::DO)) return;
|
||||
break;
|
||||
case DE:
|
||||
if (MatchKeywordStart(input, "debugger", 2, Token::DEBUGGER)) return;
|
||||
if (MatchKeywordStart(input, "default", 2, Token::DEFAULT)) return;
|
||||
if (MatchKeywordStart(input, "delete", 2, Token::DELETE)) return;
|
||||
break;
|
||||
case F:
|
||||
if (MatchKeywordStart(input, "false", 1, Token::FALSE_LITERAL)) return;
|
||||
if (MatchKeywordStart(input, "finally", 1, Token::FINALLY)) return;
|
||||
if (MatchKeywordStart(input, "for", 1, Token::FOR)) return;
|
||||
if (MatchKeywordStart(input, "function", 1, Token::FUNCTION)) return;
|
||||
break;
|
||||
case I:
|
||||
if (MatchKeyword(input, 'f', KEYWORD_MATCHED, Token::IF)) return;
|
||||
if (MatchKeyword(input, 'n', IN, Token::IN)) return;
|
||||
break;
|
||||
case IN:
|
||||
token_ = Token::IDENTIFIER;
|
||||
if (MatchKeywordStart(input, "instanceof", 2, Token::INSTANCEOF)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case N:
|
||||
if (MatchKeywordStart(input, "native", 1, Token::NATIVE)) return;
|
||||
if (MatchKeywordStart(input, "new", 1, Token::NEW)) return;
|
||||
if (MatchKeywordStart(input, "null", 1, Token::NULL_LITERAL)) return;
|
||||
break;
|
||||
case T:
|
||||
if (MatchState(input, 'h', TH)) return;
|
||||
if (MatchState(input, 'r', TR)) return;
|
||||
if (MatchKeywordStart(input, "typeof", 1, Token::TYPEOF)) return;
|
||||
break;
|
||||
case TH:
|
||||
if (MatchKeywordStart(input, "this", 2, Token::THIS)) return;
|
||||
if (MatchKeywordStart(input, "throw", 2, Token::THROW)) return;
|
||||
break;
|
||||
case TR:
|
||||
if (MatchKeywordStart(input, "true", 2, Token::TRUE_LITERAL)) return;
|
||||
if (MatchKeyword(input, 'y', KEYWORD_MATCHED, Token::TRY)) return;
|
||||
break;
|
||||
case V:
|
||||
if (MatchKeywordStart(input, "var", 1, Token::VAR)) return;
|
||||
if (MatchKeywordStart(input, "void", 1, Token::VOID)) return;
|
||||
break;
|
||||
case W:
|
||||
if (MatchKeywordStart(input, "while", 1, Token::WHILE)) return;
|
||||
if (MatchKeywordStart(input, "with", 1, Token::WITH)) return;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
// On fallthrough, it's a failure.
|
||||
state_ = UNMATCHABLE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Scanner::LiteralScope
|
||||
|
||||
|
121
src/scanner.h
121
src/scanner.h
@ -30,6 +30,7 @@
|
||||
|
||||
#include "token.h"
|
||||
#include "char-predicates-inl.h"
|
||||
#include "scanner-base.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -142,126 +143,6 @@ class ExternalStringUTF16Buffer: public UTF16Buffer {
|
||||
};
|
||||
|
||||
|
||||
class KeywordMatcher {
|
||||
// Incrementally recognize keywords.
|
||||
//
|
||||
// Recognized keywords:
|
||||
// break case catch const* continue debugger* default delete do else
|
||||
// finally false for function if in instanceof native* new null
|
||||
// return switch this throw true try typeof var void while with
|
||||
//
|
||||
// *: Actually "future reserved keywords". These are the only ones we
|
||||
// recognized, the remaining are allowed as identifiers.
|
||||
public:
|
||||
KeywordMatcher()
|
||||
: state_(INITIAL),
|
||||
token_(Token::IDENTIFIER),
|
||||
keyword_(NULL),
|
||||
counter_(0),
|
||||
keyword_token_(Token::ILLEGAL) {}
|
||||
|
||||
Token::Value token() { return token_; }
|
||||
|
||||
inline void AddChar(uc32 input) {
|
||||
if (state_ != UNMATCHABLE) {
|
||||
Step(input);
|
||||
}
|
||||
}
|
||||
|
||||
void Fail() {
|
||||
token_ = Token::IDENTIFIER;
|
||||
state_ = UNMATCHABLE;
|
||||
}
|
||||
|
||||
private:
|
||||
enum State {
|
||||
UNMATCHABLE,
|
||||
INITIAL,
|
||||
KEYWORD_PREFIX,
|
||||
KEYWORD_MATCHED,
|
||||
C,
|
||||
CA,
|
||||
CO,
|
||||
CON,
|
||||
D,
|
||||
DE,
|
||||
F,
|
||||
I,
|
||||
IN,
|
||||
N,
|
||||
T,
|
||||
TH,
|
||||
TR,
|
||||
V,
|
||||
W
|
||||
};
|
||||
|
||||
struct FirstState {
|
||||
const char* keyword;
|
||||
State state;
|
||||
Token::Value token;
|
||||
};
|
||||
|
||||
// Range of possible first characters of a keyword.
|
||||
static const unsigned int kFirstCharRangeMin = 'b';
|
||||
static const unsigned int kFirstCharRangeMax = 'w';
|
||||
static const unsigned int kFirstCharRangeLength =
|
||||
kFirstCharRangeMax - kFirstCharRangeMin + 1;
|
||||
// State map for first keyword character range.
|
||||
static FirstState first_states_[kFirstCharRangeLength];
|
||||
|
||||
// If input equals keyword's character at position, continue matching keyword
|
||||
// from that position.
|
||||
inline bool MatchKeywordStart(uc32 input,
|
||||
const char* keyword,
|
||||
int position,
|
||||
Token::Value token_if_match) {
|
||||
if (input == keyword[position]) {
|
||||
state_ = KEYWORD_PREFIX;
|
||||
this->keyword_ = keyword;
|
||||
this->counter_ = position + 1;
|
||||
this->keyword_token_ = token_if_match;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// If input equals match character, transition to new state and return true.
|
||||
inline bool MatchState(uc32 input, char match, State new_state) {
|
||||
if (input == match) {
|
||||
state_ = new_state;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool MatchKeyword(uc32 input,
|
||||
char match,
|
||||
State new_state,
|
||||
Token::Value keyword_token) {
|
||||
if (input != match) {
|
||||
return false;
|
||||
}
|
||||
state_ = new_state;
|
||||
token_ = keyword_token;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Step(uc32 input);
|
||||
|
||||
// Current state.
|
||||
State state_;
|
||||
// Token for currently added characters.
|
||||
Token::Value token_;
|
||||
|
||||
// Matching a specific keyword string (there is only one possible valid
|
||||
// keyword with the current prefix).
|
||||
const char* keyword_;
|
||||
int counter_;
|
||||
Token::Value keyword_token_;
|
||||
};
|
||||
|
||||
|
||||
enum ParserLanguage { JAVASCRIPT, JSON };
|
||||
|
||||
|
||||
|
@ -28,6 +28,8 @@
|
||||
#ifndef V8_TOKEN_H_
|
||||
#define V8_TOKEN_H_
|
||||
|
||||
#include "checks.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
|
@ -263,7 +263,7 @@ TEST(StandAlonePreParser) {
|
||||
i::CompleteParserRecorder log;
|
||||
i::Scanner scanner;
|
||||
scanner.Initialize(i::Handle<i::String>::null(), &stream, i::JAVASCRIPT);
|
||||
i::preparser::PreParser<i::Scanner, i::CompleteParserRecorder> preparser;
|
||||
v8::preparser::PreParser<i::Scanner, i::CompleteParserRecorder> preparser;
|
||||
bool result = preparser.PreParseProgram(&scanner, &log, true);
|
||||
CHECK(result);
|
||||
i::ScriptDataImpl data(log.ExtractData());
|
||||
|
@ -426,6 +426,8 @@
|
||||
'../../src/rewriter.h',
|
||||
'../../src/runtime.cc',
|
||||
'../../src/runtime.h',
|
||||
'../../src/scanner-base.cc',
|
||||
'../../src/scanner-base.h',
|
||||
'../../src/scanner.cc',
|
||||
'../../src/scanner.h',
|
||||
'../../src/scopeinfo.cc',
|
||||
|
@ -115,6 +115,7 @@
|
||||
89A88E180E71A6960043BA31 /* property.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF16D0E719B8F00D62E90 /* property.cc */; };
|
||||
89A88E190E71A6970043BA31 /* rewriter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF16F0E719B8F00D62E90 /* rewriter.cc */; };
|
||||
89A88E1A0E71A69B0043BA31 /* runtime.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1710E719B8F00D62E90 /* runtime.cc */; };
|
||||
89A88E1B0E71A69D0043BA31 /* scanner-base.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1730E719B8F00D62E90 /* scanner-base.cc */; };
|
||||
89A88E1B0E71A69D0043BA31 /* scanner.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1730E719B8F00D62E90 /* scanner.cc */; };
|
||||
89A88E1C0E71A69E0043BA31 /* scopeinfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1760E719B8F00D62E90 /* scopeinfo.cc */; };
|
||||
89A88E1D0E71A6A00043BA31 /* scopes.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1780E719B8F00D62E90 /* scopes.cc */; };
|
||||
@ -177,6 +178,7 @@
|
||||
89F23C6C0E78D5B2006B2466 /* property.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF16D0E719B8F00D62E90 /* property.cc */; };
|
||||
89F23C6D0E78D5B2006B2466 /* rewriter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF16F0E719B8F00D62E90 /* rewriter.cc */; };
|
||||
89F23C6E0E78D5B2006B2466 /* runtime.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1710E719B8F00D62E90 /* runtime.cc */; };
|
||||
89F23C6F0E78D5B2006B2466 /* scanner-base.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1730E719B8F00D62E90 /* scanner-base.cc */; };
|
||||
89F23C6F0E78D5B2006B2466 /* scanner.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1730E719B8F00D62E90 /* scanner.cc */; };
|
||||
89F23C700E78D5B2006B2466 /* scopeinfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1760E719B8F00D62E90 /* scopeinfo.cc */; };
|
||||
89F23C710E78D5B2006B2466 /* scopes.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1780E719B8F00D62E90 /* scopes.cc */; };
|
||||
@ -481,6 +483,8 @@
|
||||
897FF1700E719B8F00D62E90 /* rewriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rewriter.h; sourceTree = "<group>"; };
|
||||
897FF1710E719B8F00D62E90 /* runtime.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = runtime.cc; sourceTree = "<group>"; };
|
||||
897FF1720E719B8F00D62E90 /* runtime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = runtime.h; sourceTree = "<group>"; };
|
||||
897FF1730E719B8F00D62E90 /* scanner-base.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scanner-base.cc; sourceTree = "<group>"; };
|
||||
897FF1740E719B8F00D62E90 /* scanner-base.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scanner-base.h; sourceTree = "<group>"; };
|
||||
897FF1730E719B8F00D62E90 /* scanner.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scanner.cc; sourceTree = "<group>"; };
|
||||
897FF1740E719B8F00D62E90 /* scanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scanner.h; sourceTree = "<group>"; };
|
||||
897FF1750E719B8F00D62E90 /* SConscript */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SConscript; sourceTree = "<group>"; };
|
||||
@ -943,6 +947,8 @@
|
||||
897FF1700E719B8F00D62E90 /* rewriter.h */,
|
||||
897FF1710E719B8F00D62E90 /* runtime.cc */,
|
||||
897FF1720E719B8F00D62E90 /* runtime.h */,
|
||||
897FF1730E719B8F00D62E90 /* scanner-base.cc */,
|
||||
897FF1740E719B8F00D62E90 /* scanner-base.h */,
|
||||
897FF1730E719B8F00D62E90 /* scanner.cc */,
|
||||
897FF1740E719B8F00D62E90 /* scanner.h */,
|
||||
897FF1760E719B8F00D62E90 /* scopeinfo.cc */,
|
||||
@ -1348,6 +1354,7 @@
|
||||
58950D630F5551AF00F3E8BA /* register-allocator.cc in Sources */,
|
||||
89A88E190E71A6970043BA31 /* rewriter.cc in Sources */,
|
||||
89A88E1A0E71A69B0043BA31 /* runtime.cc in Sources */,
|
||||
89A88E1B0E71A69D0043BA31 /* scanner-base.cc in Sources */,
|
||||
89A88E1B0E71A69D0043BA31 /* scanner.cc in Sources */,
|
||||
89A88E1C0E71A69E0043BA31 /* scopeinfo.cc in Sources */,
|
||||
89A88E1D0E71A6A00043BA31 /* scopes.cc in Sources */,
|
||||
@ -1472,6 +1479,7 @@
|
||||
58950D640F5551B500F3E8BA /* register-allocator.cc in Sources */,
|
||||
89F23C6D0E78D5B2006B2466 /* rewriter.cc in Sources */,
|
||||
89F23C6E0E78D5B2006B2466 /* runtime.cc in Sources */,
|
||||
89F23C6F0E78D5B2006B2466 /* scanner-base.cc in Sources */,
|
||||
89F23C6F0E78D5B2006B2466 /* scanner.cc in Sources */,
|
||||
89F23C700E78D5B2006B2466 /* scopeinfo.cc in Sources */,
|
||||
89F23C710E78D5B2006B2466 /* scopes.cc in Sources */,
|
||||
|
@ -881,6 +881,14 @@
|
||||
RelativePath="..\..\src\runtime.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\scanner-base.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\scanner-base.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\scanner.cc"
|
||||
>
|
||||
|
Loading…
Reference in New Issue
Block a user