From b217aab2cb609d40e6af02ad7496dc9d1f34f0ac Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 18 Aug 2015 16:25:43 +0200 Subject: [PATCH] XPath compiler support for translate() --- lib/oga/ruby/node.rb | 9 ++++++++ lib/oga/xpath/compiler.rb | 45 ++++++++++++++++++++++++++++++++++++++ spec/oga/ruby/node_spec.rb | 10 +++++++++ 3 files changed, 64 insertions(+) diff --git a/lib/oga/ruby/node.rb b/lib/oga/ruby/node.rb index 1589973..8610ed7 100644 --- a/lib/oga/ruby/node.rb +++ b/lib/oga/ruby/node.rb @@ -44,6 +44,15 @@ module Oga @children end + ## + # Returns a "to_a" call node. + # + # @return [Oga::Ruby::Node] + # + def to_array + Node.new(:send, [self, :to_a]) + end + ## # Returns an assignment node. # diff --git a/lib/oga/xpath/compiler.rb b/lib/oga/xpath/compiler.rb index 73bdd28..2128560 100644 --- a/lib/oga/xpath/compiler.rb +++ b/lib/oga/xpath/compiler.rb @@ -1125,6 +1125,51 @@ module Oga end end + # @param [Oga::Ruby::Node] input + # @param [AST::Node] source + # @param [AST::Node] find + # @param [AST::Node] replace + # @return [Oga::Ruby::Node] + def on_call_translate(input, source, find, replace) + source_var = unique_literal(:source) + find_var = unique_literal(:find) + replace_var = unique_literal(:replace) + replaced_var = unique_literal(:replaced) + conversion = literal(Conversion) + + char = unique_literal(:char) + index = unique_literal(:index) + + source_var.assign(try_match_first_node(source, input)) + .followed_by do + replaced_var.assign(conversion.to_string(source_var)) + end + .followed_by do + find_var.assign(try_match_first_node(find, input)) + end + .followed_by do + find_var.assign(conversion.to_string(find_var).chars.to_array) + end + .followed_by do + replace_var.assign(try_match_first_node(replace, input)) + end + .followed_by do + replace_var.assign(conversion.to_string(replace_var).chars.to_array) + end + .followed_by do + find_var.each_with_index.add_block(char, index) do + replace_with = replace_var[index] + .if_true { replace_var[index] } + .else { string('') } + + replaced_var.assign(replaced_var.gsub(char, replace_with)) + end + end + .followed_by do + replaced_var + end + end + ## # Delegates type tests to specific handlers. # diff --git a/spec/oga/ruby/node_spec.rb b/spec/oga/ruby/node_spec.rb index 76d0740..d444967 100644 --- a/spec/oga/ruby/node_spec.rb +++ b/spec/oga/ruby/node_spec.rb @@ -17,6 +17,16 @@ describe Oga::Ruby::Node do end end + describe '#to_array' do + it 'returns a send Node' do + number = described_class.new(:lit, %w{10}) + node = number.to_array + + node.type.should == :send + node.to_a.should == [number, :to_a] + end + end + describe '#assign' do it 'returns an assignment Node' do left = described_class.new(:lit, %w{number})