From 4c0e67ae92f288be74748af9de7891b7b641943e Mon Sep 17 00:00:00 2001 From: "arseny.kapoulkine" Date: Mon, 31 May 2010 16:53:13 +0000 Subject: XPath: Replaced backtracking with lookahead in absolute path parsing git-svn-id: http://pugixml.googlecode.com/svn/trunk@485 99668b35-9821-0410-8761-19e4c4f06640 --- src/pugixpath.cpp | 32 +++++++++----------------------- tests/test_xpath_parse.cpp | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/pugixpath.cpp b/src/pugixpath.cpp index 6262ff3..78127dc 100644 --- a/src/pugixpath.cpp +++ b/src/pugixpath.cpp @@ -881,12 +881,6 @@ namespace pugi return m_cur; } - void reset(const char_t* state) - { - m_cur = state; - next(); - } - void next() { contents_clear(); @@ -3079,25 +3073,17 @@ namespace pugi { if (m_lexer.current() == lex_slash) { - // Save state for next lexeme - that is, whatever follows '/' - const char_t* state = 0; // gcc3 "variable might be used uninitialized in this function" bug workaround - state = m_lexer.state(); - m_lexer.next(); - xpath_ast_node* n = 0; // gcc3 "variable might be used uninitialized in this function" bug workaround - n = new (m_alloc.node()) xpath_ast_node(ast_step_root, xpath_type_node_set); - - try - { - n = parse_relative_location_path(n); - } - catch (const xpath_exception&) - { - m_lexer.reset(state); - } - - return n; + xpath_ast_node* n = new (m_alloc.node()) xpath_ast_node(ast_step_root, xpath_type_node_set); + + // relative location path can start from axis_attribute, dot, double_dot, multiply and string lexemes; any other lexeme means standalone root path + lexeme_t l = m_lexer.current(); + + if (l == lex_string || l == lex_axis_attribute || l == lex_dot || l == lex_double_dot || l == lex_multiply) + return parse_relative_location_path(n); + else + return n; } else if (m_lexer.current() == lex_double_slash) { diff --git a/tests/test_xpath_parse.cpp b/tests/test_xpath_parse.cpp index b977ce5..caebb9b 100644 --- a/tests/test_xpath_parse.cpp +++ b/tests/test_xpath_parse.cpp @@ -254,4 +254,19 @@ TEST(xpath_parse_jaxen_invalid) } } +TEST_XML(xpath_parse_absolute, "
") +{ + CHECK_XPATH_NODESET(doc, STR("/")) % 1; + + CHECK_XPATH_NODESET(doc, STR("/div/s")) % 3; + CHECK_XPATH_NODESET(doc, STR("/ div /s")) % 3; + CHECK_XPATH_FAIL(STR("/ div 5")); + + CHECK_XPATH_NODESET(doc, STR("/*/s")) % 3; + CHECK_XPATH_NODESET(doc, STR("/ * /s")) % 3; + CHECK_XPATH_FAIL(STR("/ * 5")); + + CHECK_XPATH_NODESET(doc, STR("/*[/]")) % 2; +} + #endif -- cgit v1.2.3