Classes | Public Member Functions | Static Public Member Functions | Public Attributes
xpath_parser Struct Reference
Collaboration diagram for xpath_parser:
Collaboration graph
[legend]

List of all members.

Classes

struct  binary_op_t

Public Member Functions

void throw_error (const char *message)
void throw_error_oom ()
void * alloc_node ()
const char_t * alloc_string (const xpath_lexer_string &value)
xpath_ast_nodeparse_function_helper (ast_type_t type0, ast_type_t type1, size_t argc, xpath_ast_node *args[2])
xpath_ast_nodeparse_function (const xpath_lexer_string &name, size_t argc, xpath_ast_node *args[2])
axis_t parse_axis_name (const xpath_lexer_string &name, bool &specified)
nodetest_t parse_node_test_type (const xpath_lexer_string &name)
xpath_ast_nodeparse_primary_expression ()
xpath_ast_nodeparse_filter_expression ()
xpath_ast_nodeparse_step (xpath_ast_node *set)
xpath_ast_nodeparse_relative_location_path (xpath_ast_node *set)
xpath_ast_nodeparse_location_path ()
xpath_ast_nodeparse_path_or_unary_expression ()
xpath_ast_nodeparse_expression_rec (xpath_ast_node *lhs, int limit)
xpath_ast_nodeparse_expression ()
 xpath_parser (const char_t *query, xpath_variable_set *variables, xpath_allocator *alloc, xpath_parse_result *result)
xpath_ast_nodeparse ()

Static Public Member Functions

static xpath_ast_nodeparse (const char_t *query, xpath_variable_set *variables, xpath_allocator *alloc, xpath_parse_result *result)

Public Attributes

xpath_allocator_alloc
xpath_lexer _lexer
const char_t * _query
xpath_variable_set * _variables
xpath_parse_result * _result
char_t _scratch [32]

Detailed Description

Definition at line 9258 of file pugixml.cpp.


Constructor & Destructor Documentation

xpath_parser::xpath_parser ( const char_t *  query,
xpath_variable_set *  variables,
xpath_allocator alloc,
xpath_parse_result *  result 
) [inline]

Definition at line 10061 of file pugixml.cpp.

                                                                                                                                    : _alloc(alloc), _lexer(query), _query(query), _variables(variables), _result(result)
                {
                }

Member Function Documentation

void* xpath_parser::alloc_node ( ) [inline]
const char_t* xpath_parser::alloc_string ( const xpath_lexer_string value) [inline]

Definition at line 9304 of file pugixml.cpp.

References _alloc, xpath_allocator::allocate_nothrow(), xpath_lexer_string::begin, xpath_lexer_string::end, and throw_error_oom().

Referenced by parse_primary_expression(), and parse_step().

                {
                        if (value.begin)
                        {
                                size_t length = static_cast<size_t>(value.end - value.begin);

                                char_t* c = static_cast<char_t*>(_alloc->allocate_nothrow((length + 1) * sizeof(char_t)));
                                if (!c) throw_error_oom();
                                assert(c); // workaround for clang static analysis

                                memcpy(c, value.begin, length * sizeof(char_t));
                                c[length] = 0;

                                return c;
                        }
                        else return 0;
                }

Definition at line 10065 of file pugixml.cpp.

References _lexer, xpath_lexer::current(), lex_eof, parse_expression(), and throw_error().

Referenced by parse().

                {
                        xpath_ast_node* result = parse_expression();
                        
                        if (_lexer.current() != lex_eof)
                        {
                                // there are still unparsed tokens left, error
                                throw_error("Incorrect query");
                        }
                        
                        return result;
                }
static xpath_ast_node* xpath_parser::parse ( const char_t *  query,
xpath_variable_set *  variables,
xpath_allocator alloc,
xpath_parse_result *  result 
) [inline, static]

Definition at line 10078 of file pugixml.cpp.

References parse().

                {
                        xpath_parser parser(query, variables, alloc, result);

                #ifdef PUGIXML_NO_EXCEPTIONS
                        int error = setjmp(parser._error_handler);

                        return (error == 0) ? parser.parse() : 0;
                #else
                        return parser.parse();
                #endif
                }
axis_t xpath_parser::parse_axis_name ( const xpath_lexer_string name,
bool &  specified 
) [inline]

Definition at line 9444 of file pugixml.cpp.

References axis_ancestor, axis_ancestor_or_self, axis_attribute, axis_child, axis_descendant, axis_descendant_or_self, axis_following, axis_following_sibling, axis_namespace, axis_parent, axis_preceding, axis_preceding_sibling, axis_self, and xpath_lexer_string::begin.

Referenced by parse_step().

                {
                        specified = true;

                        switch (name.begin[0])
                        {
                        case 'a':
                                if (name == PUGIXML_TEXT("ancestor"))
                                        return axis_ancestor;
                                else if (name == PUGIXML_TEXT("ancestor-or-self"))
                                        return axis_ancestor_or_self;
                                else if (name == PUGIXML_TEXT("attribute"))
                                        return axis_attribute;
                                
                                break;
                        
                        case 'c':
                                if (name == PUGIXML_TEXT("child"))
                                        return axis_child;
                                
                                break;
                        
                        case 'd':
                                if (name == PUGIXML_TEXT("descendant"))
                                        return axis_descendant;
                                else if (name == PUGIXML_TEXT("descendant-or-self"))
                                        return axis_descendant_or_self;
                                
                                break;
                        
                        case 'f':
                                if (name == PUGIXML_TEXT("following"))
                                        return axis_following;
                                else if (name == PUGIXML_TEXT("following-sibling"))
                                        return axis_following_sibling;
                                
                                break;
                        
                        case 'n':
                                if (name == PUGIXML_TEXT("namespace"))
                                        return axis_namespace;
                                
                                break;
                        
                        case 'p':
                                if (name == PUGIXML_TEXT("parent"))
                                        return axis_parent;
                                else if (name == PUGIXML_TEXT("preceding"))
                                        return axis_preceding;
                                else if (name == PUGIXML_TEXT("preceding-sibling"))
                                        return axis_preceding_sibling;
                                
                                break;
                        
                        case 's':
                                if (name == PUGIXML_TEXT("self"))
                                        return axis_self;
                                
                                break;

                        default:
                                break;
                        }

                        specified = false;
                        return axis_child;
                }

Definition at line 10008 of file pugixml.cpp.

References _lexer, alloc_node(), ast_op_union, ast_unknown, xpath_parser::binary_op_t::asttype, xpath_lexer::next(), xpath_parser::binary_op_t::parse(), parse_path_or_unary_expression(), xpath_parser::binary_op_t::precedence, xpath_ast_node::rettype(), xpath_parser::binary_op_t::rettype, and throw_error().

Referenced by parse_expression(), and parse_path_or_unary_expression().

                {
                        binary_op_t op = binary_op_t::parse(_lexer);

                        while (op.asttype != ast_unknown && op.precedence >= limit)
                        {
                                _lexer.next();

                                xpath_ast_node* rhs = parse_path_or_unary_expression();

                                binary_op_t nextop = binary_op_t::parse(_lexer);

                                while (nextop.asttype != ast_unknown && nextop.precedence > op.precedence)
                                {
                                        rhs = parse_expression_rec(rhs, nextop.precedence);

                                        nextop = binary_op_t::parse(_lexer);
                                }

                                if (op.asttype == ast_op_union && (lhs->rettype() != xpath_type_node_set || rhs->rettype() != xpath_type_node_set))
                                        throw_error("Union operator has to be applied to node sets");

                                lhs = new (alloc_node()) xpath_ast_node(op.asttype, op.rettype, lhs, rhs);

                                op = binary_op_t::parse(_lexer);
                        }

                        return lhs;
                }

Definition at line 9653 of file pugixml.cpp.

References _lexer, alloc_node(), ast_filter, ast_filter_posinv, xpath_lexer::current(), xpath_ast_node::is_posinv(), lex_close_square_brace, lex_open_square_brace, xpath_lexer::next(), parse_expression(), parse_primary_expression(), xpath_ast_node::rettype(), and throw_error().

Referenced by parse_path_or_unary_expression().

                {
                        xpath_ast_node* n = parse_primary_expression();

                        while (_lexer.current() == lex_open_square_brace)
                        {
                                _lexer.next();

                                xpath_ast_node* expr = parse_expression();

                                if (n->rettype() != xpath_type_node_set) throw_error("Predicate has to be applied to node set");

                                bool posinv = expr->rettype() != xpath_type_number && expr->is_posinv();

                                n = new (alloc_node()) xpath_ast_node(posinv ? ast_filter_posinv : ast_filter, xpath_type_node_set, n, expr);

                                if (_lexer.current() != lex_close_square_brace)
                                        throw_error("Unmatched square brace");
                        
                                _lexer.next();
                        }
                        
                        return n;
                }
xpath_ast_node* xpath_parser::parse_function ( const xpath_lexer_string name,
size_t  argc,
xpath_ast_node args[2] 
) [inline]

Definition at line 9331 of file pugixml.cpp.

References alloc_node(), ast_func_boolean, ast_func_ceiling, ast_func_concat, ast_func_contains, ast_func_count, ast_func_false, ast_func_floor, ast_func_id, ast_func_lang, ast_func_last, ast_func_local_name_0, ast_func_local_name_1, ast_func_name_0, ast_func_name_1, ast_func_namespace_uri_0, ast_func_namespace_uri_1, ast_func_normalize_space_0, ast_func_normalize_space_1, ast_func_not, ast_func_number_0, ast_func_number_1, ast_func_position, ast_func_round, ast_func_starts_with, ast_func_string_0, ast_func_string_1, ast_func_string_length_0, ast_func_string_length_1, ast_func_substring_2, ast_func_substring_3, ast_func_substring_after, ast_func_substring_before, ast_func_sum, ast_func_translate, ast_func_true, xpath_lexer_string::begin, parse_function_helper(), and throw_error().

Referenced by parse_primary_expression().

                {
                        switch (name.begin[0])
                        {
                        case 'b':
                                if (name == PUGIXML_TEXT("boolean") && argc == 1)
                                        return new (alloc_node()) xpath_ast_node(ast_func_boolean, xpath_type_boolean, args[0]);
                                        
                                break;
                        
                        case 'c':
                                if (name == PUGIXML_TEXT("count") && argc == 1)
                                {
                                        if (args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set");
                                        return new (alloc_node()) xpath_ast_node(ast_func_count, xpath_type_number, args[0]);
                                }
                                else if (name == PUGIXML_TEXT("contains") && argc == 2)
                                        return new (alloc_node()) xpath_ast_node(ast_func_contains, xpath_type_boolean, args[0], args[1]);
                                else if (name == PUGIXML_TEXT("concat") && argc >= 2)
                                        return new (alloc_node()) xpath_ast_node(ast_func_concat, xpath_type_string, args[0], args[1]);
                                else if (name == PUGIXML_TEXT("ceiling") && argc == 1)
                                        return new (alloc_node()) xpath_ast_node(ast_func_ceiling, xpath_type_number, args[0]);
                                        
                                break;
                        
                        case 'f':
                                if (name == PUGIXML_TEXT("false") && argc == 0)
                                        return new (alloc_node()) xpath_ast_node(ast_func_false, xpath_type_boolean);
                                else if (name == PUGIXML_TEXT("floor") && argc == 1)
                                        return new (alloc_node()) xpath_ast_node(ast_func_floor, xpath_type_number, args[0]);
                                        
                                break;
                        
                        case 'i':
                                if (name == PUGIXML_TEXT("id") && argc == 1)
                                        return new (alloc_node()) xpath_ast_node(ast_func_id, xpath_type_node_set, args[0]);
                                        
                                break;
                        
                        case 'l':
                                if (name == PUGIXML_TEXT("last") && argc == 0)
                                        return new (alloc_node()) xpath_ast_node(ast_func_last, xpath_type_number);
                                else if (name == PUGIXML_TEXT("lang") && argc == 1)
                                        return new (alloc_node()) xpath_ast_node(ast_func_lang, xpath_type_boolean, args[0]);
                                else if (name == PUGIXML_TEXT("local-name") && argc <= 1)
                                        return parse_function_helper(ast_func_local_name_0, ast_func_local_name_1, argc, args);
                        
                                break;
                        
                        case 'n':
                                if (name == PUGIXML_TEXT("name") && argc <= 1)
                                        return parse_function_helper(ast_func_name_0, ast_func_name_1, argc, args);
                                else if (name == PUGIXML_TEXT("namespace-uri") && argc <= 1)
                                        return parse_function_helper(ast_func_namespace_uri_0, ast_func_namespace_uri_1, argc, args);
                                else if (name == PUGIXML_TEXT("normalize-space") && argc <= 1)
                                        return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_normalize_space_0 : ast_func_normalize_space_1, xpath_type_string, args[0], args[1]);
                                else if (name == PUGIXML_TEXT("not") && argc == 1)
                                        return new (alloc_node()) xpath_ast_node(ast_func_not, xpath_type_boolean, args[0]);
                                else if (name == PUGIXML_TEXT("number") && argc <= 1)
                                        return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_number_0 : ast_func_number_1, xpath_type_number, args[0]);
                        
                                break;
                        
                        case 'p':
                                if (name == PUGIXML_TEXT("position") && argc == 0)
                                        return new (alloc_node()) xpath_ast_node(ast_func_position, xpath_type_number);
                                
                                break;
                        
                        case 'r':
                                if (name == PUGIXML_TEXT("round") && argc == 1)
                                        return new (alloc_node()) xpath_ast_node(ast_func_round, xpath_type_number, args[0]);

                                break;
                        
                        case 's':
                                if (name == PUGIXML_TEXT("string") && argc <= 1)
                                        return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_0 : ast_func_string_1, xpath_type_string, args[0]);
                                else if (name == PUGIXML_TEXT("string-length") && argc <= 1)
                                        return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_length_0 : ast_func_string_length_1, xpath_type_number, args[0]);
                                else if (name == PUGIXML_TEXT("starts-with") && argc == 2)
                                        return new (alloc_node()) xpath_ast_node(ast_func_starts_with, xpath_type_boolean, args[0], args[1]);
                                else if (name == PUGIXML_TEXT("substring-before") && argc == 2)
                                        return new (alloc_node()) xpath_ast_node(ast_func_substring_before, xpath_type_string, args[0], args[1]);
                                else if (name == PUGIXML_TEXT("substring-after") && argc == 2)
                                        return new (alloc_node()) xpath_ast_node(ast_func_substring_after, xpath_type_string, args[0], args[1]);
                                else if (name == PUGIXML_TEXT("substring") && (argc == 2 || argc == 3))
                                        return new (alloc_node()) xpath_ast_node(argc == 2 ? ast_func_substring_2 : ast_func_substring_3, xpath_type_string, args[0], args[1]);
                                else if (name == PUGIXML_TEXT("sum") && argc == 1)
                                {
                                        if (args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set");
                                        return new (alloc_node()) xpath_ast_node(ast_func_sum, xpath_type_number, args[0]);
                                }

                                break;
                        
                        case 't':
                                if (name == PUGIXML_TEXT("translate") && argc == 3)
                                        return new (alloc_node()) xpath_ast_node(ast_func_translate, xpath_type_string, args[0], args[1]);
                                else if (name == PUGIXML_TEXT("true") && argc == 0)
                                        return new (alloc_node()) xpath_ast_node(ast_func_true, xpath_type_boolean);
                                        
                                break;

                        default:
                                break;
                        }

                        throw_error("Unrecognized function or wrong parameter count");

                        return 0;
                }
xpath_ast_node* xpath_parser::parse_function_helper ( ast_type_t  type0,
ast_type_t  type1,
size_t  argc,
xpath_ast_node args[2] 
) [inline]

Definition at line 9322 of file pugixml.cpp.

References alloc_node(), and throw_error().

Referenced by parse_function().

                {
                        assert(argc <= 1);

                        if (argc == 1 && args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set");

                        return new (alloc_node()) xpath_ast_node(argc == 0 ? type0 : type1, xpath_type_string, args[0]);
                }

Definition at line 9847 of file pugixml.cpp.

References _lexer, alloc_node(), ast_step, ast_step_root, axis_descendant_or_self, xpath_lexer::current(), lex_axis_attribute, lex_dot, lex_double_dot, lex_double_slash, lex_multiply, lex_slash, lex_string, xpath_lexer::next(), nodetest_type_node, and parse_relative_location_path().

Referenced by parse_path_or_unary_expression().

                {
                        if (_lexer.current() == lex_slash)
                        {
                                _lexer.next();
                                
                                xpath_ast_node* n = new (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 = _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 (_lexer.current() == lex_double_slash)
                        {
                                _lexer.next();
                                
                                xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step_root, xpath_type_node_set);
                                n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0);
                                
                                return parse_relative_location_path(n);
                        }

                        // else clause moved outside of if because of bogus warning 'control may reach end of non-void function being inlined' in gcc 4.0.1
                        return parse_relative_location_path(0);
                }

Definition at line 9512 of file pugixml.cpp.

References xpath_lexer_string::begin, nodetest_none, nodetest_type_comment, nodetest_type_node, nodetest_type_pi, and nodetest_type_text.

Referenced by parse_path_or_unary_expression(), and parse_step().

                {
                        switch (name.begin[0])
                        {
                        case 'c':
                                if (name == PUGIXML_TEXT("comment"))
                                        return nodetest_type_comment;

                                break;

                        case 'n':
                                if (name == PUGIXML_TEXT("node"))
                                        return nodetest_type_node;

                                break;

                        case 'p':
                                if (name == PUGIXML_TEXT("processing-instruction"))
                                        return nodetest_type_pi;

                                break;

                        case 't':
                                if (name == PUGIXML_TEXT("text"))
                                        return nodetest_type_text;

                                break;
                        
                        default:
                                break;
                        }

                        return nodetest_none;
                }

Definition at line 9883 of file pugixml.cpp.

References _lexer, alloc_node(), ast_op_negate, ast_step, axis_descendant_or_self, xpath_lexer::contents(), ct_space, xpath_lexer::current(), lex_double_slash, lex_minus, lex_number, lex_open_brace, lex_quoted_string, lex_slash, lex_string, lex_var_ref, xpath_lexer::next(), nodetest_none, nodetest_type_node, parse_expression_rec(), parse_filter_expression(), parse_location_path(), parse_node_test_type(), parse_relative_location_path(), PUGI__IS_CHARTYPE, xpath_ast_node::rettype(), xpath_lexer::state(), and throw_error().

Referenced by parse_expression(), and parse_expression_rec().

                {
                        // Clarification.
                        // PathExpr begins with either LocationPath or FilterExpr.
                        // FilterExpr begins with PrimaryExpr
                        // PrimaryExpr begins with '$' in case of it being a variable reference,
                        // '(' in case of it being an expression, string literal, number constant or
                        // function call.

                        if (_lexer.current() == lex_var_ref || _lexer.current() == lex_open_brace || 
                                _lexer.current() == lex_quoted_string || _lexer.current() == lex_number ||
                                _lexer.current() == lex_string)
                        {
                                if (_lexer.current() == lex_string)
                                {
                                        // This is either a function call, or not - if not, we shall proceed with location path
                                        const char_t* state = _lexer.state();
                                        
                                        while (PUGI__IS_CHARTYPE(*state, ct_space)) ++state;
                                        
                                        if (*state != '(') return parse_location_path();

                                        // This looks like a function call; however this still can be a node-test. Check it.
                                        if (parse_node_test_type(_lexer.contents()) != nodetest_none) return parse_location_path();
                                }
                                
                                xpath_ast_node* n = parse_filter_expression();

                                if (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash)
                                {
                                        lexeme_t l = _lexer.current();
                                        _lexer.next();
                                        
                                        if (l == lex_double_slash)
                                        {
                                                if (n->rettype() != xpath_type_node_set) throw_error("Step has to be applied to node set");

                                                n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0);
                                        }
        
                                        // select from location path
                                        return parse_relative_location_path(n);
                                }

                                return n;
                        }
                        else if (_lexer.current() == lex_minus)
                        {
                                _lexer.next();

                                // precedence 7+ - only parses union expressions
                                xpath_ast_node* expr = parse_expression_rec(parse_path_or_unary_expression(), 7);

                                return new (alloc_node()) xpath_ast_node(ast_op_negate, xpath_type_number, expr);
                        }
                        else
                                return parse_location_path();
                }

Definition at line 9548 of file pugixml.cpp.

References _lexer, _scratch, _variables, alloc_node(), alloc_string(), ast_number_constant, ast_string_constant, ast_variable, xpath_lexer_string::begin, xpath_lexer::contents(), convert_string_to_number_scratch(), xpath_lexer::current(), xpath_lexer_string::end, get_variable_scratch(), lex_close_brace, lex_comma, lex_number, lex_open_brace, lex_quoted_string, lex_string, lex_var_ref, xpath_lexer::next(), parse_expression(), parse_function(), xpath_ast_node::set_next(), throw_error(), and throw_error_oom().

Referenced by parse_filter_expression().

                {
                        switch (_lexer.current())
                        {
                        case lex_var_ref:
                        {
                                xpath_lexer_string name = _lexer.contents();

                                if (!_variables)
                                        throw_error("Unknown variable: variable set is not provided");

                                xpath_variable* var = get_variable_scratch(_scratch, _variables, name.begin, name.end);

                                if (!var)
                                        throw_error("Unknown variable: variable set does not contain the given name");

                                _lexer.next();

                                return new (alloc_node()) xpath_ast_node(ast_variable, var->type(), var);
                        }

                        case lex_open_brace:
                        {
                                _lexer.next();

                                xpath_ast_node* n = parse_expression();

                                if (_lexer.current() != lex_close_brace)
                                        throw_error("Unmatched braces");

                                _lexer.next();

                                return n;
                        }

                        case lex_quoted_string:
                        {
                                const char_t* value = alloc_string(_lexer.contents());

                                xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_string_constant, xpath_type_string, value);
                                _lexer.next();

                                return n;
                        }

                        case lex_number:
                        {
                                double value = 0;

                                if (!convert_string_to_number_scratch(_scratch, _lexer.contents().begin, _lexer.contents().end, &value))
                                        throw_error_oom();

                                xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_number_constant, xpath_type_number, value);
                                _lexer.next();

                                return n;
                        }

                        case lex_string:
                        {
                                xpath_ast_node* args[2] = {0};
                                size_t argc = 0;
                                
                                xpath_lexer_string function = _lexer.contents();
                                _lexer.next();
                                
                                xpath_ast_node* last_arg = 0;
                                
                                if (_lexer.current() != lex_open_brace)
                                        throw_error("Unrecognized function call");
                                _lexer.next();

                                if (_lexer.current() != lex_close_brace)
                                        args[argc++] = parse_expression();

                                while (_lexer.current() != lex_close_brace)
                                {
                                        if (_lexer.current() != lex_comma)
                                                throw_error("No comma between function arguments");
                                        _lexer.next();
                                        
                                        xpath_ast_node* n = parse_expression();
                                        
                                        if (argc < 2) args[argc] = n;
                                        else last_arg->set_next(n);

                                        argc++;
                                        last_arg = n;
                                }
                                
                                _lexer.next();

                                return parse_function(function, argc, args);
                        }

                        default:
                                throw_error("Unrecognizable primary expression");

                                return 0;
                        }
                }

Definition at line 9683 of file pugixml.cpp.

References _lexer, alloc_node(), alloc_string(), ast_predicate, ast_step, axis_attribute, axis_child, axis_parent, axis_self, xpath_lexer_string::begin, xpath_lexer::contents(), xpath_lexer::current(), xpath_lexer_string::end, lex_axis_attribute, lex_close_brace, lex_close_square_brace, lex_dot, lex_double_colon, lex_double_dot, lex_multiply, lex_open_brace, lex_open_square_brace, lex_quoted_string, lex_string, xpath_lexer::next(), nodetest_all, nodetest_all_in_namespace, nodetest_name, nodetest_none, nodetest_pi, nodetest_type_node, parse_axis_name(), parse_expression(), parse_node_test_type(), xpath_ast_node::set_next(), xpath_ast_node::set_right(), and throw_error().

Referenced by parse_relative_location_path().

                {
                        if (set && set->rettype() != xpath_type_node_set)
                                throw_error("Step has to be applied to node set");

                        bool axis_specified = false;
                        axis_t axis = axis_child; // implied child axis

                        if (_lexer.current() == lex_axis_attribute)
                        {
                                axis = axis_attribute;
                                axis_specified = true;
                                
                                _lexer.next();
                        }
                        else if (_lexer.current() == lex_dot)
                        {
                                _lexer.next();
                                
                                return new (alloc_node()) xpath_ast_node(ast_step, set, axis_self, nodetest_type_node, 0);
                        }
                        else if (_lexer.current() == lex_double_dot)
                        {
                                _lexer.next();
                                
                                return new (alloc_node()) xpath_ast_node(ast_step, set, axis_parent, nodetest_type_node, 0);
                        }
                
                        nodetest_t nt_type = nodetest_none;
                        xpath_lexer_string nt_name;
                        
                        if (_lexer.current() == lex_string)
                        {
                                // node name test
                                nt_name = _lexer.contents();
                                _lexer.next();

                                // was it an axis name?
                                if (_lexer.current() == lex_double_colon)
                                {
                                        // parse axis name
                                        if (axis_specified) throw_error("Two axis specifiers in one step");

                                        axis = parse_axis_name(nt_name, axis_specified);

                                        if (!axis_specified) throw_error("Unknown axis");

                                        // read actual node test
                                        _lexer.next();

                                        if (_lexer.current() == lex_multiply)
                                        {
                                                nt_type = nodetest_all;
                                                nt_name = xpath_lexer_string();
                                                _lexer.next();
                                        }
                                        else if (_lexer.current() == lex_string)
                                        {
                                                nt_name = _lexer.contents();
                                                _lexer.next();
                                        }
                                        else throw_error("Unrecognized node test");
                                }
                                
                                if (nt_type == nodetest_none)
                                {
                                        // node type test or processing-instruction
                                        if (_lexer.current() == lex_open_brace)
                                        {
                                                _lexer.next();
                                                
                                                if (_lexer.current() == lex_close_brace)
                                                {
                                                        _lexer.next();

                                                        nt_type = parse_node_test_type(nt_name);

                                                        if (nt_type == nodetest_none) throw_error("Unrecognized node type");
                                                        
                                                        nt_name = xpath_lexer_string();
                                                }
                                                else if (nt_name == PUGIXML_TEXT("processing-instruction"))
                                                {
                                                        if (_lexer.current() != lex_quoted_string)
                                                                throw_error("Only literals are allowed as arguments to processing-instruction()");
                                                
                                                        nt_type = nodetest_pi;
                                                        nt_name = _lexer.contents();
                                                        _lexer.next();
                                                        
                                                        if (_lexer.current() != lex_close_brace)
                                                                throw_error("Unmatched brace near processing-instruction()");
                                                        _lexer.next();
                                                }
                                                else
                                                        throw_error("Unmatched brace near node type test");

                                        }
                                        // QName or NCName:*
                                        else
                                        {
                                                if (nt_name.end - nt_name.begin > 2 && nt_name.end[-2] == ':' && nt_name.end[-1] == '*') // NCName:*
                                                {
                                                        nt_name.end--; // erase *
                                                        
                                                        nt_type = nodetest_all_in_namespace;
                                                }
                                                else nt_type = nodetest_name;
                                        }
                                }
                        }
                        else if (_lexer.current() == lex_multiply)
                        {
                                nt_type = nodetest_all;
                                _lexer.next();
                        }
                        else throw_error("Unrecognized node test");
                        
                        xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step, set, axis, nt_type, alloc_string(nt_name));
                        
                        xpath_ast_node* last = 0;
                        
                        while (_lexer.current() == lex_open_square_brace)
                        {
                                _lexer.next();
                                
                                xpath_ast_node* expr = parse_expression();

                                xpath_ast_node* pred = new (alloc_node()) xpath_ast_node(ast_predicate, xpath_type_node_set, expr);
                                
                                if (_lexer.current() != lex_close_square_brace)
                                        throw_error("Unmatched square brace");
                                _lexer.next();
                                
                                if (last) last->set_next(pred);
                                else n->set_right(pred);
                                
                                last = pred;
                        }
                        
                        return n;
                }
void xpath_parser::throw_error ( const char *  message) [inline]

Definition at line 9274 of file pugixml.cpp.

References _lexer, _query, _result, and xpath_lexer::current_pos().

Referenced by parse(), parse_expression_rec(), parse_filter_expression(), parse_function(), parse_function_helper(), parse_path_or_unary_expression(), parse_primary_expression(), parse_step(), and throw_error_oom().

                {
                        _result->error = message;
                        _result->offset = _lexer.current_pos() - _query;

                #ifdef PUGIXML_NO_EXCEPTIONS
                        longjmp(_error_handler, 1);
                #else
                        throw xpath_exception(*_result);
                #endif
                }
void xpath_parser::throw_error_oom ( ) [inline]

Definition at line 9286 of file pugixml.cpp.

References throw_error().

Referenced by alloc_node(), alloc_string(), and parse_primary_expression().

                {
                #ifdef PUGIXML_NO_EXCEPTIONS
                        throw_error("Out of memory");
                #else
                        throw std::bad_alloc();
                #endif
                }

Member Data Documentation

Definition at line 9260 of file pugixml.cpp.

Referenced by alloc_node(), and alloc_string().

const char_t* xpath_parser::_query

Definition at line 9263 of file pugixml.cpp.

Referenced by throw_error().

xpath_parse_result* xpath_parser::_result

Definition at line 9266 of file pugixml.cpp.

Referenced by throw_error().

Definition at line 9268 of file pugixml.cpp.

Referenced by parse_primary_expression().

xpath_variable_set* xpath_parser::_variables

Definition at line 9264 of file pugixml.cpp.

Referenced by parse_primary_expression().


The documentation for this struct was generated from the following file:

Generated on Mon Sep 15 2014 01:23:56 for QuickFIX by doxygen 1.7.6.1 written by Dimitri van Heesch, © 1997-2001