PathExpr ::= LocationPath | FilterExpr | FilterExpr '/' RelativeLocationPath | FilterExpr '//' RelativeLocationPath
| 9336 | // | FilterExpr '/' RelativeLocationPath |
| 9337 | // | FilterExpr '//' RelativeLocationPath |
| 9338 | xpath_ast_node* parse_path_expression() |
| 9339 | { |
| 9340 | // Clarification. |
| 9341 | // PathExpr begins with either LocationPath or FilterExpr. |
| 9342 | // FilterExpr begins with PrimaryExpr |
| 9343 | // PrimaryExpr begins with '$' in case of it being a variable reference, |
| 9344 | // '(' in case of it being an expression, string literal, number constant or |
| 9345 | // function call. |
| 9346 | |
| 9347 | if (_lexer.current() == lex_var_ref || _lexer.current() == lex_open_brace || |
| 9348 | _lexer.current() == lex_quoted_string || _lexer.current() == lex_number || |
| 9349 | _lexer.current() == lex_string) |
| 9350 | { |
| 9351 | if (_lexer.current() == lex_string) |
| 9352 | { |
| 9353 | // This is either a function call, or not - if not, we shall proceed with location path |
| 9354 | const char_t* state = _lexer.state(); |
| 9355 | |
| 9356 | while (PUGI__IS_CHARTYPE(*state, ct_space)) ++state; |
| 9357 | |
| 9358 | if (*state != '(') return parse_location_path(); |
| 9359 | |
| 9360 | // This looks like a function call; however this still can be a node-test. Check it. |
| 9361 | if (parse_node_test_type(_lexer.contents()) != nodetest_none) return parse_location_path(); |
| 9362 | } |
| 9363 | |
| 9364 | xpath_ast_node* n = parse_filter_expression(); |
| 9365 | |
| 9366 | if (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) |
| 9367 | { |
| 9368 | lexeme_t l = _lexer.current(); |
| 9369 | _lexer.next(); |
| 9370 | |
| 9371 | if (l == lex_double_slash) |
| 9372 | { |
| 9373 | if (n->rettype() != xpath_type_node_set) throw_error("Step has to be applied to node set"); |
| 9374 | |
| 9375 | n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); |
| 9376 | } |
| 9377 | |
| 9378 | // select from location path |
| 9379 | return parse_relative_location_path(n); |
| 9380 | } |
| 9381 | |
| 9382 | return n; |
| 9383 | } |
| 9384 | else return parse_location_path(); |
| 9385 | } |
| 9386 | |
| 9387 | // UnionExpr ::= PathExpr | UnionExpr '|' PathExpr |
| 9388 | xpath_ast_node* parse_union_expression() |