MasterLexerImpl() : source_(NULL), token_(Token::NOT_STARTED),
paren_count_(0), last_was_eol_(false),
has_previous_(false),
- previous_token_(Token::NOT_STARTED),
previous_paren_count_(0),
previous_was_eol_(false)
{
// These are to allow restoring state before previous token.
bool has_previous_;
- Token previous_token_;
size_t previous_paren_count_;
bool previous_was_eol_;
};
impl_->has_previous_ = false;
// If thrown in this section, nothing observable except for not having
// previous will happen.
- impl_->previous_token_ = impl_->token_;
impl_->previous_paren_count_ = impl_->paren_count_;
impl_->previous_was_eol_ = impl_->last_was_eol_;
impl_->source_->mark();
void
MasterLexer::ungetToken() {
if (impl_->has_previous_) {
- // The one that could fail due to bad_alloc first
- impl_->token_ = impl_->previous_token_;
- // The rest should not throw.
impl_->has_previous_ = false;
impl_->source_->ungetAll();
impl_->last_was_eol_ = impl_->previous_was_eol_;
/// by this parameter. Multiple options can be passed at once by
/// bitwise or (eg. option1 | option 2). See description of available
/// options.
- /// \return Next token found in the input.
+ /// \return Next token found in the input. Note that the token refers to
+ /// some internal data in in the lexer. It is valid only until
+ /// getNextToken or ungetToken is called. Also, the token becomes
+ /// invalid when the lexer is destroyed.
/// \throw isc::InvalidOperation in case the source is not available. This
/// may mean the pushSource() has not been called yet, or that the
/// current source has been read past the end.
// We access the lexer through any state, so use the one we have.
EXPECT_EQ(1, state->getParenCount(lexer));
EXPECT_TRUE(state->wasLastEOL(lexer));
- EXPECT_EQ(MasterLexer::Token::INITIAL_WS,
- state->getToken(lexer).getType());
// Now get the token and check the state changed
EXPECT_EQ(MasterLexer::Token::END_OF_LINE, lexer.getNextToken().getType());
EXPECT_EQ(2, state->getParenCount(lexer));
EXPECT_FALSE(state->wasLastEOL(lexer));
- EXPECT_EQ(MasterLexer::Token::END_OF_LINE,
- state->getToken(lexer).getType());
// Return the token back. Check the state is as it was before.
lexer.ungetToken();
EXPECT_EQ(1, state->getParenCount(lexer));
EXPECT_TRUE(state->wasLastEOL(lexer));
- EXPECT_EQ(MasterLexer::Token::INITIAL_WS,
- state->getToken(lexer).getType());
// By calling getToken again, we verify even the source got back to
// original. We must push it as a fake start again so it is picked.
lexer.pushFakeStart(state.get());
EXPECT_EQ(MasterLexer::Token::END_OF_LINE, lexer.getNextToken().getType());
EXPECT_EQ(2, state->getParenCount(lexer));
EXPECT_FALSE(state->wasLastEOL(lexer));
- EXPECT_EQ(MasterLexer::Token::END_OF_LINE,
- state->getToken(lexer).getType());
}
// Check ungetting token without overriding the start method. We also
EXPECT_THROW(lexer.getNextToken(), TestException);
EXPECT_EQ(0, s1->getParenCount(lexer));
EXPECT_FALSE(s1->wasLastEOL(lexer));
- EXPECT_EQ(MasterLexer::Token::NOT_STARTED,
- s1->getToken(lexer).getErrorCode());
// It gets back to the original state, so getting the newline works.
EXPECT_EQ(MasterLexer::Token::END_OF_LINE, lexer.getNextToken().getType());