Browse Source

[2372] more parentheses support

JINMEI Tatuya 12 years ago
parent
commit
65fee8d161
2 changed files with 47 additions and 14 deletions
  1. 9 4
      src/lib/dns/master_lexer.cc
  2. 38 10
      src/lib/dns/tests/master_lexer_state_unittest.cc

+ 9 - 4
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);

+ 38 - 10
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<const State*>(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<const State*>(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<const State*>(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<const State*>(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<const State*>(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);
+}
+
 }