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  }

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  }

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  }

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"))
9470  return axis_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"))
9478  return axis_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"))
9494  return axis_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  }

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

◆ 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 
10032  op = binary_op_t::parse(_lexer);
10033  }
10034 
10035  return lhs;
10036  }

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.

9654  {
9656 
9657  while (_lexer.current() == lex_open_square_brace)
9658  {
9659  _lexer.next();
9660 
9661  xpath_ast_node* expr = parse_expression();
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  }

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  }

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)
9859  return parse_relative_location_path(n);
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 
9870  return parse_relative_location_path(n);
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
9874  return parse_relative_location_path(0);
9875  }

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  }

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 
9892  if (_lexer.current() == lex_var_ref || _lexer.current() == lex_open_brace ||
9894  _lexer.current() == lex_string)
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
9924  return parse_relative_location_path(n);
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  }

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.

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 
9575  if (_lexer.current() != lex_close_brace)
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 
9598  throw_error_oom();
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 
9620  if (_lexer.current() != lex_close_brace)
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  }

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 
9831  while (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash)
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  }

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?
9721  if (_lexer.current() == lex_double_colon)
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 
9754  if (_lexer.current() == lex_close_brace)
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  {
9766  if (_lexer.current() != lex_quoted_string)
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 
9773  if (_lexer.current() != lex_close_brace)
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 
9805  while (_lexer.current() == lex_open_square_brace)
9806  {
9807  _lexer.next();
9808 
9809  xpath_ast_node* expr = parse_expression();
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  }

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  }

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:
xpath_parser::_lexer
xpath_lexer _lexer
Definition: pugixml.cpp:9261
axis_descendant
@ axis_descendant
Definition: pugixml.cpp:7887
PUGI__IS_CHARTYPE
#define PUGI__IS_CHARTYPE(c, ct)
Definition: pugixml.cpp:1195
axis_ancestor_or_self
@ axis_ancestor_or_self
Definition: pugixml.cpp:7884
ast_func_translate
@ ast_func_translate
Definition: pugixml.cpp:7865
xpath_parser::alloc_string
const char_t * alloc_string(const xpath_lexer_string &value)
Definition: pugixml.cpp:9304
ast_func_last
@ ast_func_last
Definition: pugixml.cpp:7842
ast_func_starts_with
@ ast_func_starts_with
Definition: pugixml.cpp:7855
xpath_parser::_alloc
xpath_allocator * _alloc
Definition: pugixml.cpp:9260
ct_space
@ ct_space
Definition: pugixml.cpp:1130
xpath_parser::parse_path_or_unary_expression
xpath_ast_node * parse_path_or_unary_expression()
Definition: pugixml.cpp:9883
ast_number_constant
@ ast_number_constant
Definition: pugixml.cpp:7840
xpath_lexer_string::end
const char_t * end
Definition: pugixml.cpp:7498
xpath_lexer::next
void next()
Definition: pugixml.cpp:7531
lex_axis_attribute
@ lex_axis_attribute
Definition: pugixml.cpp:7488
ast_func_name_0
@ ast_func_name_0
Definition: pugixml.cpp:7850
lex_quoted_string
@ lex_quoted_string
Definition: pugixml.cpp:7480
lex_close_brace
@ lex_close_brace
Definition: pugixml.cpp:7479
lex_double_dot
@ lex_double_dot
Definition: pugixml.cpp:7490
ast_func_local_name_1
@ ast_func_local_name_1
Definition: pugixml.cpp:7847
xpath_lexer::contents
const xpath_lexer_string & contents() const
Definition: pugixml.cpp:7810
ast_func_id
@ ast_func_id
Definition: pugixml.cpp:7845
lex_dot
@ lex_dot
Definition: pugixml.cpp:7489
ast_filter_posinv
@ ast_filter_posinv
Definition: pugixml.cpp:7838
xpath_parser::throw_error
void throw_error(const char *message)
Definition: pugixml.cpp:9274
xpath_ast_node
Definition: pugixml.cpp:7918
ast_op_union
@ ast_op_union
Definition: pugixml.cpp:7835
lex_comma
@ lex_comma
Definition: pugixml.cpp:7487
ast_func_substring_after
@ ast_func_substring_after
Definition: pugixml.cpp:7858
xpath_ast_node::rettype
xpath_value_type rettype() const
Definition: pugixml.cpp:9252
ast_func_namespace_uri_1
@ ast_func_namespace_uri_1
Definition: pugixml.cpp:7849
ast_func_position
@ ast_func_position
Definition: pugixml.cpp:7843
axis_ancestor
@ axis_ancestor
Definition: pugixml.cpp:7883
xpath_lexer::current_pos
const char_t * current_pos() const
Definition: pugixml.cpp:7805
axis_preceding
@ axis_preceding
Definition: pugixml.cpp:7893
ast_op_negate
@ ast_op_negate
Definition: pugixml.cpp:7834
nodetest_none
@ nodetest_none
Definition: pugixml.cpp:7900
ast_func_local_name_0
@ ast_func_local_name_0
Definition: pugixml.cpp:7846
ast_func_string_1
@ ast_func_string_1
Definition: pugixml.cpp:7853
xpath_parser
Definition: pugixml.cpp:9258
axis_namespace
@ axis_namespace
Definition: pugixml.cpp:7891
nodetest_all
@ nodetest_all
Definition: pugixml.cpp:7907
ast_func_number_1
@ ast_func_number_1
Definition: pugixml.cpp:7872
nodetest_type_comment
@ nodetest_type_comment
Definition: pugixml.cpp:7903
ast_func_boolean
@ ast_func_boolean
Definition: pugixml.cpp:7866
lex_eof
@ lex_eof
Definition: pugixml.cpp:7492
xpath_parser::parse_primary_expression
xpath_ast_node * parse_primary_expression()
Definition: pugixml.cpp:9548
ast_func_concat
@ ast_func_concat
Definition: pugixml.cpp:7854
axis_following_sibling
@ axis_following_sibling
Definition: pugixml.cpp:7890
lex_number
@ lex_number
Definition: pugixml.cpp:7481
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
ast_func_number_0
@ ast_func_number_0
Definition: pugixml.cpp:7871
nodetest_type_node
@ nodetest_type_node
Definition: pugixml.cpp:7902
lex_double_colon
@ lex_double_colon
Definition: pugixml.cpp:7491
lex_open_brace
@ lex_open_brace
Definition: pugixml.cpp:7478
xpath_parser::parse_axis_name
axis_t parse_axis_name(const xpath_lexer_string &name, bool &specified)
Definition: pugixml.cpp:9444
ast_func_substring_3
@ ast_func_substring_3
Definition: pugixml.cpp:7860
ast_step
@ ast_step
Definition: pugixml.cpp:7877
xpath_parser::_query
const char_t * _query
Definition: pugixml.cpp:9263
ast_func_contains
@ ast_func_contains
Definition: pugixml.cpp:7856
lex_close_square_brace
@ lex_close_square_brace
Definition: pugixml.cpp:7485
nodetest_name
@ nodetest_name
Definition: pugixml.cpp:7901
ast_variable
@ ast_variable
Definition: pugixml.cpp:7841
ast_filter
@ ast_filter
Definition: pugixml.cpp:7837
xpath_lexer_string
Definition: pugixml.cpp:7495
axis_following
@ axis_following
Definition: pugixml.cpp:7889
xpath_parser::parse_expression
xpath_ast_node * parse_expression()
Definition: pugixml.cpp:10056
ast_func_lang
@ ast_func_lang
Definition: pugixml.cpp:7870
nodetest_type_text
@ nodetest_type_text
Definition: pugixml.cpp:7905
ast_func_true
@ ast_func_true
Definition: pugixml.cpp:7868
xpath_parser::parse_expression_rec
xpath_ast_node * parse_expression_rec(xpath_ast_node *lhs, int limit)
Definition: pugixml.cpp:10008
nodetest_type_pi
@ nodetest_type_pi
Definition: pugixml.cpp:7904
nodetest_t
nodetest_t
Definition: pugixml.cpp:7898
ast_func_substring_2
@ ast_func_substring_2
Definition: pugixml.cpp:7859
ast_func_substring_before
@ ast_func_substring_before
Definition: pugixml.cpp:7857
xpath_parser::_variables
xpath_variable_set * _variables
Definition: pugixml.cpp:9264
xpath_allocator::allocate_nothrow
void * allocate_nothrow(size_t size)
Definition: pugixml.cpp:6217
xpath_lexer_string::begin
const char_t * begin
Definition: pugixml.cpp:7497
xpath_lexer::current
lexeme_t current() const
Definition: pugixml.cpp:7800
ast_func_normalize_space_0
@ ast_func_normalize_space_0
Definition: pugixml.cpp:7863
axis_preceding_sibling
@ axis_preceding_sibling
Definition: pugixml.cpp:7894
xpath_parser::parse_relative_location_path
xpath_ast_node * parse_relative_location_path(xpath_ast_node *set)
Definition: pugixml.cpp:9827
xpath_parser::parse_node_test_type
nodetest_t parse_node_test_type(const xpath_lexer_string &name)
Definition: pugixml.cpp:9512
xpath_parser::_scratch
char_t _scratch[32]
Definition: pugixml.cpp:9268
axis_parent
@ axis_parent
Definition: pugixml.cpp:7892
ast_func_normalize_space_1
@ ast_func_normalize_space_1
Definition: pugixml.cpp:7864
xpath_parser::parse_filter_expression
xpath_ast_node * parse_filter_expression()
Definition: pugixml.cpp:9653
lex_multiply
@ lex_multiply
Definition: pugixml.cpp:7475
ast_func_not
@ ast_func_not
Definition: pugixml.cpp:7867
nodetest_pi
@ nodetest_pi
Definition: pugixml.cpp:7906
ast_func_count
@ ast_func_count
Definition: pugixml.cpp:7844
xpath_ast_node::set_next
void set_next(xpath_ast_node *value)
Definition: pugixml.cpp:8551
lex_string
@ lex_string
Definition: pugixml.cpp:7486
ast_func_floor
@ ast_func_floor
Definition: pugixml.cpp:7874
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
lex_minus
@ lex_minus
Definition: pugixml.cpp:7474
ast_func_namespace_uri_0
@ ast_func_namespace_uri_0
Definition: pugixml.cpp:7848
lex_open_square_brace
@ lex_open_square_brace
Definition: pugixml.cpp:7484
lexeme_t
lexeme_t
Definition: pugixml.cpp:7464
ast_func_false
@ ast_func_false
Definition: pugixml.cpp:7869
xpath_ast_node::is_posinv
bool is_posinv()
Definition: pugixml.cpp:9221
xpath_parser::alloc_node
void * alloc_node()
Definition: pugixml.cpp:9295
axis_t
axis_t
Definition: pugixml.cpp:7881
nodetest_all_in_namespace
@ nodetest_all_in_namespace
Definition: pugixml.cpp:7908
ast_func_name_1
@ ast_func_name_1
Definition: pugixml.cpp:7851
ast_func_string_0
@ ast_func_string_0
Definition: pugixml.cpp:7852
ast_func_string_length_0
@ ast_func_string_length_0
Definition: pugixml.cpp:7861
xpath_parser::throw_error_oom
void throw_error_oom()
Definition: pugixml.cpp:9286
ast_func_ceiling
@ ast_func_ceiling
Definition: pugixml.cpp:7875
ast_func_round
@ ast_func_round
Definition: pugixml.cpp:7876
axis_attribute
@ axis_attribute
Definition: pugixml.cpp:7885
ast_step_root
@ ast_step_root
Definition: pugixml.cpp:7878
lex_var_ref
@ lex_var_ref
Definition: pugixml.cpp:7477
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
xpath_parser::binary_op_t::parse
static binary_op_t parse(xpath_lexer &lexer)
Definition: pugixml.cpp:9956
ast_func_sum
@ ast_func_sum
Definition: pugixml.cpp:7873
lex_slash
@ lex_slash
Definition: pugixml.cpp:7482
axis_descendant_or_self
@ axis_descendant_or_self
Definition: pugixml.cpp:7888
ast_string_constant
@ ast_string_constant
Definition: pugixml.cpp:7839
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
ast_unknown
@ ast_unknown
Definition: pugixml.cpp:7820
xpath_ast_node::set_right
void set_right(xpath_ast_node *value)
Definition: pugixml.cpp:8556
xpath_parser::parse_location_path
xpath_ast_node * parse_location_path()
Definition: pugixml.cpp:9847
ast_func_string_length_1
@ ast_func_string_length_1
Definition: pugixml.cpp:7862
lex_double_slash
@ lex_double_slash
Definition: pugixml.cpp:7483
xpath_lexer::state
const char_t * state() const
Definition: pugixml.cpp:7526
axis_self
@ axis_self
Definition: pugixml.cpp:7895
xpath_parser::parse_step
xpath_ast_node * parse_step(xpath_ast_node *set)
Definition: pugixml.cpp:9683
xpath_parser::_result
xpath_parse_result * _result
Definition: pugixml.cpp:9266
ast_predicate
@ ast_predicate
Definition: pugixml.cpp:7836
axis_child
@ axis_child
Definition: pugixml.cpp:7886

Generated on Wed Apr 29 2020 19:41:30 for QuickFIX by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2001