Wrap predicate AST nodes _around_ other nodes.
This means that "foo[1]" uses this AST:
(predicate (test nil "foo") (int 1))
Instead of this AST:
(test nil "foo" (int 1))
This makes it easier for the XPath evaluator to process predicates correctly.
This commit is contained in:
1 parent
24350fa457
commit
817a5e075b
5 files changed
+68
-62
No files matched your search
+36
-23
@@ -163,45 +163,58 @@ module Oga
|
||||
end
|
||||
|
||||
##
|
||||
# Processes a node test and optionally a predicate.
|
||||
# Processes a node test.
|
||||
#
|
||||
# @param [AST::Node] ast_node
|
||||
# @param [Oga::XML::NodeSet] context
|
||||
# @return [Oga::XML::NodeSet]
|
||||
#
|
||||
def on_test(ast_node, context)
|
||||
nodes = XML::NodeSet.new
|
||||
predicate = ast_node.children[2]
|
||||
xpath_index = 1
|
||||
nodes = XML::NodeSet.new
|
||||
|
||||
context.each do |xml_node|
|
||||
next unless node_matches?(xml_node, ast_node)
|
||||
nodes << xml_node if node_matches?(xml_node, ast_node)
|
||||
end
|
||||
|
||||
if predicate
|
||||
retval = with_node_set(context) do
|
||||
process(predicate, XML::NodeSet.new([xml_node]))
|
||||
return nodes
|
||||
end
|
||||
|
||||
##
|
||||
# Processes a predicate.
|
||||
#
|
||||
# @param [AST::Node] ast_node
|
||||
# @param [Oga::XML::NodeSet] context
|
||||
# @return [Oga::XML::NodeSet]
|
||||
#
|
||||
def on_predicate(ast_node, context)
|
||||
test, predicate = *ast_node
|
||||
|
||||
initial_nodes = process(test, context)
|
||||
final_nodes = XML::NodeSet.new
|
||||
xpath_index = 1
|
||||
|
||||
initial_nodes.each do |xml_node|
|
||||
retval = with_node_set(initial_nodes) do
|
||||
process(predicate, XML::NodeSet.new([xml_node]))
|
||||
end
|
||||
|
||||
# Numeric values are used as node set indexes.
|
||||
if retval.is_a?(Numeric)
|
||||
final_nodes << xml_node if retval.to_i == xpath_index
|
||||
|
||||
# Node sets, strings, booleans, etc
|
||||
elsif retval
|
||||
if retval.respond_to?(:empty?) and retval.empty?
|
||||
next
|
||||
end
|
||||
|
||||
# Numeric values are used as node set indexes.
|
||||
if retval.is_a?(Numeric)
|
||||
nodes << xml_node if retval.to_i == xpath_index
|
||||
|
||||
# Node sets, strings, booleans, etc
|
||||
elsif retval
|
||||
if retval.respond_to?(:empty?) and retval.empty?
|
||||
next
|
||||
end
|
||||
|
||||
nodes << xml_node
|
||||
end
|
||||
else
|
||||
nodes << xml_node
|
||||
final_nodes << xml_node
|
||||
end
|
||||
|
||||
xpath_index += 1
|
||||
end
|
||||
|
||||
return nodes
|
||||
return final_nodes
|
||||
end
|
||||
|
||||
##
|
||||
|
||||
@@ -40,9 +40,8 @@ rule
|
||||
;
|
||||
|
||||
expression_members
|
||||
: node_test_as_axis
|
||||
: expression_with_predicate
|
||||
| operator
|
||||
| axis
|
||||
| string
|
||||
| number
|
||||
| call
|
||||
@@ -51,9 +50,14 @@ rule
|
||||
| variable
|
||||
;
|
||||
|
||||
path_member
|
||||
expression_with_predicate
|
||||
: node_test_as_axis
|
||||
| node_test_as_axis predicate { s(:predicate, val[0], val[1]) }
|
||||
| axis
|
||||
| axis predicate { s(:predicate, val[0], val[1]) }
|
||||
|
||||
path_member
|
||||
: expression_with_predicate
|
||||
| call
|
||||
;
|
||||
|
||||
@@ -83,7 +87,7 @@ rule
|
||||
|
||||
node_test
|
||||
: node_name { s(:test, *val[0]) }
|
||||
| node_name predicate { s(:test, *val[0], val[1]) }
|
||||
#| node_name predicate { s(:predicate, s(:test, *val[0]), val[1]) }
|
||||
| type_test { val[0] }
|
||||
;
|
||||
|
||||
|
||||
Reference in new issue
Block a user