Classes | Public Member Functions | Static Public Member Functions | Public Attributes | List of all members
xpath_parser Struct Reference
Collaboration diagram for xpath_parser:
Collaboration graph
[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_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::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.

10061 : _alloc(alloc), _lexer(query), _query(query), _variables(variables), _result(result)
10062 {
10063 }
xpath_variable_set * _variables
Definition pugixml.cpp:9264
xpath_lexer _lexer
Definition pugixml.cpp:9261
xpath_parse_result * _result
Definition pugixml.cpp:9266
const char_t * _query
Definition pugixml.cpp:9263
xpath_allocator * _alloc
Definition pugixml.cpp:9260

Member Function Documentation

◆ alloc_node()

void * xpath_parser::alloc_node ( )
inline

◆ alloc_string()

const char_t * xpath_parser::alloc_string ( const xpath_lexer_string value)
inline

Definition at line 9304 of file pugixml.cpp.

9305 {
9306 if (value.begin)
9307 {
9308 size_t length = static_cast<size_t>(value.end - value.begin);
9309
9310 char_t* c = static_cast<char_t*>(_alloc->allocate_nothrow((length + 1) * sizeof(char_t)));
9311 if (!c) throw_error_oom();
9312 assert(c); // workaround for clang static analysis
9313
9314 memcpy(c, value.begin, length * sizeof(char_t));
9315 c[length] = 0;
9316
9317 return c;
9318 }
9319 else return 0;
9320 }
const char_t * begin
Definition pugixml.cpp:7497
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.

10066 {
10067 xpath_ast_node* result = parse_expression();
10068
10069 if (_lexer.current() != lex_eof)
10070 {
10071 // there are still unparsed tokens left, error
10072 throw_error("Incorrect query");
10073 }
10074
10075 return result;
10076 }
lexeme_t current() const
Definition pugixml.cpp:7800
@ lex_eof
Definition pugixml.cpp:7492
void throw_error(const char *message)
Definition pugixml.cpp:9274
xpath_ast_node * parse_expression()

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 
)
inlinestatic

Definition at line 10078 of file pugixml.cpp.

10079 {
10080 xpath_parser parser(query, variables, alloc, result);
10081
10082 #ifdef PUGIXML_NO_EXCEPTIONS
10083 int error = setjmp(parser._error_handler);
10084
10085 return (error == 0) ? parser.parse() : 0;
10086 #else
10087 return parser.parse();
10088 #endif
10089 }

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.

9445 {
9446 specified = true;
9447
9448 switch (name.begin[0])
9449 {
9450 case 'a':
9451 if (name == PUGIXML_TEXT("ancestor"))
9452 return axis_ancestor;
9453 else if (name == PUGIXML_TEXT("ancestor-or-self"))
9454 return axis_ancestor_or_self;
9455 else if (name == PUGIXML_TEXT("attribute"))
9456 return axis_attribute;
9457
9458 break;
9459
9460 case 'c':
9461 if (name == PUGIXML_TEXT("child"))
9462 return axis_child;
9463
9464 break;
9465
9466 case 'd':
9467 if (name == PUGIXML_TEXT("descendant"))
9468 return axis_descendant;
9469 else if (name == PUGIXML_TEXT("descendant-or-self"))
9471
9472 break;
9473
9474 case 'f':
9475 if (name == PUGIXML_TEXT("following"))
9476 return axis_following;
9477 else if (name == PUGIXML_TEXT("following-sibling"))
9479
9480 break;
9481
9482 case 'n':
9483 if (name == PUGIXML_TEXT("namespace"))
9484 return axis_namespace;
9485
9486 break;
9487
9488 case 'p':
9489 if (name == PUGIXML_TEXT("parent"))
9490 return axis_parent;
9491 else if (name == PUGIXML_TEXT("preceding"))
9492 return axis_preceding;
9493 else if (name == PUGIXML_TEXT("preceding-sibling"))
9495
9496 break;
9497
9498 case 's':
9499 if (name == PUGIXML_TEXT("self"))
9500 return axis_self;
9501
9502 break;
9503
9504 default:
9505 break;
9506 }
9507
9508 specified = false;
9509 return axis_child;
9510 }
@ axis_preceding
Definition pugixml.cpp:7893
@ axis_ancestor_or_self
Definition pugixml.cpp:7884
@ axis_attribute
Definition pugixml.cpp:7885
@ axis_following_sibling
Definition pugixml.cpp:7890
@ axis_child
Definition pugixml.cpp:7886
@ axis_descendant
Definition pugixml.cpp:7887
@ axis_descendant_or_self
Definition pugixml.cpp:7888
@ axis_self
Definition pugixml.cpp:7895
@ axis_following
Definition pugixml.cpp:7889
@ axis_ancestor
Definition pugixml.cpp:7883
@ axis_preceding_sibling
Definition pugixml.cpp:7894
@ axis_namespace
Definition pugixml.cpp:7891
@ 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.

10057 {
10059 }
xpath_ast_node * parse_path_or_unary_expression()
Definition pugixml.cpp:9883
xpath_ast_node * parse_expression_rec(xpath_ast_node *lhs, int limit)

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.

10009 {
10010 binary_op_t op = binary_op_t::parse(_lexer);
10011
10012 while (op.asttype != ast_unknown && op.precedence >= limit)
10013 {
10014 _lexer.next();
10015
10017
10018 binary_op_t nextop = binary_op_t::parse(_lexer);
10019
10020 while (nextop.asttype != ast_unknown && nextop.precedence > op.precedence)
10021 {
10022 rhs = parse_expression_rec(rhs, nextop.precedence);
10023
10024 nextop = binary_op_t::parse(_lexer);
10025 }
10026
10027 if (op.asttype == ast_op_union && (lhs->rettype() != xpath_type_node_set || rhs->rettype() != xpath_type_node_set))
10028 throw_error("Union operator has to be applied to node sets");
10029
10030 lhs = new (alloc_node()) xpath_ast_node(op.asttype, op.rettype, lhs, rhs);
10031
10033 }
10034
10035 return lhs;
10036 }
xpath_value_type rettype() const
Definition pugixml.cpp:9252
void next()
Definition pugixml.cpp:7531
@ ast_unknown
Definition pugixml.cpp:7820
@ ast_op_union
Definition pugixml.cpp:7835
static binary_op_t parse(xpath_lexer &lexer)
Definition pugixml.cpp:9956
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_expression_rec(), 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(), parse_expression_rec(), 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.

9654 {
9656
9658 {
9659 _lexer.next();
9660
9662
9663 if (n->rettype() != xpath_type_node_set) throw_error("Predicate has to be applied to node set");
9664
9665 bool posinv = expr->rettype() != xpath_type_number && expr->is_posinv();
9666
9667 n = new (alloc_node()) xpath_ast_node(posinv ? ast_filter_posinv : ast_filter, xpath_type_node_set, n, expr);
9668
9670 throw_error("Unmatched square brace");
9671
9672 _lexer.next();
9673 }
9674
9675 return n;
9676 }
@ ast_filter
Definition pugixml.cpp:7837
@ ast_filter_posinv
Definition pugixml.cpp:7838
@ lex_close_square_brace
Definition pugixml.cpp:7485
@ lex_open_square_brace
Definition pugixml.cpp:7484
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.

9332 {
9333 switch (name.begin[0])
9334 {
9335 case 'b':
9336 if (name == PUGIXML_TEXT("boolean") && argc == 1)
9337 return new (alloc_node()) xpath_ast_node(ast_func_boolean, xpath_type_boolean, args[0]);
9338
9339 break;
9340
9341 case 'c':
9342 if (name == PUGIXML_TEXT("count") && argc == 1)
9343 {
9344 if (args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set");
9345 return new (alloc_node()) xpath_ast_node(ast_func_count, xpath_type_number, args[0]);
9346 }
9347 else if (name == PUGIXML_TEXT("contains") && argc == 2)
9348 return new (alloc_node()) xpath_ast_node(ast_func_contains, xpath_type_boolean, args[0], args[1]);
9349 else if (name == PUGIXML_TEXT("concat") && argc >= 2)
9350 return new (alloc_node()) xpath_ast_node(ast_func_concat, xpath_type_string, args[0], args[1]);
9351 else if (name == PUGIXML_TEXT("ceiling") && argc == 1)
9352 return new (alloc_node()) xpath_ast_node(ast_func_ceiling, xpath_type_number, args[0]);
9353
9354 break;
9355
9356 case 'f':
9357 if (name == PUGIXML_TEXT("false") && argc == 0)
9358 return new (alloc_node()) xpath_ast_node(ast_func_false, xpath_type_boolean);
9359 else if (name == PUGIXML_TEXT("floor") && argc == 1)
9360 return new (alloc_node()) xpath_ast_node(ast_func_floor, xpath_type_number, args[0]);
9361
9362 break;
9363
9364 case 'i':
9365 if (name == PUGIXML_TEXT("id") && argc == 1)
9366 return new (alloc_node()) xpath_ast_node(ast_func_id, xpath_type_node_set, args[0]);
9367
9368 break;
9369
9370 case 'l':
9371 if (name == PUGIXML_TEXT("last") && argc == 0)
9372 return new (alloc_node()) xpath_ast_node(ast_func_last, xpath_type_number);
9373 else if (name == PUGIXML_TEXT("lang") && argc == 1)
9374 return new (alloc_node()) xpath_ast_node(ast_func_lang, xpath_type_boolean, args[0]);
9375 else if (name == PUGIXML_TEXT("local-name") && argc <= 1)
9377
9378 break;
9379
9380 case 'n':
9381 if (name == PUGIXML_TEXT("name") && argc <= 1)
9383 else if (name == PUGIXML_TEXT("namespace-uri") && argc <= 1)
9385 else if (name == PUGIXML_TEXT("normalize-space") && argc <= 1)
9386 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]);
9387 else if (name == PUGIXML_TEXT("not") && argc == 1)
9388 return new (alloc_node()) xpath_ast_node(ast_func_not, xpath_type_boolean, args[0]);
9389 else if (name == PUGIXML_TEXT("number") && argc <= 1)
9390 return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_number_0 : ast_func_number_1, xpath_type_number, args[0]);
9391
9392 break;
9393
9394 case 'p':
9395 if (name == PUGIXML_TEXT("position") && argc == 0)
9396 return new (alloc_node()) xpath_ast_node(ast_func_position, xpath_type_number);
9397
9398 break;
9399
9400 case 'r':
9401 if (name == PUGIXML_TEXT("round") && argc == 1)
9402 return new (alloc_node()) xpath_ast_node(ast_func_round, xpath_type_number, args[0]);
9403
9404 break;
9405
9406 case 's':
9407 if (name == PUGIXML_TEXT("string") && argc <= 1)
9408 return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_0 : ast_func_string_1, xpath_type_string, args[0]);
9409 else if (name == PUGIXML_TEXT("string-length") && argc <= 1)
9410 return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_length_0 : ast_func_string_length_1, xpath_type_number, args[0]);
9411 else if (name == PUGIXML_TEXT("starts-with") && argc == 2)
9412 return new (alloc_node()) xpath_ast_node(ast_func_starts_with, xpath_type_boolean, args[0], args[1]);
9413 else if (name == PUGIXML_TEXT("substring-before") && argc == 2)
9414 return new (alloc_node()) xpath_ast_node(ast_func_substring_before, xpath_type_string, args[0], args[1]);
9415 else if (name == PUGIXML_TEXT("substring-after") && argc == 2)
9416 return new (alloc_node()) xpath_ast_node(ast_func_substring_after, xpath_type_string, args[0], args[1]);
9417 else if (name == PUGIXML_TEXT("substring") && (argc == 2 || argc == 3))
9418 return new (alloc_node()) xpath_ast_node(argc == 2 ? ast_func_substring_2 : ast_func_substring_3, xpath_type_string, args[0], args[1]);
9419 else if (name == PUGIXML_TEXT("sum") && argc == 1)
9420 {
9421 if (args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set");
9422 return new (alloc_node()) xpath_ast_node(ast_func_sum, xpath_type_number, args[0]);
9423 }
9424
9425 break;
9426
9427 case 't':
9428 if (name == PUGIXML_TEXT("translate") && argc == 3)
9429 return new (alloc_node()) xpath_ast_node(ast_func_translate, xpath_type_string, args[0], args[1]);
9430 else if (name == PUGIXML_TEXT("true") && argc == 0)
9431 return new (alloc_node()) xpath_ast_node(ast_func_true, xpath_type_boolean);
9432
9433 break;
9434
9435 default:
9436 break;
9437 }
9438
9439 throw_error("Unrecognized function or wrong parameter count");
9440
9441 return 0;
9442 }
@ ast_func_substring_3
Definition pugixml.cpp:7860
@ ast_func_sum
Definition pugixml.cpp:7873
@ ast_func_name_1
Definition pugixml.cpp:7851
@ ast_func_floor
Definition pugixml.cpp:7874
@ ast_func_concat
Definition pugixml.cpp:7854
@ ast_func_name_0
Definition pugixml.cpp:7850
@ ast_func_not
Definition pugixml.cpp:7867
@ ast_func_string_1
Definition pugixml.cpp:7853
@ ast_func_string_0
Definition pugixml.cpp:7852
@ ast_func_number_0
Definition pugixml.cpp:7871
@ ast_func_substring_before
Definition pugixml.cpp:7857
@ ast_func_string_length_0
Definition pugixml.cpp:7861
@ ast_func_local_name_1
Definition pugixml.cpp:7847
@ ast_func_namespace_uri_0
Definition pugixml.cpp:7848
@ ast_func_lang
Definition pugixml.cpp:7870
@ ast_func_true
Definition pugixml.cpp:7868
@ ast_func_normalize_space_1
Definition pugixml.cpp:7864
@ ast_func_contains
Definition pugixml.cpp:7856
@ ast_func_substring_2
Definition pugixml.cpp:7859
@ ast_func_position
Definition pugixml.cpp:7843
@ ast_func_ceiling
Definition pugixml.cpp:7875
@ ast_func_last
Definition pugixml.cpp:7842
@ ast_func_normalize_space_0
Definition pugixml.cpp:7863
@ ast_func_boolean
Definition pugixml.cpp:7866
@ ast_func_count
Definition pugixml.cpp:7844
@ ast_func_substring_after
Definition pugixml.cpp:7858
@ ast_func_namespace_uri_1
Definition pugixml.cpp:7849
@ ast_func_translate
Definition pugixml.cpp:7865
@ ast_func_round
Definition pugixml.cpp:7876
@ ast_func_number_1
Definition pugixml.cpp:7872
@ ast_func_string_length_1
Definition pugixml.cpp:7862
@ ast_func_starts_with
Definition pugixml.cpp:7855
@ ast_func_false
Definition pugixml.cpp:7869
@ ast_func_local_name_0
Definition pugixml.cpp:7846
@ ast_func_id
Definition pugixml.cpp:7845
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.

9323 {
9324 assert(argc <= 1);
9325
9326 if (argc == 1 && args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set");
9327
9328 return new (alloc_node()) xpath_ast_node(argc == 0 ? type0 : type1, xpath_type_string, args[0]);
9329 }

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.

9848 {
9849 if (_lexer.current() == lex_slash)
9850 {
9851 _lexer.next();
9852
9853 xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step_root, xpath_type_node_set);
9854
9855 // relative location path can start from axis_attribute, dot, double_dot, multiply and string lexemes; any other lexeme means standalone root path
9856 lexeme_t l = _lexer.current();
9857
9858 if (l == lex_string || l == lex_axis_attribute || l == lex_dot || l == lex_double_dot || l == lex_multiply)
9860 else
9861 return n;
9862 }
9863 else if (_lexer.current() == lex_double_slash)
9864 {
9865 _lexer.next();
9866
9867 xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step_root, xpath_type_node_set);
9869
9871 }
9872
9873 // 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
9875 }
@ ast_step
Definition pugixml.cpp:7877
@ ast_step_root
Definition pugixml.cpp:7878
lexeme_t
Definition pugixml.cpp:7465
@ lex_multiply
Definition pugixml.cpp:7475
@ lex_double_slash
Definition pugixml.cpp:7483
@ lex_axis_attribute
Definition pugixml.cpp:7488
@ lex_slash
Definition pugixml.cpp:7482
@ lex_dot
Definition pugixml.cpp:7489
@ lex_string
Definition pugixml.cpp:7486
@ lex_double_dot
Definition pugixml.cpp:7490
@ nodetest_type_node
Definition pugixml.cpp:7902
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.

9513 {
9514 switch (name.begin[0])
9515 {
9516 case 'c':
9517 if (name == PUGIXML_TEXT("comment"))
9518 return nodetest_type_comment;
9519
9520 break;
9521
9522 case 'n':
9523 if (name == PUGIXML_TEXT("node"))
9524 return nodetest_type_node;
9525
9526 break;
9527
9528 case 'p':
9529 if (name == PUGIXML_TEXT("processing-instruction"))
9530 return nodetest_type_pi;
9531
9532 break;
9533
9534 case 't':
9535 if (name == PUGIXML_TEXT("text"))
9536 return nodetest_type_text;
9537
9538 break;
9539
9540 default:
9541 break;
9542 }
9543
9544 return nodetest_none;
9545 }
@ nodetest_none
Definition pugixml.cpp:7900
@ nodetest_type_text
Definition pugixml.cpp:7905
@ nodetest_type_comment
Definition pugixml.cpp:7903
@ 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.

9884 {
9885 // Clarification.
9886 // PathExpr begins with either LocationPath or FilterExpr.
9887 // FilterExpr begins with PrimaryExpr
9888 // PrimaryExpr begins with '$' in case of it being a variable reference,
9889 // '(' in case of it being an expression, string literal, number constant or
9890 // function call.
9891
9895 {
9896 if (_lexer.current() == lex_string)
9897 {
9898 // This is either a function call, or not - if not, we shall proceed with location path
9899 const char_t* state = _lexer.state();
9900
9901 while (PUGI__IS_CHARTYPE(*state, ct_space)) ++state;
9902
9903 if (*state != '(') return parse_location_path();
9904
9905 // This looks like a function call; however this still can be a node-test. Check it.
9907 }
9908
9910
9912 {
9913 lexeme_t l = _lexer.current();
9914 _lexer.next();
9915
9916 if (l == lex_double_slash)
9917 {
9918 if (n->rettype() != xpath_type_node_set) throw_error("Step has to be applied to node set");
9919
9921 }
9922
9923 // select from location path
9925 }
9926
9927 return n;
9928 }
9929 else if (_lexer.current() == lex_minus)
9930 {
9931 _lexer.next();
9932
9933 // precedence 7+ - only parses union expressions
9935
9936 return new (alloc_node()) xpath_ast_node(ast_op_negate, xpath_type_number, expr);
9937 }
9938 else
9939 return parse_location_path();
9940 }
const xpath_lexer_string & contents() const
Definition pugixml.cpp:7810
const char_t * state() const
Definition pugixml.cpp:7526
@ ast_op_negate
Definition pugixml.cpp:7834
@ lex_quoted_string
Definition pugixml.cpp:7480
@ lex_var_ref
Definition pugixml.cpp:7477
@ lex_minus
Definition pugixml.cpp:7474
@ lex_number
Definition pugixml.cpp:7481
@ lex_open_brace
Definition pugixml.cpp:7478
#define PUGI__IS_CHARTYPE(c, ct)
Definition pugixml.cpp:1195
@ ct_space
Definition pugixml.cpp:1130
xpath_ast_node * parse_filter_expression()
Definition pugixml.cpp:9653
nodetest_t parse_node_test_type(const xpath_lexer_string &name)
Definition pugixml.cpp:9512
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_path_or_unary_expression(), parse_relative_location_path(), PUGI__IS_CHARTYPE, xpath_ast_node::rettype(), xpath_lexer::state(), and throw_error().

Referenced by parse_expression(), parse_expression_rec(), and parse_path_or_unary_expression().

◆ parse_primary_expression()

xpath_ast_node * xpath_parser::parse_primary_expression ( )
inline

Definition at line 9548 of file pugixml.cpp.

9549 {
9550 switch (_lexer.current())
9551 {
9552 case lex_var_ref:
9553 {
9555
9556 if (!_variables)
9557 throw_error("Unknown variable: variable set is not provided");
9558
9559 xpath_variable* var = get_variable_scratch(_scratch, _variables, name.begin, name.end);
9560
9561 if (!var)
9562 throw_error("Unknown variable: variable set does not contain the given name");
9563
9564 _lexer.next();
9565
9566 return new (alloc_node()) xpath_ast_node(ast_variable, var->type(), var);
9567 }
9568
9569 case lex_open_brace:
9570 {
9571 _lexer.next();
9572
9574
9576 throw_error("Unmatched braces");
9577
9578 _lexer.next();
9579
9580 return n;
9581 }
9582
9583 case lex_quoted_string:
9584 {
9585 const char_t* value = alloc_string(_lexer.contents());
9586
9587 xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_string_constant, xpath_type_string, value);
9588 _lexer.next();
9589
9590 return n;
9591 }
9592
9593 case lex_number:
9594 {
9595 double value = 0;
9596
9599
9600 xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_number_constant, xpath_type_number, value);
9601 _lexer.next();
9602
9603 return n;
9604 }
9605
9606 case lex_string:
9607 {
9608 xpath_ast_node* args[2] = {0};
9609 size_t argc = 0;
9610
9611 xpath_lexer_string function = _lexer.contents();
9612 _lexer.next();
9613
9614 xpath_ast_node* last_arg = 0;
9615
9616 if (_lexer.current() != lex_open_brace)
9617 throw_error("Unrecognized function call");
9618 _lexer.next();
9619
9621 args[argc++] = parse_expression();
9622
9623 while (_lexer.current() != lex_close_brace)
9624 {
9625 if (_lexer.current() != lex_comma)
9626 throw_error("No comma between function arguments");
9627 _lexer.next();
9628
9630
9631 if (argc < 2) args[argc] = n;
9632 else last_arg->set_next(n);
9633
9634 argc++;
9635 last_arg = n;
9636 }
9637
9638 _lexer.next();
9639
9640 return parse_function(function, argc, args);
9641 }
9642
9643 default:
9644 throw_error("Unrecognizable primary expression");
9645
9646 return 0;
9647 }
9648 }
void set_next(xpath_ast_node *value)
Definition pugixml.cpp:8551
@ ast_number_constant
Definition pugixml.cpp:7840
@ ast_variable
Definition pugixml.cpp:7841
@ ast_string_constant
Definition pugixml.cpp:7839
@ lex_comma
Definition pugixml.cpp:7487
@ lex_close_brace
Definition pugixml.cpp:7479
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
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
const char_t * alloc_string(const xpath_lexer_string &value)
Definition pugixml.cpp:9304
xpath_ast_node * parse_function(const xpath_lexer_string &name, size_t argc, xpath_ast_node *args[2])
Definition pugixml.cpp:9331
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.

9828 {
9829 xpath_ast_node* n = parse_step(set);
9830
9832 {
9833 lexeme_t l = _lexer.current();
9834 _lexer.next();
9835
9836 if (l == lex_double_slash)
9838
9839 n = parse_step(n);
9840 }
9841
9842 return n;
9843 }
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.

9684 {
9685 if (set && set->rettype() != xpath_type_node_set)
9686 throw_error("Step has to be applied to node set");
9687
9688 bool axis_specified = false;
9689 axis_t axis = axis_child; // implied child axis
9690
9692 {
9693 axis = axis_attribute;
9694 axis_specified = true;
9695
9696 _lexer.next();
9697 }
9698 else if (_lexer.current() == lex_dot)
9699 {
9700 _lexer.next();
9701
9703 }
9704 else if (_lexer.current() == lex_double_dot)
9705 {
9706 _lexer.next();
9707
9709 }
9710
9711 nodetest_t nt_type = nodetest_none;
9712 xpath_lexer_string nt_name;
9713
9714 if (_lexer.current() == lex_string)
9715 {
9716 // node name test
9717 nt_name = _lexer.contents();
9718 _lexer.next();
9719
9720 // was it an axis name?
9722 {
9723 // parse axis name
9724 if (axis_specified) throw_error("Two axis specifiers in one step");
9725
9726 axis = parse_axis_name(nt_name, axis_specified);
9727
9728 if (!axis_specified) throw_error("Unknown axis");
9729
9730 // read actual node test
9731 _lexer.next();
9732
9733 if (_lexer.current() == lex_multiply)
9734 {
9735 nt_type = nodetest_all;
9736 nt_name = xpath_lexer_string();
9737 _lexer.next();
9738 }
9739 else if (_lexer.current() == lex_string)
9740 {
9741 nt_name = _lexer.contents();
9742 _lexer.next();
9743 }
9744 else throw_error("Unrecognized node test");
9745 }
9746
9747 if (nt_type == nodetest_none)
9748 {
9749 // node type test or processing-instruction
9750 if (_lexer.current() == lex_open_brace)
9751 {
9752 _lexer.next();
9753
9755 {
9756 _lexer.next();
9757
9758 nt_type = parse_node_test_type(nt_name);
9759
9760 if (nt_type == nodetest_none) throw_error("Unrecognized node type");
9761
9762 nt_name = xpath_lexer_string();
9763 }
9764 else if (nt_name == PUGIXML_TEXT("processing-instruction"))
9765 {
9767 throw_error("Only literals are allowed as arguments to processing-instruction()");
9768
9769 nt_type = nodetest_pi;
9770 nt_name = _lexer.contents();
9771 _lexer.next();
9772
9774 throw_error("Unmatched brace near processing-instruction()");
9775 _lexer.next();
9776 }
9777 else
9778 throw_error("Unmatched brace near node type test");
9779
9780 }
9781 // QName or NCName:*
9782 else
9783 {
9784 if (nt_name.end - nt_name.begin > 2 && nt_name.end[-2] == ':' && nt_name.end[-1] == '*') // NCName:*
9785 {
9786 nt_name.end--; // erase *
9787
9788 nt_type = nodetest_all_in_namespace;
9789 }
9790 else nt_type = nodetest_name;
9791 }
9792 }
9793 }
9794 else if (_lexer.current() == lex_multiply)
9795 {
9796 nt_type = nodetest_all;
9797 _lexer.next();
9798 }
9799 else throw_error("Unrecognized node test");
9800
9801 xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step, set, axis, nt_type, alloc_string(nt_name));
9802
9803 xpath_ast_node* last = 0;
9804
9806 {
9807 _lexer.next();
9808
9810
9811 xpath_ast_node* pred = new (alloc_node()) xpath_ast_node(ast_predicate, xpath_type_node_set, expr);
9812
9814 throw_error("Unmatched square brace");
9815 _lexer.next();
9816
9817 if (last) last->set_next(pred);
9818 else n->set_right(pred);
9819
9820 last = pred;
9821 }
9822
9823 return n;
9824 }
void set_right(xpath_ast_node *value)
Definition pugixml.cpp:8556
@ ast_predicate
Definition pugixml.cpp:7836
@ lex_double_colon
Definition pugixml.cpp:7491
nodetest_t
Definition pugixml.cpp:7899
@ nodetest_all
Definition pugixml.cpp:7907
@ nodetest_name
Definition pugixml.cpp:7901
@ nodetest_all_in_namespace
Definition pugixml.cpp:7908
@ nodetest_pi
Definition pugixml.cpp:7906
axis_t
Definition pugixml.cpp:7882
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.

9275 {
9276 _result->error = message;
9277 _result->offset = _lexer.current_pos() - _query;
9278
9279 #ifdef PUGIXML_NO_EXCEPTIONS
9280 longjmp(_error_handler, 1);
9281 #else
9282 throw xpath_exception(*_result);
9283 #endif
9284 }
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.

9287 {
9288 #ifdef PUGIXML_NO_EXCEPTIONS
9289 throw_error("Out of memory");
9290 #else
9291 throw std::bad_alloc();
9292 #endif
9293 }

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

◆ _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:

Generated on Mon Oct 14 2024 06:04:44 for QuickFIX by doxygen 1.9.8 written by Dimitri van Heesch, © 1997-2001