← Back to Examples
Transform Patterns
RubyconceptualintermediateParslet-compatible
Transform DSL patterns demonstration
How the Code Works
This section explains how the parsing rules map to the format semantics.
Transform Class Structure
class Spring < Parsanol::Transform
rule(:stem => sequence(:branches)) {
{:stem => (branches + [{:branch => :leaf}])}
}
endEach season is a separate transform class: Different classes encapsulate different transformation behaviors.
Sequence Pattern
rule(:stem => sequence(:branches)) {
{:stem => (branches + [{:branch => :leaf}])}
}`sequence(:x)` matches arrays of simple values: `branches` is bound to the array content.
Subtree Pattern
rule(:stem => subtree(:branches)) {
new_branches = branches.map { |b| {:branch => [:leaf, :flower]} }
{:stem => new_branches}
}`subtree(:x)` matches any nested structure: Recursively applies to children.
Branch Pattern
class Fall < Parsanol::Transform
rule(:branch => sequence(:x)) {
x.each { |e| puts "Fruit!" if e == :flower }
x.each { |e| puts "Falling Leaves!" if e == :leaf }
{:branch => []}
}
endMatch and transform nested arrays: Iterate over array contents while transforming.
Composition
def do_seasons(tree)
[Spring, Summer, Fall, Winter].each do |season|
tree = season.new.apply(tree)
end
tree
endMultiple transforms are applied in sequence: Each transform passes its output to the next.
Composition
def do_seasons(tree)
[Spring, Summer, Fall, Winter].each do |season|
tree = season.new.apply(tree)
end
tree
endMultiple transforms are applied in sequence: Each transform passes its output to the next.
Source Code
Ruby
# frozen_string_literal: true
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
require "parsanol/parslet"
require "pp"
tree = { bud: { stem: [] } }
class Spring < Parsanol::Transform
rule(stem: sequence(:branches)) do
{ stem: (branches + [{ branch: :leaf }]) }
end
end
class Summer < Parsanol::Transform
rule(stem: subtree(:branches)) do
new_branches = branches.map { |_b| { branch: %i[leaf flower] } }
{ stem: new_branches }
end
end
class Fall < Parsanol::Transform
rule(branch: sequence(:x)) do
x.each do |e|
puts "Fruit!" if e == :flower
puts "Falling Leaves!" if e == :leaf
end
{ branch: [] }
end
end
class Winter < Parsanol::Transform
rule(stem: subtree(:x)) do
{ stem: [] }
end
end
def do_seasons(tree)
[Spring, Summer, Fall, Winter].each do |season|
p "And when #{season} comes"
tree = season.new.apply(tree)
pp tree
puts
end
tree
end
# What marvel of life!
tree = do_seasons(tree)
do_seasons(tree)