ParseTree 1.3.7 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +18 -0
- data/Makefile +27 -11
- data/Manifest.txt +4 -1
- data/bin/parse_tree_abc +9 -2
- data/bin/parse_tree_deps +2 -1
- data/demo/printer.rb +20 -0
- data/lib/parse_tree.rb +5 -3
- data/lib/sexp.rb +257 -0
- data/lib/sexp_processor.rb +2 -179
- data/test/something.rb +6 -0
- data/test/test_parse_tree.rb +15 -0
- data/test/test_sexp.rb +298 -0
- data/test/test_sexp_processor.rb +0 -150
- metadata +49 -44
data/History.txt
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
*** 1.4.0 / 2005-10-15
|
2
|
+
|
3
|
+
+ 5 minor enhancements
|
4
|
+
+ Improved Makefile's install rule, uninstall, and added FILTER to all.
|
5
|
+
+ Fixed minor issues w/ Makefile.
|
6
|
+
+ Added -I=loadpath to parse_tree_abc.
|
7
|
+
+ Added *args support for methods.
|
8
|
+
+ Split out sexp to its own file.
|
9
|
+
+ 2 bug fixes
|
10
|
+
+ Fixed weird bug in parse_tree_deps where sort was failing on deps.
|
11
|
+
+ ! Fixed fatal bug in parse_tree.rb caused by safe_level fix in ruby 1.8.3.
|
12
|
+
|
13
|
+
*** 1.3.8 / 2005-09-27
|
14
|
+
|
15
|
+
+ 1 bug fix:
|
16
|
+
+ Our private version of struct METHOD went out of sync w/ latest ruby.
|
17
|
+
+ Only use this if you are on 1.8.3+.
|
18
|
+
|
1
19
|
*** 1.3.7 / 2005-07-13
|
2
20
|
|
3
21
|
+ 3 bug fixes:
|
data/Makefile
CHANGED
@@ -3,9 +3,27 @@ RUBY_DEBUG?=
|
|
3
3
|
RUBY_FLAGS?=-w -Ilib:bin:../../RubyInline/dev
|
4
4
|
RUBY_LIB?=$(shell $(RUBY) -rrbconfig -e 'include Config; print CONFIG["sitelibdir"]')
|
5
5
|
PREFIX?=/usr/local
|
6
|
+
FILTER?=
|
7
|
+
|
8
|
+
LIB_FILES= \
|
9
|
+
composite_sexp_processor.rb \
|
10
|
+
parse_tree.rb \
|
11
|
+
sexp.rb \
|
12
|
+
sexp_processor.rb \
|
13
|
+
$(END)
|
14
|
+
|
15
|
+
TEST_FILES= \
|
16
|
+
test_sexp_processor.rb \
|
17
|
+
$(END)
|
18
|
+
|
19
|
+
BIN_FILES= \
|
20
|
+
parse_tree_abc \
|
21
|
+
parse_tree_show \
|
22
|
+
parse_tree_deps \
|
23
|
+
$(END)
|
6
24
|
|
7
25
|
all test: FORCE
|
8
|
-
$(RUBY) $(RUBY_DEBUG) $(RUBY_FLAGS) test/test_all.rb
|
26
|
+
$(RUBY) $(RUBY_DEBUG) $(RUBY_FLAGS) test/test_all.rb $(FILTER)
|
9
27
|
|
10
28
|
# we only install test_sexp_processor.rb to help make ruby_to_c's
|
11
29
|
# subclass tests work.
|
@@ -14,19 +32,17 @@ docs:
|
|
14
32
|
rdoc -d -I png --main SexpProcessor -x test_\* -x something.rb
|
15
33
|
|
16
34
|
install:
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
cp -f bin/parse_tree_abc $(PREFIX)/bin
|
21
|
-
chmod 444 $(RUBY_LIB)/parse_tree.rb $(RUBY_LIB)/sexp_processor.rb $(RUBY_LIB)/composite_sexp_processor.rb $(RUBY_LIB)/test_sexp_processor.rb
|
22
|
-
chmod 555 $(PREFIX)/bin/parse_tree_show $(PREFIX)/bin/parse_tree_abc
|
35
|
+
cd lib && install -m 0444 $(LIB_FILES) $(RUBY_LIB)
|
36
|
+
cd test && install -m 0444 $(TEST_FILES) $(RUBY_LIB)
|
37
|
+
cd bin && install -m 0555 $(BIN_FILES) $(PREFIX)/bin
|
23
38
|
|
24
39
|
uninstall:
|
25
|
-
|
26
|
-
|
40
|
+
cd $(RUBY_LIB) && rm -f $(LIB_FILES) $(TEST_FILES)
|
41
|
+
cd $(PREFIX)/bin && rm -f $(BIN_FILES)
|
27
42
|
|
28
43
|
audit:
|
29
|
-
ZenTest
|
44
|
+
ZenTest -I=lib:test $(addprefix lib/,$(LIB_FILES)) test/test_all.rb
|
45
|
+
# test_composite_sexp_processor.rb test_sexp_processor.rb
|
30
46
|
|
31
47
|
clean:
|
32
48
|
-find . -name \*~ | xargs rm
|
@@ -36,6 +52,6 @@ demo:
|
|
36
52
|
echo 1+1 | $(RUBY) $(RUBY_FLAGS) ./bin/parse_tree_show -f
|
37
53
|
|
38
54
|
gem:
|
39
|
-
|
55
|
+
ruby ParseTree.gemspec
|
40
56
|
|
41
57
|
FORCE:
|
data/Manifest.txt
CHANGED
@@ -1,17 +1,20 @@
|
|
1
1
|
History.txt
|
2
2
|
Makefile
|
3
3
|
Manifest.txt
|
4
|
-
README.txt
|
5
4
|
ParseTree.gemspec
|
5
|
+
README.txt
|
6
6
|
bin/parse_tree_abc
|
7
7
|
bin/parse_tree_deps
|
8
8
|
bin/parse_tree_show
|
9
|
+
demo/printer.rb
|
9
10
|
lib/composite_sexp_processor.rb
|
10
11
|
lib/parse_tree.rb
|
12
|
+
lib/sexp.rb
|
11
13
|
lib/sexp_processor.rb
|
12
14
|
test/something.rb
|
13
15
|
test/test_all.rb
|
14
16
|
test/test_composite_sexp_processor.rb
|
15
17
|
test/test_parse_tree.rb
|
18
|
+
test/test_sexp.rb
|
16
19
|
test/test_sexp_processor.rb
|
17
20
|
validate.sh
|
data/bin/parse_tree_abc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#!/usr/local/bin/ruby
|
1
|
+
#!/usr/local/bin/ruby -ws
|
2
2
|
|
3
3
|
# ABC metric
|
4
4
|
#
|
@@ -6,9 +6,16 @@
|
|
6
6
|
#
|
7
7
|
# A simple way to measure the complexity of a function or method.
|
8
8
|
|
9
|
+
if defined? $I and String === $I then
|
10
|
+
$I.split(/:/).each do |dir|
|
11
|
+
$: << dir
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
9
15
|
PARSE_TREE_ABC=true
|
10
16
|
|
11
17
|
begin require 'rubygems' rescue LoadError end
|
18
|
+
require 'sexp'
|
12
19
|
require 'parse_tree'
|
13
20
|
require 'sexp_processor'
|
14
21
|
|
@@ -78,5 +85,5 @@ score.sort_by { |k,v| v }.reverse.each do |key,val|
|
|
78
85
|
tval += val
|
79
86
|
printf "%3d) %-50s = %2d + %2d + %2d = %6.2f\n", count, name, a, b, c, val
|
80
87
|
count += 1
|
81
|
-
end
|
88
|
+
end rescue nil
|
82
89
|
printf "%3d) %-50s = %2d + %2d + %2d = %6.2f\n", count, "Total", ta, tb, tc, tval
|
data/bin/parse_tree_deps
CHANGED
@@ -33,7 +33,7 @@ class DependencyAnalyzer < SexpProcessor
|
|
33
33
|
end
|
34
34
|
|
35
35
|
deps = analyzer.dependencies
|
36
|
-
deps.keys.
|
36
|
+
deps.keys.sort_by {|k| k.to_s}.each do |dep_to|
|
37
37
|
dep_from = deps[dep_to]
|
38
38
|
puts "#{dep_to}: #{dep_from.uniq.sort.join(", ")}"
|
39
39
|
end
|
@@ -57,5 +57,6 @@ end
|
|
57
57
|
if __FILE__ == $0 then
|
58
58
|
ARGV.each { |name| require name }
|
59
59
|
ObjectSpace.each_object(Module) { |klass| new_classes << klass }
|
60
|
+
new_classes.delete DependencyAnalyzer unless defined? $a
|
60
61
|
DependencyAnalyzer.process(*(new_classes - old_classes))
|
61
62
|
end
|
data/demo/printer.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
require 'rubygems'
|
3
|
+
require 'sexp_processor'
|
4
|
+
|
5
|
+
class QuickPrinter < SexpProcessor
|
6
|
+
def initialize
|
7
|
+
super
|
8
|
+
self.strict = false
|
9
|
+
self.auto_shift_type = true
|
10
|
+
end
|
11
|
+
def process_defn(exp)
|
12
|
+
name = exp.shift
|
13
|
+
args = process exp.shift
|
14
|
+
body = process exp.shift
|
15
|
+
puts " def #{name}"
|
16
|
+
return s(:defn, name, args, body)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
QuickPrinter.new.process(*ParseTree.new.parse_tree(QuickPrinter))
|
data/lib/parse_tree.rb
CHANGED
@@ -24,7 +24,7 @@ require 'inline'
|
|
24
24
|
|
25
25
|
class ParseTree
|
26
26
|
|
27
|
-
VERSION = '1.
|
27
|
+
VERSION = '1.4.0'
|
28
28
|
|
29
29
|
##
|
30
30
|
# Initializes a ParseTree instance. Includes newline nodes if
|
@@ -129,13 +129,14 @@ class ParseTree
|
|
129
129
|
# builder.add_compile_flags "-Wmissing-prototypes"
|
130
130
|
# builder.add_compile_flags "-Wsign-compare"
|
131
131
|
|
132
|
-
builder.prefix %
|
132
|
+
builder.prefix %{
|
133
133
|
#define nd_3rd u3.node
|
134
134
|
|
135
135
|
struct METHOD {
|
136
136
|
VALUE klass, rklass;
|
137
137
|
VALUE recv;
|
138
138
|
ID id, oid;
|
139
|
+
#{ RUBY_VERSION <= "1.8.2" ? "" : "int safe_level;" }
|
139
140
|
NODE *body;
|
140
141
|
};
|
141
142
|
|
@@ -586,7 +587,8 @@ again_no_block:
|
|
586
587
|
arg_count = node->nd_rest;
|
587
588
|
if (arg_count > 0) {
|
588
589
|
// *arg name
|
589
|
-
|
590
|
+
VALUE sym = rb_str_intern(rb_str_plus(rb_str_new2("*"), rb_str_new2(rb_id2name(locals[node->nd_rest + 1]))));
|
591
|
+
rb_ary_push(current, sym);
|
590
592
|
} else if (arg_count == -1) {
|
591
593
|
// nothing to do in this case, handled above
|
592
594
|
} else if (arg_count == -2) {
|
data/lib/sexp.rb
ADDED
@@ -0,0 +1,257 @@
|
|
1
|
+
##
|
2
|
+
# Sexps are the basic storage mechanism of SexpProcessor. Sexps have
|
3
|
+
# a +type+ (to be renamed +node_type+) which is the first element of
|
4
|
+
# the Sexp. The type is used by SexpProcessor to determine whom to
|
5
|
+
# dispatch the Sexp to for processing.
|
6
|
+
|
7
|
+
$TESTING ||= false # unless defined $TESTING
|
8
|
+
|
9
|
+
class Sexp < Array # ZenTest FULL
|
10
|
+
|
11
|
+
@@array_types = [ :array, :args, ]
|
12
|
+
|
13
|
+
##
|
14
|
+
# Named positional parameters.
|
15
|
+
# Use with +SexpProcessor.require_empty=false+.
|
16
|
+
attr_accessor :accessors
|
17
|
+
|
18
|
+
##
|
19
|
+
# Create a new Sexp containing +args+.
|
20
|
+
|
21
|
+
def initialize(*args)
|
22
|
+
@accessors = []
|
23
|
+
super(args)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.from_array(a)
|
27
|
+
ary = Array === a ? a : [a]
|
28
|
+
|
29
|
+
result = self.new
|
30
|
+
|
31
|
+
ary.each do |x|
|
32
|
+
case x
|
33
|
+
when Sexp
|
34
|
+
result << x
|
35
|
+
when Array
|
36
|
+
result << self.from_array(x)
|
37
|
+
else
|
38
|
+
result << x
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
result
|
43
|
+
end
|
44
|
+
|
45
|
+
def ==(obj) # :nodoc:
|
46
|
+
if obj.class == self.class then
|
47
|
+
super
|
48
|
+
else
|
49
|
+
false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def ===(sexp)
|
54
|
+
return nil unless Sexp === sexp
|
55
|
+
pattern = self # this is just for my brain
|
56
|
+
|
57
|
+
return true if pattern == sexp
|
58
|
+
|
59
|
+
sexp.each do |subset|
|
60
|
+
return true if pattern === subset
|
61
|
+
end
|
62
|
+
|
63
|
+
return nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def =~(pattern)
|
67
|
+
return pattern === self
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Returns true if the node_type is +array+ or +args+.
|
72
|
+
#
|
73
|
+
# REFACTOR: to TypedSexp - we only care when we have units.
|
74
|
+
|
75
|
+
def array_type?
|
76
|
+
type = self.first
|
77
|
+
@@array_types.include? type
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Enumeratates the sexp yielding to +b+ when the node_type == +t+.
|
82
|
+
|
83
|
+
def each_of_type(t, &b)
|
84
|
+
each do | elem |
|
85
|
+
if Sexp === elem then
|
86
|
+
elem.each_of_type(t, &b)
|
87
|
+
b.call(elem) if elem.first == t
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Replaces all elements whose node_type is +from+ with +to+. Used
|
94
|
+
# only for the most trivial of rewrites.
|
95
|
+
|
96
|
+
def find_and_replace_all(from, to)
|
97
|
+
each_with_index do | elem, index |
|
98
|
+
if Sexp === elem then
|
99
|
+
elem.find_and_replace_all(from, to)
|
100
|
+
else
|
101
|
+
self[index] = to if elem == from
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def gsub(pattern, repl)
|
107
|
+
return repl if pattern == self
|
108
|
+
|
109
|
+
new = self.map do |subset|
|
110
|
+
case subset
|
111
|
+
when Sexp then
|
112
|
+
subset.gsub(pattern, repl)
|
113
|
+
else
|
114
|
+
subset
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
return Sexp.from_array(new)
|
119
|
+
end
|
120
|
+
|
121
|
+
def inspect # :nodoc:
|
122
|
+
sexp_str = self.map {|x|x.inspect}.join(', ')
|
123
|
+
return "s(#{sexp_str})"
|
124
|
+
end
|
125
|
+
|
126
|
+
##
|
127
|
+
# Fancy-Schmancy method used to implement named positional accessors
|
128
|
+
# via +accessors+.
|
129
|
+
#
|
130
|
+
# Example:
|
131
|
+
#
|
132
|
+
# class MyProcessor < SexpProcessor
|
133
|
+
# def initialize
|
134
|
+
# super
|
135
|
+
# self.require_empty = false
|
136
|
+
# self.sexp_accessors = {
|
137
|
+
# :call => [:lhs, :name, :rhs]
|
138
|
+
# }
|
139
|
+
# ...
|
140
|
+
# end
|
141
|
+
#
|
142
|
+
# def process_call(exp)
|
143
|
+
# lhs = exp.lhs
|
144
|
+
# name = exp.name
|
145
|
+
# rhs = exp.rhs
|
146
|
+
# ...
|
147
|
+
# end
|
148
|
+
# end
|
149
|
+
|
150
|
+
def method_missing(meth, *a, &b)
|
151
|
+
super unless @accessors.include? meth
|
152
|
+
|
153
|
+
index = @accessors.index(meth) + 1 # skip type
|
154
|
+
return self.at(index)
|
155
|
+
end
|
156
|
+
|
157
|
+
def pretty_print(q) # :nodoc:
|
158
|
+
q.group(1, 's(', ')') do
|
159
|
+
q.seplist(self) {|v| q.pp v }
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
##
|
164
|
+
# Returns the Sexp without the node_type.
|
165
|
+
|
166
|
+
def sexp_body
|
167
|
+
self[1..-1]
|
168
|
+
end
|
169
|
+
|
170
|
+
##
|
171
|
+
# If run with debug, Sexp will raise if you shift on an empty
|
172
|
+
# Sexp. Helps with debugging.
|
173
|
+
|
174
|
+
def shift
|
175
|
+
raise "I'm empty" if self.empty?
|
176
|
+
super
|
177
|
+
end if $DEBUG or $TESTING
|
178
|
+
|
179
|
+
##
|
180
|
+
# Returnes the bare bones structure of the sexp.
|
181
|
+
# s(:a, :b, s(:c, :d), :e) => s(:a, s(:c))
|
182
|
+
|
183
|
+
def structure
|
184
|
+
result = self.class.new
|
185
|
+
if Array === self.first then
|
186
|
+
result = self.first.structure
|
187
|
+
else
|
188
|
+
result << self.shift
|
189
|
+
self.grep(Array).each do |subexp|
|
190
|
+
result << subexp.structure
|
191
|
+
end
|
192
|
+
end
|
193
|
+
result
|
194
|
+
end
|
195
|
+
|
196
|
+
def sub(pattern, repl)
|
197
|
+
return repl.dup if pattern == self
|
198
|
+
|
199
|
+
done = false
|
200
|
+
|
201
|
+
new = self.map do |subset|
|
202
|
+
if done then
|
203
|
+
subset
|
204
|
+
else
|
205
|
+
case subset
|
206
|
+
when Sexp then
|
207
|
+
if pattern == subset then
|
208
|
+
done = true
|
209
|
+
repl.dup
|
210
|
+
elsif pattern === subset then
|
211
|
+
done = true
|
212
|
+
subset.sub pattern, repl
|
213
|
+
else
|
214
|
+
subset
|
215
|
+
end
|
216
|
+
else
|
217
|
+
subset
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
return Sexp.from_array(new)
|
223
|
+
end
|
224
|
+
|
225
|
+
def to_a # :nodoc:
|
226
|
+
self.map { |o| Sexp === o ? o.to_a : o }
|
227
|
+
end
|
228
|
+
|
229
|
+
def to_s # :nodoc:
|
230
|
+
inspect
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
|
235
|
+
class SexpMatchSpecial < Sexp; end
|
236
|
+
|
237
|
+
class SexpAny < SexpMatchSpecial
|
238
|
+
def ===(o)
|
239
|
+
return Sexp === o
|
240
|
+
end
|
241
|
+
|
242
|
+
def inspect
|
243
|
+
"ANY"
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
module SexpMatchSpecials
|
248
|
+
def ANY(); return SexpAny.new; end
|
249
|
+
end
|
250
|
+
|
251
|
+
##
|
252
|
+
# This is just a stupid shortcut to make indentation much cleaner.
|
253
|
+
|
254
|
+
def s(*args)
|
255
|
+
Sexp.new(*args)
|
256
|
+
end
|
257
|
+
|
data/lib/sexp_processor.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
|
2
2
|
$TESTING = false unless defined? $TESTING
|
3
3
|
|
4
|
+
require 'sexp'
|
5
|
+
|
4
6
|
class Object
|
5
7
|
|
6
8
|
##
|
@@ -13,185 +15,6 @@ class Object
|
|
13
15
|
end
|
14
16
|
end
|
15
17
|
|
16
|
-
##
|
17
|
-
# Sexps are the basic storage mechanism of SexpProcessor. Sexps have
|
18
|
-
# a +type+ (to be renamed +node_type+) which is the first element of
|
19
|
-
# the Sexp. The type is used by SexpProcessor to determine whom to
|
20
|
-
# dispatch the Sexp to for processing.
|
21
|
-
|
22
|
-
class Sexp < Array # ZenTest FULL
|
23
|
-
|
24
|
-
@@array_types = [ :array, :args, ]
|
25
|
-
|
26
|
-
##
|
27
|
-
# Named positional parameters.
|
28
|
-
# Use with +SexpProcessor.require_empty=false+.
|
29
|
-
attr_accessor :accessors
|
30
|
-
|
31
|
-
##
|
32
|
-
# Create a new Sexp containing +args+.
|
33
|
-
|
34
|
-
def initialize(*args)
|
35
|
-
@accessors = []
|
36
|
-
super(args)
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.from_array(a)
|
40
|
-
ary = Array === a ? a : [a]
|
41
|
-
|
42
|
-
result = self.new
|
43
|
-
|
44
|
-
ary.each do |x|
|
45
|
-
case x
|
46
|
-
when Sexp
|
47
|
-
result << x
|
48
|
-
when Array
|
49
|
-
result << self.from_array(x)
|
50
|
-
else
|
51
|
-
result << x
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
result
|
56
|
-
end
|
57
|
-
|
58
|
-
##
|
59
|
-
# Returns true if the node_type is +array+ or +args+.
|
60
|
-
#
|
61
|
-
# REFACTOR: to TypedSexp - we only care when we have units.
|
62
|
-
|
63
|
-
def array_type?
|
64
|
-
type = self.first
|
65
|
-
@@array_types.include? type
|
66
|
-
end
|
67
|
-
|
68
|
-
##
|
69
|
-
# Enumeratates the sexp yielding to +b+ when the node_type == +t+.
|
70
|
-
|
71
|
-
def each_of_type(t, &b)
|
72
|
-
each do | elem |
|
73
|
-
if Sexp === elem then
|
74
|
-
elem.each_of_type(t, &b)
|
75
|
-
b.call(elem) if elem.first == t
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
##
|
81
|
-
# Replaces all elements whose node_type is +from+ with +to+. Used
|
82
|
-
# only for the most trivial of rewrites.
|
83
|
-
|
84
|
-
def find_and_replace_all(from, to)
|
85
|
-
each_with_index do | elem, index |
|
86
|
-
if Sexp === elem then
|
87
|
-
elem.find_and_replace_all(from, to)
|
88
|
-
else
|
89
|
-
self[index] = to if elem == from
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
##
|
95
|
-
# Fancy-Schmancy method used to implement named positional accessors
|
96
|
-
# via +accessors+.
|
97
|
-
#
|
98
|
-
# Example:
|
99
|
-
#
|
100
|
-
# class MyProcessor < SexpProcessor
|
101
|
-
# def initialize
|
102
|
-
# super
|
103
|
-
# self.require_empty = false
|
104
|
-
# self.sexp_accessors = {
|
105
|
-
# :call => [:lhs, :name, :rhs]
|
106
|
-
# }
|
107
|
-
# ...
|
108
|
-
# end
|
109
|
-
#
|
110
|
-
# def process_call(exp)
|
111
|
-
# lhs = exp.lhs
|
112
|
-
# name = exp.name
|
113
|
-
# rhs = exp.rhs
|
114
|
-
# ...
|
115
|
-
# end
|
116
|
-
# end
|
117
|
-
|
118
|
-
def method_missing(meth, *a, &b)
|
119
|
-
super unless @accessors.include? meth
|
120
|
-
|
121
|
-
index = @accessors.index(meth) + 1 # skip type
|
122
|
-
return self.at(index)
|
123
|
-
end
|
124
|
-
|
125
|
-
##
|
126
|
-
# Returns the Sexp without the node_type.
|
127
|
-
|
128
|
-
def sexp_body
|
129
|
-
self[1..-1]
|
130
|
-
end
|
131
|
-
|
132
|
-
##
|
133
|
-
# Returnes the bare bones structure of the sexp.
|
134
|
-
# s(:a, :b, s(:c, :d), :e) => s(:a, s(:c))
|
135
|
-
|
136
|
-
def structure
|
137
|
-
result = self.class.new
|
138
|
-
if Array === self.first then
|
139
|
-
result = self.first.structure
|
140
|
-
else
|
141
|
-
result << self.shift
|
142
|
-
self.grep(Array).each do |subexp|
|
143
|
-
result << subexp.structure
|
144
|
-
end
|
145
|
-
end
|
146
|
-
result
|
147
|
-
end
|
148
|
-
|
149
|
-
def ==(obj) # :nodoc:
|
150
|
-
case obj
|
151
|
-
when Sexp
|
152
|
-
super
|
153
|
-
else
|
154
|
-
false
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
def to_a # :nodoc:
|
159
|
-
self.map { |o| Sexp === o ? o.to_a : o }
|
160
|
-
end
|
161
|
-
|
162
|
-
def inspect # :nodoc:
|
163
|
-
sexp_str = self.map {|x|x.inspect}.join(', ')
|
164
|
-
return "s(#{sexp_str})"
|
165
|
-
end
|
166
|
-
|
167
|
-
def pretty_print(q) # :nodoc:
|
168
|
-
q.group(1, 's(', ')') do
|
169
|
-
q.seplist(self) {|v| q.pp v }
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def to_s # :nodoc:
|
174
|
-
inspect
|
175
|
-
end
|
176
|
-
|
177
|
-
##
|
178
|
-
# If run with debug, Sexp will raise if you shift on an empty
|
179
|
-
# Sexp. Helps with debugging.
|
180
|
-
|
181
|
-
def shift
|
182
|
-
raise "I'm empty" if self.empty?
|
183
|
-
super
|
184
|
-
end if $DEBUG or $TESTING
|
185
|
-
|
186
|
-
end
|
187
|
-
|
188
|
-
##
|
189
|
-
# This is just a stupid shortcut to make indentation much cleaner.
|
190
|
-
|
191
|
-
def s(*args)
|
192
|
-
Sexp.new(*args)
|
193
|
-
end
|
194
|
-
|
195
18
|
##
|
196
19
|
# SexpProcessor base exception class.
|
197
20
|
|
data/test/something.rb
CHANGED
data/test/test_parse_tree.rb
CHANGED
@@ -177,6 +177,21 @@ class TestParseTree < Test::Unit::TestCase
|
|
177
177
|
[:call, [:lit, 3], :downto, [:array, [:lit, 1]]],
|
178
178
|
nil,
|
179
179
|
[:fcall, :puts, [:array, [:str, "hello"]]]]]]]
|
180
|
+
@@opt_args = [:defn, :opt_args,
|
181
|
+
[:scope,
|
182
|
+
[:block,
|
183
|
+
[:args, :arg1, :arg2, :"*args", [:block, [:lasgn, :arg2, [:lit, 42]]]],
|
184
|
+
[:lasgn, :arg3,
|
185
|
+
[:call,
|
186
|
+
[:call,
|
187
|
+
[:lvar, :arg1],
|
188
|
+
:*,
|
189
|
+
[:array, [:lvar, :arg2]]],
|
190
|
+
:*,
|
191
|
+
[:array, [:lit, 7]]]],
|
192
|
+
[:fcall, :puts, [:array, [:call, [:lvar, :arg3], :to_s]]],
|
193
|
+
[:return,
|
194
|
+
[:str, "foo"]]]]]
|
180
195
|
@@multi_args = [:defn, :multi_args,
|
181
196
|
[:scope,
|
182
197
|
[:block,
|
data/test/test_sexp.rb
ADDED
@@ -0,0 +1,298 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
$TESTING = true
|
4
|
+
|
5
|
+
require 'test/unit' if $0 == __FILE__ unless defined? $ZENTEST and $ZENTEST
|
6
|
+
require 'test/unit/testcase'
|
7
|
+
require 'sexp_processor'
|
8
|
+
require 'stringio'
|
9
|
+
require 'pp'
|
10
|
+
|
11
|
+
class SexpTestCase < Test::Unit::TestCase
|
12
|
+
|
13
|
+
# KEY for regex tests
|
14
|
+
# :a == no change
|
15
|
+
# :b == will change (but sometimes ONLY once)
|
16
|
+
# :c == change to
|
17
|
+
|
18
|
+
include SexpMatchSpecials
|
19
|
+
|
20
|
+
def util_equals3(x, y)
|
21
|
+
result = x === y
|
22
|
+
assert_not_nil result, "#{x.inspect} does not === #{y.inspect}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def setup
|
26
|
+
@any = ANY()
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_stupid
|
30
|
+
# shuts up test/unit
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class TestSexp < SexpTestCase # ZenTest FULL
|
35
|
+
|
36
|
+
def util_pretty_print(expect, input)
|
37
|
+
io = StringIO.new
|
38
|
+
PP.pp(input, io)
|
39
|
+
io.rewind
|
40
|
+
assert_equal(expect, io.read.chomp)
|
41
|
+
end
|
42
|
+
|
43
|
+
def setup
|
44
|
+
super
|
45
|
+
@sexp_class = Object.const_get(self.class.name[4..-1])
|
46
|
+
@processor = SexpProcessor.new
|
47
|
+
@sexp = @sexp_class.new(1, 2, 3)
|
48
|
+
@basic_sexp = s(:lasgn, :var, s(:lit, 42))
|
49
|
+
@re = s(:lit, 42)
|
50
|
+
@bad1 = s(:lit, 24)
|
51
|
+
@bad1 = s(:blah, 42)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_class_from_array
|
55
|
+
# raise NotImplementedError, 'Need to write test_class_from_array'
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_class_index
|
59
|
+
# raise NotImplementedError, 'Need to write test_class_index'
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_accessors; end # handled
|
63
|
+
|
64
|
+
def test_accessors_equals
|
65
|
+
a = s(:call, s(:lit, 1), "func", s(:array, s(:lit, 2)))
|
66
|
+
a.accessors = [:lhs, :name, :rhs]
|
67
|
+
|
68
|
+
assert_equal a.accessors, [:lhs, :name, :rhs]
|
69
|
+
|
70
|
+
assert_equal s(:lit, 1), a.lhs
|
71
|
+
assert_equal "func", a.name
|
72
|
+
assert_equal s(:array, s(:lit, 2)), a.rhs
|
73
|
+
|
74
|
+
a.accessors = []
|
75
|
+
|
76
|
+
assert_raises NoMethodError do
|
77
|
+
a.lhs
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_array_type_eh
|
82
|
+
assert_equal false, @sexp.array_type?
|
83
|
+
@sexp.unshift :array
|
84
|
+
assert_equal true, @sexp.array_type?
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_each_of_type
|
88
|
+
# TODO: huh... this tests fails if top level sexp :b is removed
|
89
|
+
@sexp = s(:b, s(:a, s(:b, s(:a), :a, s(:b, :a), s(:b, s(:a)))))
|
90
|
+
count = 0
|
91
|
+
@sexp.each_of_type(:a) do |exp|
|
92
|
+
count += 1
|
93
|
+
end
|
94
|
+
assert_equal(3, count, "must find 3 a's in #{@sexp.inspect}")
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_equals2_array
|
98
|
+
# can't use assert_equals because it uses array as receiver
|
99
|
+
assert_not_equal(@sexp, [1, 2, 3],
|
100
|
+
"Sexp must not be equal to equivalent array")
|
101
|
+
# both directions just in case
|
102
|
+
# HACK - this seems to be a bug in ruby as far as I'm concerned
|
103
|
+
# assert_not_equal([1, 2, 3], @sexp,
|
104
|
+
# "Sexp must not be equal to equivalent array")
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_equals2_not_body
|
108
|
+
sexp2 = s(1, 2, 5)
|
109
|
+
assert_not_equal(@sexp, sexp2)
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_equals2_sexp
|
113
|
+
sexp2 = s(1, 2, 3)
|
114
|
+
if @sexp.class == Sexp then
|
115
|
+
# sexp3 = t(1, 2, 3, Type.str)
|
116
|
+
# case @sexp
|
117
|
+
# when TypedSexp
|
118
|
+
# assert_equal(@sexp, sexp3)
|
119
|
+
# assert_not_equal(@sexp, sexp2)
|
120
|
+
# when Sexp
|
121
|
+
assert_equal(@sexp, sexp2)
|
122
|
+
# assert_not_equal(@sexp, sexp3)
|
123
|
+
else
|
124
|
+
assert_not_equal(@sexp, sexp2)
|
125
|
+
# else
|
126
|
+
# flunk "unknown type"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_equals3_any
|
131
|
+
util_equals3 @any, s()
|
132
|
+
util_equals3 @any, s(:a)
|
133
|
+
util_equals3 @any, s(:a, :b, s(:c))
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_equals3_full_match
|
137
|
+
util_equals3 s(), s() # 0
|
138
|
+
util_equals3 s(:blah), s(:blah) # 1
|
139
|
+
util_equals3 s(:a, :b), s(:a, :b) # 2
|
140
|
+
util_equals3 @basic_sexp, @basic_sexp.dup # deeper structure
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_equals3_mismatch
|
144
|
+
assert_nil s() === s(:a)
|
145
|
+
assert_nil s(:a) === s()
|
146
|
+
assert_nil s(:blah1) === s(:blah2)
|
147
|
+
assert_nil s(:a) === s(:a, :b)
|
148
|
+
assert_nil s(:a, :b) === s(:a)
|
149
|
+
assert_nil s(:a1, :b) === s(:a2, :b)
|
150
|
+
assert_nil s(:a, :b1) === s(:a, :b2)
|
151
|
+
assert_nil @basic_sexp === @basic_sexp.dup.push(42)
|
152
|
+
assert_nil @basic_sexp.dup.push(42) === @basic_sexp
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_equals3_subset_match
|
156
|
+
util_equals3 s(:a), s(s(:a), s(:b)) # left
|
157
|
+
util_equals3 s(:a), s(:blah, s(:a ), s(:b)) # mid 1
|
158
|
+
util_equals3 s(:a, 1), s(:blah, s(:a, 1), s(:b)) # mid 2
|
159
|
+
util_equals3 @basic_sexp, s(:blah, @basic_sexp.dup, s(:b)) # mid deeper
|
160
|
+
util_equals3 @basic_sexp, s(@basic_sexp.dup, s(:a), s(:b)) # left deeper
|
161
|
+
|
162
|
+
util_equals3 s(:a), s(:blah, s(:blah, s(:a))) # left deeper
|
163
|
+
end
|
164
|
+
|
165
|
+
# def test_equalstilde_any
|
166
|
+
# result = @basic_sexp =~ s(:lit, ANY())
|
167
|
+
# p result
|
168
|
+
# assert result
|
169
|
+
# end
|
170
|
+
|
171
|
+
def test_equalstilde_fancy
|
172
|
+
assert_nil s(:b) =~ s(:a, s(:b), :c)
|
173
|
+
assert_not_nil s(:a, s(:b), :c) =~ s(:b)
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_equalstilde_plain
|
177
|
+
result = @basic_sexp =~ @re
|
178
|
+
assert result
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_find_and_replace_all
|
182
|
+
@sexp = s(:a, s(:b, s(:a), s(:b), s(:b, s(:a))))
|
183
|
+
expected = s(:a, s(:a, s(:a), s(:a), s(:a, s(:a))))
|
184
|
+
|
185
|
+
@sexp.find_and_replace_all(:b, :a)
|
186
|
+
|
187
|
+
assert_equal(expected, @sexp)
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_gsub
|
191
|
+
assert_equal s(:c), s().gsub(s(), s(:c))
|
192
|
+
assert_equal s(:c), s(:b).gsub(s(:b), s(:c))
|
193
|
+
assert_equal s(:a), s(:a).gsub(s(:b), s(:c))
|
194
|
+
assert_equal s(:a, s(:c)), s(:a, s(:b)).gsub(s(:b), s(:c))
|
195
|
+
|
196
|
+
assert_equal(s(:a, s(:c), s(:c)),
|
197
|
+
s(:a, s(:b), s(:b)).gsub(s(:b), s(:c)))
|
198
|
+
assert_equal(s(:a, s(:c), s(:a, s(:c))),
|
199
|
+
s(:a, s(:b), s(:a, s(:b))).gsub(s(:b), s(:c)))
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_inspect
|
203
|
+
k = @sexp_class
|
204
|
+
n = k.name[0].chr.downcase
|
205
|
+
assert_equal("#{n}()",
|
206
|
+
k.new().inspect)
|
207
|
+
assert_equal("#{n}(:a)",
|
208
|
+
k.new(:a).inspect)
|
209
|
+
assert_equal("#{n}(:a, :b)",
|
210
|
+
k.new(:a, :b).inspect)
|
211
|
+
assert_equal("#{n}(:a, #{n}(:b))",
|
212
|
+
k.new(:a, k.new(:b)).inspect)
|
213
|
+
end
|
214
|
+
|
215
|
+
def test_method_missing
|
216
|
+
assert_raises NoMethodError do
|
217
|
+
@sexp.no_such_method
|
218
|
+
end
|
219
|
+
|
220
|
+
@sexp.accessors = [:its_a_method_now]
|
221
|
+
|
222
|
+
assert_nothing_raised do
|
223
|
+
assert_equal 2, @sexp.its_a_method_now
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def test_pretty_print
|
228
|
+
util_pretty_print("s()",
|
229
|
+
s())
|
230
|
+
util_pretty_print("s(:a)",
|
231
|
+
s(:a))
|
232
|
+
util_pretty_print("s(:a, :b)",
|
233
|
+
s(:a, :b))
|
234
|
+
util_pretty_print("s(:a, s(:b))",
|
235
|
+
s(:a, s(:b)))
|
236
|
+
end
|
237
|
+
|
238
|
+
def test_sexp_body
|
239
|
+
assert_equal [2, 3], @sexp.sexp_body
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_shift
|
243
|
+
assert_equal(1, @sexp.shift)
|
244
|
+
assert_equal(2, @sexp.shift)
|
245
|
+
assert_equal(3, @sexp.shift)
|
246
|
+
|
247
|
+
assert_raise(RuntimeError) do
|
248
|
+
@sexp.shift
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def test_structure
|
253
|
+
@sexp = s(:a, 1, 2, s(:b, 3, 4), 5, 6)
|
254
|
+
expected = s(:a, s(:b))
|
255
|
+
|
256
|
+
assert_equal(expected, @sexp.structure)
|
257
|
+
end
|
258
|
+
|
259
|
+
def test_sub
|
260
|
+
assert_equal s(:c), s().sub(s(), s(:c))
|
261
|
+
assert_equal s(:c), s(:b).sub(s(:b), s(:c))
|
262
|
+
assert_equal s(:a), s(:a).sub(s(:b), s(:c))
|
263
|
+
assert_equal s(:a, s(:c)), s(:a, s(:c)).sub(s(:b), s(:c))
|
264
|
+
|
265
|
+
assert_equal s(:a, s(:c), s(:b)), s(:a, s(:b), s(:b)).sub(s(:b), s(:c))
|
266
|
+
|
267
|
+
assert_equal(s(:a, s(:c), s(:a)),
|
268
|
+
s(:a, s(:b), s(:a)).sub(s(:b), s(:c)))
|
269
|
+
assert_equal(s(:a, s(:c), s(:a, s(:a))),
|
270
|
+
s(:a, s(:b), s(:a, s(:a))).sub(s(:b), s(:c)))
|
271
|
+
assert_equal(s(:a, s(:a), s(:a, s(:c), s(:b))),
|
272
|
+
s(:a, s(:a), s(:a, s(:b), s(:b))).sub(s(:b), s(:c)))
|
273
|
+
assert_equal(s(:a, s(:c, s(:b))),
|
274
|
+
s(:a, s(:b)).sub(s(:b), s(:c, s(:b))))
|
275
|
+
end
|
276
|
+
|
277
|
+
def test_to_a
|
278
|
+
assert_equal([1, 2, 3], @sexp.to_a)
|
279
|
+
end
|
280
|
+
|
281
|
+
def test_to_s
|
282
|
+
test_inspect
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
class TestSexpAny < SexpTestCase
|
287
|
+
|
288
|
+
def setup
|
289
|
+
super
|
290
|
+
end
|
291
|
+
|
292
|
+
def test_equals3
|
293
|
+
util_equals3 @any, s()
|
294
|
+
util_equals3 @any, s(:a)
|
295
|
+
util_equals3 @any, s(:a, :b, s(:c))
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
data/test/test_sexp_processor.rb
CHANGED
@@ -78,156 +78,6 @@ end
|
|
78
78
|
|
79
79
|
# Real test classes:
|
80
80
|
|
81
|
-
class TestSexp < Test::Unit::TestCase # ZenTest FULL
|
82
|
-
|
83
|
-
def setup
|
84
|
-
@sexp_class = Object.const_get(self.class.name[4..-1])
|
85
|
-
@processor = SexpProcessor.new
|
86
|
-
@sexp = @sexp_class.new(1, 2, 3)
|
87
|
-
end
|
88
|
-
|
89
|
-
def test_new_nested
|
90
|
-
@sexp = s(:lasgn, "var", s(:str, "foo"))
|
91
|
-
assert_equal('s(:lasgn, "var", s(:str, "foo"))',
|
92
|
-
@sexp.inspect)
|
93
|
-
end
|
94
|
-
|
95
|
-
def test_equals_array
|
96
|
-
# can't use assert_equals because it uses array as receiver
|
97
|
-
assert_not_equal(@sexp, [1, 2, 3],
|
98
|
-
"Sexp must not be equal to equivalent array")
|
99
|
-
# both directions just in case
|
100
|
-
# HACK - not sure why it is failing now that we split out TypedSexp
|
101
|
-
# assert_not_equal([1, 2, 3], @sexp,
|
102
|
-
# "Sexp must not be equal to equivalent array")
|
103
|
-
end
|
104
|
-
|
105
|
-
def test_equals_sexp
|
106
|
-
sexp2 = s(1, 2, 3)
|
107
|
-
assert_equal(@sexp, sexp2)
|
108
|
-
end
|
109
|
-
|
110
|
-
def test_equals_not_body
|
111
|
-
sexp2 = s(1, 2, 5)
|
112
|
-
assert_not_equal(@sexp, sexp2)
|
113
|
-
end
|
114
|
-
|
115
|
-
def test_to_a
|
116
|
-
assert_equal([1, 2, 3], @sexp.to_a)
|
117
|
-
end
|
118
|
-
|
119
|
-
def test_accessors=
|
120
|
-
a = s(:call, s(:lit, 1), "func", s(:array, s(:lit, 2)))
|
121
|
-
a.accessors = [:lhs, :name, :rhs]
|
122
|
-
|
123
|
-
assert_equal a.accessors, [:lhs, :name, :rhs]
|
124
|
-
|
125
|
-
assert_equal s(:lit, 1), a.lhs
|
126
|
-
assert_equal "func", a.name
|
127
|
-
assert_equal s(:array, s(:lit, 2)), a.rhs
|
128
|
-
|
129
|
-
a.accessors = []
|
130
|
-
|
131
|
-
assert_raises NoMethodError do
|
132
|
-
a.lhs
|
133
|
-
end
|
134
|
-
end
|
135
|
-
def test_accessors; end # handled
|
136
|
-
|
137
|
-
def test_sexp_body
|
138
|
-
assert_equal [2, 3], @sexp.sexp_body
|
139
|
-
end
|
140
|
-
|
141
|
-
def test_array_type?
|
142
|
-
assert_equal false, @sexp.array_type?
|
143
|
-
@sexp.unshift :array
|
144
|
-
assert_equal true, @sexp.array_type?
|
145
|
-
end
|
146
|
-
|
147
|
-
def test_each_of_type
|
148
|
-
# TODO: huh... this tests fails if top level sexp :b is removed
|
149
|
-
@sexp = s(:b, s(:a, s(:b, s(:a), :a, s(:b, :a), s(:b, s(:a)))))
|
150
|
-
count = 0
|
151
|
-
@sexp.each_of_type(:a) do |exp|
|
152
|
-
count += 1
|
153
|
-
end
|
154
|
-
assert_equal(3, count, "must find 3 a's in #{@sexp.inspect}")
|
155
|
-
end
|
156
|
-
|
157
|
-
def test_find_and_replace_all
|
158
|
-
@sexp = s(:a, s(:b, s(:a), s(:b), s(:b, s(:a))))
|
159
|
-
expected = s(:a, s(:a, s(:a), s(:a), s(:a, s(:a))))
|
160
|
-
|
161
|
-
@sexp.find_and_replace_all(:b, :a)
|
162
|
-
|
163
|
-
assert_equal(expected, @sexp)
|
164
|
-
end
|
165
|
-
|
166
|
-
def test_structure
|
167
|
-
@sexp = s(:a, 1, 2, s(:b, 3, 4), 5, 6)
|
168
|
-
expected = s(:a, s(:b))
|
169
|
-
|
170
|
-
assert_equal(expected, @sexp.structure)
|
171
|
-
end
|
172
|
-
|
173
|
-
def test_method_missing
|
174
|
-
assert_raises NoMethodError do
|
175
|
-
@sexp.no_such_method
|
176
|
-
end
|
177
|
-
|
178
|
-
@sexp.accessors = [:its_a_method_now]
|
179
|
-
|
180
|
-
assert_nothing_raised do
|
181
|
-
assert_equal 2, @sexp.its_a_method_now
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
def test_inspect
|
186
|
-
k = @sexp_class
|
187
|
-
n = k.name[0].chr.downcase
|
188
|
-
assert_equal("#{n}()",
|
189
|
-
k.new().inspect)
|
190
|
-
assert_equal("#{n}(:a)",
|
191
|
-
k.new(:a).inspect)
|
192
|
-
assert_equal("#{n}(:a, :b)",
|
193
|
-
k.new(:a, :b).inspect)
|
194
|
-
assert_equal("#{n}(:a, #{n}(:b))",
|
195
|
-
k.new(:a, k.new(:b)).inspect)
|
196
|
-
end
|
197
|
-
|
198
|
-
def test_to_s
|
199
|
-
test_inspect
|
200
|
-
end
|
201
|
-
|
202
|
-
def util_pretty_print(expect, input)
|
203
|
-
io = StringIO.new
|
204
|
-
PP.pp(input, io)
|
205
|
-
io.rewind
|
206
|
-
assert_equal(expect, io.read.chomp)
|
207
|
-
end
|
208
|
-
|
209
|
-
def test_pretty_print
|
210
|
-
util_pretty_print("s()",
|
211
|
-
s())
|
212
|
-
util_pretty_print("s(:a)",
|
213
|
-
s(:a))
|
214
|
-
util_pretty_print("s(:a, :b)",
|
215
|
-
s(:a, :b))
|
216
|
-
util_pretty_print("s(:a, s(:b))",
|
217
|
-
s(:a, s(:b)))
|
218
|
-
end
|
219
|
-
|
220
|
-
def test_shift
|
221
|
-
assert_equal(1, @sexp.shift)
|
222
|
-
assert_equal(2, @sexp.shift)
|
223
|
-
assert_equal(3, @sexp.shift)
|
224
|
-
|
225
|
-
assert_raise(RuntimeError) do
|
226
|
-
@sexp.shift
|
227
|
-
end
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
81
|
class TestSexpProcessor < Test::Unit::TestCase
|
232
82
|
|
233
83
|
def setup
|
metadata
CHANGED
@@ -1,69 +1,74 @@
|
|
1
|
-
|
2
|
-
rubygems_version: 0.8.
|
1
|
+
!ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11.1
|
3
3
|
specification_version: 1
|
4
4
|
name: ParseTree
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.
|
7
|
-
date: 2005-07
|
6
|
+
version: 1.4.0
|
7
|
+
date: 2005-10-17 00:00:00 -07:00
|
8
8
|
summary: Extract and enumerate ruby parse trees.
|
9
9
|
require_paths:
|
10
|
-
|
11
|
-
|
10
|
+
- lib
|
11
|
+
- test
|
12
12
|
email: ryand-ruby@zenspider.com
|
13
13
|
homepage: http://www.zenspider.com/ZSS/Products/ParseTree/
|
14
14
|
rubyforge_project: parsetree
|
15
|
-
description:
|
16
|
-
an entire class or a specific method and returns it as a s-expression (aka sexp)
|
17
|
-
using ruby's arrays, strings, symbols, and integers."
|
15
|
+
description: ParseTree is a C extension (using RubyInline) that extracts the parse tree for an entire class or a specific method and returns it as a s-expression (aka sexp) using ruby's arrays, strings, symbols, and integers.
|
18
16
|
autorequire: parse_tree
|
19
17
|
default_executable:
|
20
18
|
bindir: bin
|
21
19
|
has_rdoc: true
|
22
20
|
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
23
21
|
requirements:
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
version: 0.0.0
|
22
|
+
- - ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
28
25
|
version:
|
29
26
|
platform: ruby
|
27
|
+
signing_key:
|
28
|
+
cert_chain:
|
30
29
|
authors:
|
31
|
-
|
30
|
+
- Ryan Davis
|
32
31
|
files:
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
32
|
+
- History.txt
|
33
|
+
- Makefile
|
34
|
+
- Manifest.txt
|
35
|
+
- README.txt
|
36
|
+
- bin/parse_tree_abc
|
37
|
+
- bin/parse_tree_deps
|
38
|
+
- bin/parse_tree_show
|
39
|
+
- demo/printer.rb
|
40
|
+
- lib/composite_sexp_processor.rb
|
41
|
+
- lib/parse_tree.rb
|
42
|
+
- lib/sexp.rb
|
43
|
+
- lib/sexp_processor.rb
|
44
|
+
- test/something.rb
|
45
|
+
- test/test_all.rb
|
46
|
+
- test/test_composite_sexp_processor.rb
|
47
|
+
- test/test_parse_tree.rb
|
48
|
+
- test/test_sexp.rb
|
49
|
+
- test/test_sexp_processor.rb
|
50
|
+
- validate.sh
|
49
51
|
test_files:
|
50
|
-
|
52
|
+
- test/test_all.rb
|
51
53
|
rdoc_options: []
|
54
|
+
|
52
55
|
extra_rdoc_files: []
|
56
|
+
|
53
57
|
executables:
|
54
|
-
|
55
|
-
|
56
|
-
|
58
|
+
- parse_tree_abc
|
59
|
+
- parse_tree_deps
|
60
|
+
- parse_tree_show
|
57
61
|
extensions: []
|
62
|
+
|
58
63
|
requirements: []
|
64
|
+
|
59
65
|
dependencies:
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
version:
|
66
|
+
- !ruby/object:Gem::Dependency
|
67
|
+
name: RubyInline
|
68
|
+
version_requirement:
|
69
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 3.2.0
|
74
|
+
version:
|