Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep AxisSpecifier ::= AxisName '::' | '@'? NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')' NameTest ::= '*' | NCName ':' '*' | QName AbbreviatedStep ::= '.' | '..'
| 8507 | // NameTest ::= '*' | NCName ':' '*' | QName |
| 8508 | // AbbreviatedStep ::= '.' | '..' |
| 8509 | xpath_ast_node* parse_step(xpath_ast_node* set) |
| 8510 | { |
| 8511 | if (set && set->rettype() != xpath_type_node_set) |
| 8512 | throw_error("Step has to be applied to node set"); |
| 8513 | |
| 8514 | bool axis_specified = false; |
| 8515 | axis_t axis = axis_child; // implied child axis |
| 8516 | |
| 8517 | if (_lexer.current() == lex_axis_attribute) |
| 8518 | { |
| 8519 | axis = axis_attribute; |
| 8520 | axis_specified = true; |
| 8521 | |
| 8522 | _lexer.next(); |
| 8523 | } |
| 8524 | else if (_lexer.current() == lex_dot) |
| 8525 | { |
| 8526 | _lexer.next(); |
| 8527 | |
| 8528 | return new (alloc_node()) xpath_ast_node(ast_step, set, axis_self, nodetest_type_node, 0); |
| 8529 | } |
| 8530 | else if (_lexer.current() == lex_double_dot) |
| 8531 | { |
| 8532 | _lexer.next(); |
| 8533 | |
| 8534 | return new (alloc_node()) xpath_ast_node(ast_step, set, axis_parent, nodetest_type_node, 0); |
| 8535 | } |
| 8536 | |
| 8537 | nodetest_t nt_type = nodetest_none; |
| 8538 | xpath_lexer_string nt_name; |
| 8539 | |
| 8540 | if (_lexer.current() == lex_string) |
| 8541 | { |
| 8542 | // node name test |
| 8543 | nt_name = _lexer.contents(); |
| 8544 | _lexer.next(); |
| 8545 | |
| 8546 | // was it an axis name? |
| 8547 | if (_lexer.current() == lex_double_colon) |
| 8548 | { |
| 8549 | // parse axis name |
| 8550 | if (axis_specified) throw_error("Two axis specifiers in one step"); |
| 8551 | |
| 8552 | axis = parse_axis_name(nt_name, axis_specified); |
| 8553 | |
| 8554 | if (!axis_specified) throw_error("Unknown axis"); |
| 8555 | |
| 8556 | // read actual node test |
| 8557 | _lexer.next(); |
| 8558 | |
| 8559 | if (_lexer.current() == lex_multiply) |
| 8560 | { |
| 8561 | nt_type = nodetest_all; |
| 8562 | nt_name = xpath_lexer_string(); |
| 8563 | _lexer.next(); |
| 8564 | } |
| 8565 | else if (_lexer.current() == lex_string) |
| 8566 | { |