xpath_parser Struct Reference
Collaboration diagram for xpath_parser:
[legend]

## 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_node * | parse_function_helper (ast_type_t type0, ast_type_t type1, size_t argc, xpath_ast_node *args[2])
xpath_ast_node * | parse_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_node * | parse_primary_expression ()
xpath_ast_node * | parse_filter_expression ()
xpath_ast_node * | parse_step (xpath_ast_node *set)
xpath_ast_node * | parse_relative_location_path (xpath_ast_node *set)
xpath_ast_node * | parse_location_path ()
xpath_ast_node * | parse_path_or_unary_expression ()
xpath_ast_node * | parse_expression_rec (xpath_ast_node *lhs, int limit)
xpath_ast_node * | parse_expression ()
| xpath_parser (const char_t *query, xpath_variable_set *variables, xpath_allocator *alloc, xpath_parse_result *result)
xpath_ast_node * | parse ()

## Static Public Member Functions

static xpath_ast_node * | parse (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::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)
{
}
xpath_parser::_variables
xpath_variable_set * _variables
Definition: pugixml.cpp:9264
xpath_parser::_lexer
xpath_lexer _lexer
Definition: pugixml.cpp:9261
xpath_parser::_result
xpath_parse_result * _result
Definition: pugixml.cpp:9266
xpath_parser::_query
const char_t * _query
Definition: pugixml.cpp:9263
xpath_parser::_alloc
xpath_allocator * _alloc
Definition: pugixml.cpp:9260

## Member Function Documentation

## alloc_node()

void* xpath_parser::alloc_node | ( |  | ) |

inline

Definition at line 9295 of file pugixml.cpp.

{
void* result = _alloc->allocate_nothrow(sizeof(xpath_ast_node));
if (!result) throw_error_oom();
return result;
}
xpath_allocator::allocate_nothrow
void * allocate_nothrow(size_t size)
Definition: pugixml.cpp:6217
xpath_ast_node
Definition: pugixml.cpp:7919
xpath_parser::throw_error_oom
void throw_error_oom()
Definition: pugixml.cpp:9286

References _alloc, xpath_allocator::allocate_nothrow(), and throw_error_oom().

Referenced by parse_expression_rec(), parse_filter_expression(), parse_function(), parse_function_helper(), parse_location_path(), parse_path_or_unary_expression(), parse_primary_expression(), parse_relative_location_path(), and parse_step().

## alloc_string()

const char_t* xpath_parser::alloc_string | ( | const xpath_lexer_string & | value | ) |

inline

Definition at line 9304 of file pugixml.cpp.

{
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;
}
xpath_lexer_string::begin
const char_t * begin
Definition: pugixml.cpp:7497
xpath_lexer_string::end
const char_t * end
Definition: pugixml.cpp:7498

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().

## parse() [1/2]

xpath_ast_node* xpath_parser::parse | ( |  | ) |

inline

Definition at line 10065 of file pugixml.cpp.

{
xpath_ast_node* result = parse_expression();
if (_lexer.current() != lex_eof)
{
// there are still unparsed tokens left, error
throw_error("Incorrect query");
}
return result;
}
xpath_lexer::current
lexeme_t current() const
Definition: pugixml.cpp:7800
lex_eof
@ lex_eof
Definition: pugixml.cpp:7492
xpath_parser::throw_error
void throw_error(const char *message)
Definition: pugixml.cpp:9274
xpath_parser::parse_expression
xpath_ast_node * parse_expression()
Definition: pugixml.cpp:10056

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

Referenced by parse().

## parse() [2/2]

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.

{
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
}
xpath_parser
Definition: pugixml.cpp:9259

References parse().

## parse_axis_name()

axis_t xpath_parser::parse_axis_name | ( | const xpath_lexer_string & | name,
|  | bool & | specified
| ) |  |

inline

Definition at line 9444 of file pugixml.cpp.

{
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;
}
axis_preceding
@ axis_preceding
Definition: pugixml.cpp:7893
axis_ancestor_or_self
@ axis_ancestor_or_self
Definition: pugixml.cpp:7884
axis_attribute
@ axis_attribute
Definition: pugixml.cpp:7885
axis_following_sibling
@ axis_following_sibling
Definition: pugixml.cpp:7890
axis_child
@ axis_child
Definition: pugixml.cpp:7886
axis_descendant
@ axis_descendant
Definition: pugixml.cpp:7887
axis_descendant_or_self
@ axis_descendant_or_self
Definition: pugixml.cpp:7888
axis_self
@ axis_self
Definition: pugixml.cpp:7895
axis_following
@ axis_following
Definition: pugixml.cpp:7889
axis_ancestor
@ axis_ancestor
Definition: pugixml.cpp:7883
axis_preceding_sibling
@ axis_preceding_sibling
Definition: pugixml.cpp:7894
axis_namespace
@ axis_namespace
Definition: pugixml.cpp:7891
axis_parent
@ axis_parent
Definition: pugixml.cpp:7892

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().

## parse_expression()

xpath_ast_node* xpath_parser::parse_expression | ( |  | ) |

inline

Definition at line 10056 of file pugixml.cpp.

{
return parse_expression_rec(parse_path_or_unary_expression(), 0);
}
xpath_parser::parse_path_or_unary_expression
xpath_ast_node * parse_path_or_unary_expression()
Definition: pugixml.cpp:9883
xpath_parser::parse_expression_rec
xpath_ast_node * parse_expression_rec(xpath_ast_node *lhs, int limit)
Definition: pugixml.cpp:10008

References parse_expression_rec(), and parse_path_or_unary_expression().

Referenced by parse(), parse_filter_expression(), parse_primary_expression(), and parse_step().

## parse_expression_rec()

xpath_ast_node* xpath_parser::parse_expression_rec | ( | xpath_ast_node * | lhs,
|  | int | limit
| ) |  |

inline

Definition at line 10008 of file pugixml.cpp.

{
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;
}
xpath_ast_node::rettype
xpath_value_type rettype() const
Definition: pugixml.cpp:9252
xpath_lexer::next
void next()
Definition: pugixml.cpp:7531
ast_unknown
@ ast_unknown
Definition: pugixml.cpp:7820
ast_op_union
@ ast_op_union
Definition: pugixml.cpp:7835
xpath_parser::binary_op_t::parse
static binary_op_t parse(xpath_lexer &lexer)
Definition: pugixml.cpp:9956
xpath_parser::alloc_node
void * alloc_node()
Definition: pugixml.cpp:9295

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().

## parse_filter_expression()

xpath_ast_node* xpath_parser::parse_filter_expression | ( |  | ) |

inline

Definition at line 9653 of file pugixml.cpp.

{
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::is_posinv
bool is_posinv()
Definition: pugixml.cpp:9221
ast_filter
@ ast_filter
Definition: pugixml.cpp:7837
ast_filter_posinv
@ ast_filter_posinv
Definition: pugixml.cpp:7838
lex_close_square_brace
@ lex_close_square_brace
Definition: pugixml.cpp:7485
lex_open_square_brace
@ lex_open_square_brace
Definition: pugixml.cpp:7484
xpath_parser::parse_primary_expression
xpath_ast_node * parse_primary_expression()
Definition: pugixml.cpp:9548

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().

## parse_function()

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.

{
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;
}
ast_func_substring_3
@ ast_func_substring_3
Definition: pugixml.cpp:7860
ast_func_sum
@ ast_func_sum
Definition: pugixml.cpp:7873
ast_func_name_1
@ ast_func_name_1
Definition: pugixml.cpp:7851
ast_func_floor
@ ast_func_floor
Definition: pugixml.cpp:7874
ast_func_concat
@ ast_func_concat
Definition: pugixml.cpp:7854
ast_func_name_0
@ ast_func_name_0
Definition: pugixml.cpp:7850
ast_func_not
@ ast_func_not
Definition: pugixml.cpp:7867
ast_func_string_1
@ ast_func_string_1
Definition: pugixml.cpp:7853
ast_func_string_0
@ ast_func_string_0
Definition: pugixml.cpp:7852
ast_func_number_0
@ ast_func_number_0
Definition: pugixml.cpp:7871
ast_func_substring_before
@ ast_func_substring_before
Definition: pugixml.cpp:7857
ast_func_string_length_0
@ ast_func_string_length_0
Definition: pugixml.cpp:7861
ast_func_local_name_1
@ ast_func_local_name_1
Definition: pugixml.cpp:7847
ast_func_namespace_uri_0
@ ast_func_namespace_uri_0
Definition: pugixml.cpp:7848
ast_func_lang
@ ast_func_lang
Definition: pugixml.cpp:7870
ast_func_true
@ ast_func_true
Definition: pugixml.cpp:7868
ast_func_normalize_space_1
@ ast_func_normalize_space_1
Definition: pugixml.cpp:7864
ast_func_contains
@ ast_func_contains
Definition: pugixml.cpp:7856
ast_func_substring_2
@ ast_func_substring_2
Definition: pugixml.cpp:7859
ast_func_position
@ ast_func_position
Definition: pugixml.cpp:7843
ast_func_ceiling
@ ast_func_ceiling
Definition: pugixml.cpp:7875
ast_func_last
@ ast_func_last
Definition: pugixml.cpp:7842
ast_func_normalize_space_0
@ ast_func_normalize_space_0
Definition: pugixml.cpp:7863
ast_func_boolean
@ ast_func_boolean
Definition: pugixml.cpp:7866
ast_func_count
@ ast_func_count
Definition: pugixml.cpp:7844
ast_func_substring_after
@ ast_func_substring_after
Definition: pugixml.cpp:7858
ast_func_namespace_uri_1
@ ast_func_namespace_uri_1
Definition: pugixml.cpp:7849
ast_func_translate
@ ast_func_translate
Definition: pugixml.cpp:7865
ast_func_round
@ ast_func_round
Definition: pugixml.cpp:7876
ast_func_number_1
@ ast_func_number_1
Definition: pugixml.cpp:7872
ast_func_string_length_1
@ ast_func_string_length_1
Definition: pugixml.cpp:7862
ast_func_starts_with
@ ast_func_starts_with
Definition: pugixml.cpp:7855
ast_func_false
@ ast_func_false
Definition: pugixml.cpp:7869
ast_func_local_name_0
@ ast_func_local_name_0
Definition: pugixml.cpp:7846
ast_func_id
@ ast_func_id
Definition: pugixml.cpp:7845
xpath_parser::parse_function_helper
xpath_ast_node * parse_function_helper(ast_type_t type0, ast_type_t type1, size_t argc, xpath_ast_node *args[2])
Definition: pugixml.cpp:9322

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().

## parse_function_helper()

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.

{
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]);
}

References alloc_node(), and throw_error().

Referenced by parse_function().

## parse_location_path()

xpath_ast_node* xpath_parser::parse_location_path | ( |  | ) |

inline

Definition at line 9847 of file pugixml.cpp.

{
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);
}
ast_step
@ ast_step
Definition: pugixml.cpp:7877
ast_step_root
@ ast_step_root
Definition: pugixml.cpp:7878
lexeme_t
lexeme_t
Definition: pugixml.cpp:7465
lex_multiply
@ lex_multiply
Definition: pugixml.cpp:7475
lex_double_slash
@ lex_double_slash
Definition: pugixml.cpp:7483
lex_axis_attribute
@ lex_axis_attribute
Definition: pugixml.cpp:7488
lex_slash
@ lex_slash
Definition: pugixml.cpp:7482
lex_dot
@ lex_dot
Definition: pugixml.cpp:7489
lex_string
@ lex_string
Definition: pugixml.cpp:7486
lex_double_dot
@ lex_double_dot
Definition: pugixml.cpp:7490
nodetest_type_node
@ nodetest_type_node
Definition: pugixml.cpp:7902
xpath_parser::parse_relative_location_path
xpath_ast_node * parse_relative_location_path(xpath_ast_node *set)
Definition: pugixml.cpp:9827

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().

## parse_node_test_type()

nodetest_t xpath_parser::parse_node_test_type | ( | const xpath_lexer_string & | name | ) |

inline

Definition at line 9512 of file pugixml.cpp.

{
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;
}
nodetest_none
@ nodetest_none
Definition: pugixml.cpp:7900
nodetest_type_text
@ nodetest_type_text
Definition: pugixml.cpp:7905
nodetest_type_comment
@ nodetest_type_comment
Definition: pugixml.cpp:7903
nodetest_type_pi
@ nodetest_type_pi
Definition: pugixml.cpp:7904

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().

## parse_path_or_unary_expression()

xpath_ast_node* xpath_parser::parse_path_or_unary_expression | ( |  | ) |

inline

Definition at line 9883 of file pugixml.cpp.

{
// 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();
}
xpath_lexer::contents
const xpath_lexer_string & contents() const
Definition: pugixml.cpp:7810
xpath_lexer::state
const char_t * state() const
Definition: pugixml.cpp:7526
ast_op_negate
@ ast_op_negate
Definition: pugixml.cpp:7834
lex_quoted_string
@ lex_quoted_string
Definition: pugixml.cpp:7480
lex_var_ref
@ lex_var_ref
Definition: pugixml.cpp:7477
lex_minus
@ lex_minus
Definition: pugixml.cpp:7474
lex_number
@ lex_number
Definition: pugixml.cpp:7481
lex_open_brace
@ lex_open_brace
Definition: pugixml.cpp:7478
PUGI__IS_CHARTYPE
#define PUGI__IS_CHARTYPE(c, ct)
Definition: pugixml.cpp:1195
ct_space
@ ct_space
Definition: pugixml.cpp:1130
xpath_parser::parse_filter_expression
xpath_ast_node * parse_filter_expression()
Definition: pugixml.cpp:9653
xpath_parser::parse_node_test_type
nodetest_t parse_node_test_type(const xpath_lexer_string &name)
Definition: pugixml.cpp:9512
xpath_parser::parse_location_path
xpath_ast_node * parse_location_path()
Definition: pugixml.cpp:9847

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().

## parse_primary_expression()

xpath_ast_node* xpath_parser::parse_primary_expression | ( |  | ) |

inline

Definition at line 9548 of file pugixml.cpp.

{
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;
}
}
xpath_ast_node::set_next
void set_next(xpath_ast_node *value)
Definition: pugixml.cpp:8551
ast_number_constant
@ ast_number_constant
Definition: pugixml.cpp:7840
ast_variable
@ ast_variable
Definition: pugixml.cpp:7841
ast_string_constant
@ ast_string_constant
Definition: pugixml.cpp:7839
lex_comma
@ lex_comma
Definition: pugixml.cpp:7487
lex_close_brace
@ lex_close_brace
Definition: pugixml.cpp:7479
get_variable_scratch
PUGI__FN xpath_variable * get_variable_scratch(char_t(&buffer)[32], xpath_variable_set *set, const char_t *begin, const char_t *end)
Definition: pugixml.cpp:7275
convert_string_to_number_scratch
PUGI__FN bool convert_string_to_number_scratch(char_t(&buffer)[32], const char_t *begin, const char_t *end, double *out_result)
Definition: pugixml.cpp:6981
xpath_lexer_string
Definition: pugixml.cpp:7496
xpath_parser::alloc_string
const char_t * alloc_string(const xpath_lexer_string &value)
Definition: pugixml.cpp:9304
xpath_parser::parse_function
xpath_ast_node * parse_function(const xpath_lexer_string &name, size_t argc, xpath_ast_node *args[2])
Definition: pugixml.cpp:9331
xpath_parser::_scratch
char_t _scratch[32]
Definition: pugixml.cpp:9268

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().

## parse_relative_location_path()

xpath_ast_node* xpath_parser::parse_relative_location_path | ( | xpath_ast_node * | set | ) |

inline

Definition at line 9827 of file pugixml.cpp.

{
xpath_ast_node* n = parse_step(set);
while (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash)
{
lexeme_t l = _lexer.current();
_lexer.next();
if (l == lex_double_slash)
n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0);
n = parse_step(n);
}
return n;
}
xpath_parser::parse_step
xpath_ast_node * parse_step(xpath_ast_node *set)
Definition: pugixml.cpp:9683

References _lexer, alloc_node(), ast_step, axis_descendant_or_self, xpath_lexer::current(), lex_double_slash, lex_slash, xpath_lexer::next(), nodetest_type_node, and parse_step().

Referenced by parse_location_path(), and parse_path_or_unary_expression().

## parse_step()

xpath_ast_node* xpath_parser::parse_step | ( | xpath_ast_node * | set | ) |

inline

Definition at line 9683 of file pugixml.cpp.

{
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;
}
xpath_ast_node::set_right
void set_right(xpath_ast_node *value)
Definition: pugixml.cpp:8556
ast_predicate
@ ast_predicate
Definition: pugixml.cpp:7836
lex_double_colon
@ lex_double_colon
Definition: pugixml.cpp:7491
nodetest_t
nodetest_t
Definition: pugixml.cpp:7899
nodetest_all
@ nodetest_all
Definition: pugixml.cpp:7907
nodetest_name
@ nodetest_name
Definition: pugixml.cpp:7901
nodetest_all_in_namespace
@ nodetest_all_in_namespace
Definition: pugixml.cpp:7908
nodetest_pi
@ nodetest_pi
Definition: pugixml.cpp:7906
axis_t
axis_t
Definition: pugixml.cpp:7882
xpath_parser::parse_axis_name
axis_t parse_axis_name(const xpath_lexer_string &name, bool &specified)
Definition: pugixml.cpp:9444

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::rettype(), xpath_ast_node::set_next(), xpath_ast_node::set_right(), and throw_error().

Referenced by parse_relative_location_path().

## throw_error()

void xpath_parser::throw_error | ( | const char * | message | ) |

inline

Definition at line 9274 of file pugixml.cpp.

{
_result->error = message;
_result->offset = _lexer.current_pos() - _query;
#ifdef PUGIXML_NO_EXCEPTIONS
longjmp(_error_handler, 1);
#else
throw xpath_exception(*_result);
#endif
}
xpath_lexer::current_pos
const char_t * current_pos() const
Definition: pugixml.cpp:7805

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().

## throw_error_oom()

void xpath_parser::throw_error_oom | ( |  | ) |

inline

Definition at line 9286 of file pugixml.cpp.

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

References throw_error().

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

## Member Data Documentation

## _alloc

xpath_allocator* xpath_parser::_alloc

Definition at line 9260 of file pugixml.cpp.

Referenced by alloc_node(), and alloc_string().

## _lexer

xpath_lexer xpath_parser::_lexer

Definition at line 9261 of file pugixml.cpp.

Referenced by parse(), parse_expression_rec(), parse_filter_expression(), parse_location_path(), parse_path_or_unary_expression(), parse_primary_expression(), parse_relative_location_path(), parse_step(), and throw_error().

## _query

const char_t* xpath_parser::_query

Definition at line 9263 of file pugixml.cpp.

Referenced by throw_error().

## _result

xpath_parse_result* xpath_parser::_result

Definition at line 9266 of file pugixml.cpp.

Referenced by throw_error().

## _scratch

char_t xpath_parser::_scratch[32]

Definition at line 9268 of file pugixml.cpp.

Referenced by parse_primary_expression().

## _variables

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:

- pugixml.cpp