From: JINMEI Tatuya Date: Fri, 2 Nov 2012 23:03:36 +0000 (-0700) Subject: [2372] more parentheses support X-Git-Tag: trac2487_base~1^2~21^2~23 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=65fee8d161688cc74df9f14b641b64bc5117cd1f;p=thirdparty%2Fkea.git [2372] more parentheses support --- diff --git a/src/lib/dns/master_lexer.cc b/src/lib/dns/master_lexer.cc index 737844bb1d..b4bec94cde 100644 --- a/src/lib/dns/master_lexer.cc +++ b/src/lib/dns/master_lexer.cc @@ -222,9 +222,11 @@ Start::handle(MasterLexer& lexer, MasterLexer::Options& options, } continue; } else if (c == '\n') { - getLexerImpl(lexer)->last_was_eol_ = true; - getLexerImpl(lexer)->token_ = Token(Token::END_OF_LINE); - return (NULL); + if ((options & MasterLexer::END_OF_LINE) != 0) { + getLexerImpl(lexer)->last_was_eol_ = true; + getLexerImpl(lexer)->token_ = Token(Token::END_OF_LINE); + return (NULL); + } } else if (c == '(') { getLexerImpl(lexer)->last_was_eol_ = false; cancelOptions(options, @@ -234,7 +236,10 @@ Start::handle(MasterLexer& lexer, MasterLexer::Options& options, } else if (c == ')') { // TBD: unbalanced case --getLexerImpl(lexer)->paren_count_; - options = orig_options; // TBD: only when count becomes 0 + if (getLexerImpl(lexer)->paren_count_ == 0) { + options = orig_options; + } + continue; } else { getLexerImpl(lexer)->last_was_eol_ = false; return (&STRING_STATE); diff --git a/src/lib/dns/tests/master_lexer_state_unittest.cc b/src/lib/dns/tests/master_lexer_state_unittest.cc index 849d6ddbd5..98f5b30d94 100644 --- a/src/lib/dns/tests/master_lexer_state_unittest.cc +++ b/src/lib/dns/tests/master_lexer_state_unittest.cc @@ -28,7 +28,8 @@ typedef MasterLexer::Token Token; // shortcut class MasterLexerStateTest : public ::testing::Test { protected: - MasterLexerStateTest() : s_start(State::getInstance(State::Start)), + MasterLexerStateTest() : s_null(NULL), + s_start(State::getInstance(State::Start)), s_crlf(State::getInstance(State::CRLF)), s_string(State::getInstance(State::String)), options(MasterLexer::END_OF_LINE), @@ -36,6 +37,7 @@ protected: { lexer.pushSource(ss); } + const State* const s_null; const State& s_start; const State& s_crlf; const State& s_string; @@ -58,14 +60,14 @@ TEST_F(MasterLexerStateTest, startAndEnd) { // A simple case: the input is empty, so we begin with start and // are immediately done. const State* s_next = s_start.handle(lexer, options); - EXPECT_EQ(static_cast(NULL), s_next); + EXPECT_EQ(s_null, s_next); eofCheck(s_start, lexer); } TEST_F(MasterLexerStateTest, startToEOL) { ss << "\n"; const State* s_next = s_start.handle(lexer, options); - EXPECT_EQ(static_cast(NULL), s_next); + EXPECT_EQ(s_null, s_next); EXPECT_TRUE(s_start.wasLastEOL(lexer)); EXPECT_EQ(Token::END_OF_LINE, s_start.getToken(lexer).getType()); @@ -85,7 +87,7 @@ TEST_F(MasterLexerStateTest, space) { for (size_t i = 0; i < 2; ++i) { ss << " \t\n"; s_next = s_start.handle(lexer, options); - EXPECT_EQ(static_cast(NULL), s_next); + EXPECT_EQ(s_null, s_next); EXPECT_TRUE(s_start.wasLastEOL(lexer)); EXPECT_EQ(Token::END_OF_LINE, s_start.getToken(lexer).getType()); } @@ -95,18 +97,18 @@ TEST_F(MasterLexerStateTest, space) { ss << " "; options = MasterLexer::INITIAL_WS; s_next = s_start.handle(lexer, options); - EXPECT_EQ(static_cast(NULL), s_next); + EXPECT_EQ(s_null, s_next); EXPECT_FALSE(s_start.wasLastEOL(lexer)); EXPECT_EQ(Token::INITIAL_WS, s_start.getToken(lexer).getType()); } TEST_F(MasterLexerStateTest, parentheses) { - ss << "\n(a)"; // add \n to check if 'was EOL' is set to false + ss << "\n(\na)"; // 1st \n is to check if 'was EOL' is set to false const State* s_next = s_start.handle(lexer, options); // handle \n - EXPECT_EQ(static_cast(NULL), s_next); + EXPECT_EQ(s_null, s_next); - // Now handle '(' + // Now handle '('. It skips \n and recognize 'a' as strin EXPECT_EQ(0, s_start.getParenCount(lexer)); // check pre condition options = MasterLexer::END_OF_LINE | MasterLexer::INITIAL_WS; s_next = s_start.handle(lexer, options, options); @@ -119,8 +121,8 @@ TEST_F(MasterLexerStateTest, parentheses) { EXPECT_TRUE((options & MasterLexer::INITIAL_WS) == 0); // same for init WS EXPECT_EQ(1, s_start.getParenCount(lexer)); - // Then handle ')'. eol and init_ws are kept cleared, and will be set - // again. + // Then handle ')'. eol and init_ws are currently cleared, which will be + // set again. s_next = s_start.handle(lexer, options, (MasterLexer::END_OF_LINE | MasterLexer::INITIAL_WS)); EXPECT_EQ(0, s_start.getParenCount(lexer)); @@ -130,4 +132,30 @@ TEST_F(MasterLexerStateTest, parentheses) { // TBD: Test case: '(;' } +TEST_F(MasterLexerStateTest, nestedParentheses) { + // This is an unusual, but allowed (in this implementation) case. + + ss << "(a(b)c)"; + EXPECT_EQ(&s_string, s_start.handle(lexer, options)); // consume '(a' + EXPECT_EQ(&s_string, s_start.handle(lexer, options)); // consume '(b' + EXPECT_EQ(2, s_start.getParenCount(lexer)); // now the count is 2 + + // Close the inner most parentheses. count will be decreased, but option + // shouldn't be restored yet. + EXPECT_EQ(&s_string, + s_start.handle(lexer, options, (MasterLexer::END_OF_LINE | + MasterLexer::INITIAL_WS))); + EXPECT_EQ(1, s_start.getParenCount(lexer)); + EXPECT_TRUE((options & MasterLexer::END_OF_LINE) == 0); + EXPECT_TRUE((options & MasterLexer::INITIAL_WS) == 0); + + // Close the outermost parentheses. count will be reset to 0, and original + // options are restored. + EXPECT_EQ(s_null, + s_start.handle(lexer, options, (MasterLexer::END_OF_LINE | + MasterLexer::INITIAL_WS))); + EXPECT_TRUE((options & MasterLexer::END_OF_LINE) != 0); + EXPECT_TRUE((options & MasterLexer::INITIAL_WS) != 0); +} + }