Class: Sexp
Overview
unless defined $TESTING
Direct Known Subclasses
Constant Summary collapse
- @@array_types =
ZenTest FULL
[ :array, :args, ]
Instance Attribute Summary collapse
-
#accessors ⇒ Object
Named positional parameters.
Class Method Summary collapse
Instance Method Summary collapse
-
#==(obj) ⇒ Object
:nodoc:.
- #===(sexp) ⇒ Object
- #=~(pattern) ⇒ Object
-
#array_type? ⇒ Boolean
Returns true if the node_type is
array
orargs
. -
#each_of_type(t, &b) ⇒ Object
Enumeratates the sexp yielding to
b
when the node_type ==t
. -
#find_and_replace_all(from, to) ⇒ Object
Replaces all elements whose node_type is
from
withto
. - #gsub(pattern, repl) ⇒ Object
-
#initialize(*args) ⇒ Sexp
constructor
Create a new Sexp containing
args
. -
#inspect ⇒ Object
:nodoc:.
-
#method_missing(meth, *a, &b) ⇒ Object
Fancy-Schmancy method used to implement named positional accessors via
accessors
. -
#pretty_print(q) ⇒ Object
:nodoc:.
-
#sexp_body ⇒ Object
Returns the Sexp without the node_type.
-
#shift ⇒ Object
If run with debug, Sexp will raise if you shift on an empty Sexp.
-
#structure ⇒ Object
Returnes the bare bones structure of the sexp.
- #sub(pattern, repl) ⇒ Object
-
#to_a ⇒ Object
:nodoc:.
-
#to_s ⇒ Object
:nodoc:.
Constructor Details
#initialize(*args) ⇒ Sexp
Create a new Sexp containing args
.
21 22 23 24 |
# File 'lib/sexp.rb', line 21 def initialize(*args) @accessors = [] super(args) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(meth, *a, &b) ⇒ Object
Fancy-Schmancy method used to implement named positional accessors via accessors
.
Example:
class MyProcessor < SexpProcessor
def initialize
super
self.require_empty = false
self.sexp_accessors = {
:call => [:lhs, :name, :rhs]
}
...
end
def process_call(exp)
lhs = exp.lhs
name = exp.name
rhs = exp.rhs
...
end
end
150 151 152 153 154 155 |
# File 'lib/sexp.rb', line 150 def method_missing(meth, *a, &b) super unless @accessors.include? meth index = @accessors.index(meth) + 1 # skip type return self.at(index) end |
Instance Attribute Details
#accessors ⇒ Object
Named positional parameters. Use with SexpProcessor.require_empty=false.
16 17 18 |
# File 'lib/sexp.rb', line 16 def accessors @accessors end |
Class Method Details
Instance Method Details
#==(obj) ⇒ Object
:nodoc:
45 46 47 48 49 50 51 |
# File 'lib/sexp.rb', line 45 def ==(obj) # :nodoc: if obj.class == self.class then super else false end end |
#===(sexp) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/sexp.rb', line 53 def ===(sexp) return nil unless Sexp === sexp pattern = self # this is just for my brain return true if pattern == sexp sexp.each do |subset| return true if pattern === subset end return nil end |
#=~(pattern) ⇒ Object
66 67 68 |
# File 'lib/sexp.rb', line 66 def =~(pattern) return pattern === self end |
#array_type? ⇒ Boolean
Returns true if the node_type is array
or args
.
REFACTOR: to TypedSexp - we only care when we have units.
75 76 77 78 |
# File 'lib/sexp.rb', line 75 def array_type? type = self.first @@array_types.include? type end |
#each_of_type(t, &b) ⇒ Object
Enumeratates the sexp yielding to b
when the node_type == t
.
83 84 85 86 87 88 89 90 |
# File 'lib/sexp.rb', line 83 def each_of_type(t, &b) each do | elem | if Sexp === elem then elem.each_of_type(t, &b) b.call(elem) if elem.first == t end end end |
#find_and_replace_all(from, to) ⇒ Object
Replaces all elements whose node_type is from
with to
. Used only for the most trivial of rewrites.
96 97 98 99 100 101 102 103 104 |
# File 'lib/sexp.rb', line 96 def find_and_replace_all(from, to) each_with_index do | elem, index | if Sexp === elem then elem.find_and_replace_all(from, to) else self[index] = to if elem == from end end end |
#gsub(pattern, repl) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/sexp.rb', line 106 def gsub(pattern, repl) return repl if pattern == self new = self.map do |subset| case subset when Sexp then subset.gsub(pattern, repl) else subset end end return Sexp.from_array(new) end |
#inspect ⇒ Object
:nodoc:
121 122 123 124 |
# File 'lib/sexp.rb', line 121 def inspect # :nodoc: sexp_str = self.map {|x|x.inspect}.join(', ') return "s(#{sexp_str})" end |
#pretty_print(q) ⇒ Object
:nodoc:
157 158 159 160 161 |
# File 'lib/sexp.rb', line 157 def pretty_print(q) # :nodoc: q.group(1, 's(', ')') do q.seplist(self) {|v| q.pp v } end end |
#sexp_body ⇒ Object
Returns the Sexp without the node_type.
166 167 168 |
# File 'lib/sexp.rb', line 166 def sexp_body self[1..-1] end |
#shift ⇒ Object
If run with debug, Sexp will raise if you shift on an empty Sexp. Helps with debugging.
174 175 176 177 |
# File 'lib/sexp.rb', line 174 def shift raise "I'm empty" if self.empty? super end |
#structure ⇒ Object
Returnes the bare bones structure of the sexp. s(:a, :b, s(:c, :d), :e) => s(:a, s(:c))
183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/sexp.rb', line 183 def structure result = self.class.new if Array === self.first then result = self.first.structure else result << self.shift self.grep(Array).each do |subexp| result << subexp.structure end end result end |
#sub(pattern, repl) ⇒ Object
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/sexp.rb', line 196 def sub(pattern, repl) return repl.dup if pattern == self done = false new = self.map do |subset| if done then subset else case subset when Sexp then if pattern == subset then done = true repl.dup elsif pattern === subset then done = true subset.sub pattern, repl else subset end else subset end end end return Sexp.from_array(new) end |