Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep AxisSpecifier ::= AxisName '::' | '@'? NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')' NameTest ::= '*' | NCName ':' '*' | QName AbbreviatedStep ::= '.' | '..'
| 9138 | // NameTest ::= '*' | NCName ':' '*' | QName |
| 9139 | // AbbreviatedStep ::= '.' | '..' |
| 9140 | xpath_ast_node* parse_step(xpath_ast_node* set) |
| 9141 | { |
| 9142 | if (set && set->rettype() != xpath_type_node_set) |
| 9143 | throw_error("Step has to be applied to node set"); |
| 9144 | |
| 9145 | bool axis_specified = false; |
| 9146 | axis_t axis = axis_child; // implied child axis |
| 9147 | |
| 9148 | if (_lexer.current() == lex_axis_attribute) |
| 9149 | { |
| 9150 | axis = axis_attribute; |
| 9151 | axis_specified = true; |
| 9152 | |
| 9153 | _lexer.next(); |
| 9154 | } |
| 9155 | else if (_lexer.current() == lex_dot) |
| 9156 | { |
| 9157 | _lexer.next(); |
| 9158 | |
| 9159 | return new (alloc_node()) xpath_ast_node(ast_step, set, axis_self, nodetest_type_node, 0); |
| 9160 | } |
| 9161 | else if (_lexer.current() == lex_double_dot) |
| 9162 | { |
| 9163 | _lexer.next(); |
| 9164 | |
| 9165 | return new (alloc_node()) xpath_ast_node(ast_step, set, axis_parent, nodetest_type_node, 0); |
| 9166 | } |
| 9167 | |
| 9168 | nodetest_t nt_type = nodetest_none; |
| 9169 | xpath_lexer_string nt_name; |
| 9170 | |
| 9171 | if (_lexer.current() == lex_string) |
| 9172 | { |
| 9173 | // node name test |
| 9174 | nt_name = _lexer.contents(); |
| 9175 | _lexer.next(); |
| 9176 | |
| 9177 | // was it an axis name? |
| 9178 | if (_lexer.current() == lex_double_colon) |
| 9179 | { |
| 9180 | // parse axis name |
| 9181 | if (axis_specified) throw_error("Two axis specifiers in one step"); |
| 9182 | |
| 9183 | axis = parse_axis_name(nt_name, axis_specified); |
| 9184 | |
| 9185 | if (!axis_specified) throw_error("Unknown axis"); |
| 9186 | |
| 9187 | // read actual node test |
| 9188 | _lexer.next(); |
| 9189 | |
| 9190 | if (_lexer.current() == lex_multiply) |
| 9191 | { |
| 9192 | nt_type = nodetest_all; |
| 9193 | nt_name = xpath_lexer_string(); |
| 9194 | _lexer.next(); |
| 9195 | } |
| 9196 | else if (_lexer.current() == lex_string) |
| 9197 | { |