def _nodesByLocationTerms(location, pre_keyword = nil)
if location !~ /^([a-z]*)\(([^)]*)\)(\.(.+))?$/
raise "invalid location: \"#{location}\""
end
keyword = $1
args = $2
rest = $4
keyword = pre_keyword if keyword == ''
if keyword.nil?
raise "cannot determine preceding keyword: \"#{location}\""
end
case keyword
when 'child', 'descendant', 'ancestor', 'psibling', 'fsibling',
'preceding', 'following'
_nodesByRelativeLocationTerm("#{keyword}(#{args})") do |node|
if rest.nil?
yield node
else
node._nodesByLocationTerms(rest, keyword) do |n|
yield n
end
end
end
when 'attr'
if args !~ Spec::Name
raise "invalid attribute name: '#{args}'"
end
attr = attributes[args]
value = (attr.nil? ? nil : Text.new(attr.nodeValue))
if rest.nil?
yield value
elsif !value.nil?
value._nodesByLocationTerms(rest) do |node|
yield node
end
end
when 'span', 'string'
raise "unsupported keyword: '#{keyword}'"
else
raise "unknown keyword: '#{keyword}'"
end
end