larrytheliquid-Cry 0.0.2
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/MIT-LICENSE +20 -0
- data/README.rdoc +84 -0
- data/Rakefile +30 -0
- data/cry.rb +3 -0
- data/lib/parse_tree.rb +60 -0
- data/spec/parse_tree/private/evaluate_node_spec.rb +23 -0
- data/spec/parse_tree/public/evaluate_spec.rb +76 -0
- data/spec/parse_tree/public/height_spec.rb +70 -0
- data/spec/parse_tree/public/inspect_spec.rb +18 -0
- data/spec/parse_tree/public/new_spec.rb +7 -0
- data/spec/parse_tree/public/node_arguments_spec.rb +93 -0
- data/spec/parse_tree/public/node_method_spec.rb +35 -0
- data/spec/parse_tree/public/node_object_spec.rb +45 -0
- data/spec/spec.opts +6 -0
- metadata +75 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Larry Diehl
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
= Cry
|
2
|
+
|
3
|
+
A CommonLisp CLOS-like parse tree library for Ruby... read (and write) it and weep.
|
4
|
+
|
5
|
+
For example, you could create a parse tree like so:
|
6
|
+
|
7
|
+
parse_tree = Cry::ParseTree.new(:+, 1, 3)
|
8
|
+
|
9
|
+
... then evaluate it:
|
10
|
+
|
11
|
+
parse_tree.evaluate # => 4
|
12
|
+
|
13
|
+
... You can also create and evaluate more complex parse trees:
|
14
|
+
|
15
|
+
Cry::ParseTree.new( :+, Cry::ParseTree.new( :+, 1, Cry::ParseTree.new(:*, 2, 2) ), Cry::ParseTree.new(:+, 1, 3) ).evaluate # => 9
|
16
|
+
|
17
|
+
== Lineage
|
18
|
+
|
19
|
+
Cry::ParseTree just inherits from Array, so you can use all of Array's convenient methods for manipulating your ParseTrees too.
|
20
|
+
|
21
|
+
== Parameter order
|
22
|
+
|
23
|
+
The first parameter is the method as a String or Symbol, this never changes.
|
24
|
+
|
25
|
+
The second parameter is the object that the method will be called on. This can either be a normal object, or an unevaluated Cry::ParseTree for delayed recursive evaluation.
|
26
|
+
|
27
|
+
Any subsequent parameters can either be normal objects, or Cry::ParseTrees, and will be passed as arguments to the method call.
|
28
|
+
|
29
|
+
== Usage
|
30
|
+
|
31
|
+
require 'cry'
|
32
|
+
|
33
|
+
Cry::ParseTree.new(:*, Cry::ParseTree.new(:+, 1, 3), 23).evaluate # => 92
|
34
|
+
|
35
|
+
This is similar to the following Lisp:
|
36
|
+
|
37
|
+
(* (+ 1 3) 23) # => 92
|
38
|
+
|
39
|
+
Take note that ParseTree's second parameter is always your object (be it a class or not).
|
40
|
+
|
41
|
+
The method specified will be called on the object, similar to CLOS.
|
42
|
+
|
43
|
+
To distinguish Cry::ParseTree objects from Arrays when using inspect, they are denoted by parentheses:
|
44
|
+
|
45
|
+
Cry::ParseTree.new(:<<, [1], 2).inspect # => "(:<<, [1], 2)"
|
46
|
+
|
47
|
+
|
48
|
+
Realize that you have access to all of Ruby, so you can do crazy things like this:
|
49
|
+
|
50
|
+
Cry::ParseTree.new(:instance_variable_set, self, '@parse_tree', 'Cry::ParseTree.new(:*, Cry::ParseTree.new(:+, 1, 3), 23).evaluate').evaluate
|
51
|
+
Cry::ParseTree.new(:eval, Kernel, @parse_tree).evaluate # => 92
|
52
|
+
|
53
|
+
== Manipulation
|
54
|
+
|
55
|
+
The nice thing is that the parse trees are lazily evaluated. This means you can change them around before evaluations.
|
56
|
+
|
57
|
+
parse_tree = Cry::ParseTree.new(:+, 1, 3)
|
58
|
+
|
59
|
+
parse_tree.node_method # => :+
|
60
|
+
parse_tree.node_object # => 1
|
61
|
+
parse_tree.node_arguments # => [3]
|
62
|
+
|
63
|
+
parse_tree.node_method = :*
|
64
|
+
parse_tree.node_object = 2
|
65
|
+
parse_tree.node_arguments = [4]
|
66
|
+
|
67
|
+
parse_tree.evaluate # => 8
|
68
|
+
|
69
|
+
Also note that evaluate is not a destructive method.
|
70
|
+
|
71
|
+
parse_tree.evaluate # => 8
|
72
|
+
parse_tree.node_object = 3
|
73
|
+
parse_tree.evaluate # => 12
|
74
|
+
|
75
|
+
== Blocks
|
76
|
+
|
77
|
+
To use methods that accept a block, just use a Proc for your last argument:
|
78
|
+
|
79
|
+
Cry::ParseTree.new(:inject, [1, 2, 3], 0, lambda{|sum, i| sum + i }).evaluate # => 6
|
80
|
+
|
81
|
+
== Author
|
82
|
+
|
83
|
+
Author:: Larry Diehl (larrytheliquid)
|
84
|
+
Website:: http://larrytheliquid.com
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec/rake/spectask'
|
2
|
+
require 'spec/translator'
|
3
|
+
|
4
|
+
desc "Run all specs in spec directory"
|
5
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
6
|
+
t.spec_opts = ['--options', "\"spec/spec.opts\""]
|
7
|
+
t.spec_files = FileList['spec/parse_tree/public/**/*_spec.rb', 'spec/parse_tree/private/**/*_spec.rb']
|
8
|
+
end
|
9
|
+
|
10
|
+
namespace :spec do
|
11
|
+
desc "Run the specs under spec/parse_tree"
|
12
|
+
Spec::Rake::SpecTask.new(:parse_tree) do |t|
|
13
|
+
t.spec_opts = ['--options', "\"spec/spec.opts\""]
|
14
|
+
t.spec_files = FileList['spec/parse_tree/public/**/*_spec.rb', 'spec/parse_tree/private/**/*_spec.rb']
|
15
|
+
end
|
16
|
+
|
17
|
+
namespace :parse_tree do |t|
|
18
|
+
desc "Run the specs under spec/parse_tree/public"
|
19
|
+
Spec::Rake::SpecTask.new(:public) do |t|
|
20
|
+
t.spec_opts = ['--options', "\"spec/spec.opts\""]
|
21
|
+
t.spec_files = FileList['spec/parse_tree/public/**/*_spec.rb']
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "Run the specs under spec/parse_tree/private"
|
25
|
+
Spec::Rake::SpecTask.new(:private) do |t|
|
26
|
+
t.spec_opts = ['--options', "\"spec/spec.opts\""]
|
27
|
+
t.spec_files = FileList['spec/parse_tree/private/**/*_spec.rb']
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/cry.rb
ADDED
data/lib/parse_tree.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
module Cry
|
2
|
+
class ParseTree < Array
|
3
|
+
def initialize(*args)
|
4
|
+
super args.to_ary
|
5
|
+
end
|
6
|
+
|
7
|
+
def evaluate
|
8
|
+
evaluated_node_object = evaluate_node(node_object)
|
9
|
+
raw_send_arguments = node_arguments.map{|argument| evaluate_node(argument) }.insert(0, node_method)
|
10
|
+
evaluated_node_object.send *raw_send_arguments
|
11
|
+
rescue ArgumentError => original_error
|
12
|
+
begin
|
13
|
+
standard_send_arguments = raw_send_arguments
|
14
|
+
block_send_argument = raw_send_arguments.pop
|
15
|
+
evaluated_node_object.send *standard_send_arguments, &block_send_argument
|
16
|
+
rescue Exception
|
17
|
+
raise original_error
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def node_method
|
22
|
+
self.first.to_sym unless empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
def node_method=(node_method)
|
26
|
+
self[0] = node_method.to_sym
|
27
|
+
end
|
28
|
+
|
29
|
+
def node_object
|
30
|
+
self[1] unless size < 2
|
31
|
+
end
|
32
|
+
|
33
|
+
def node_object=(node_object)
|
34
|
+
self[1] = node_object
|
35
|
+
end
|
36
|
+
|
37
|
+
def node_arguments
|
38
|
+
size >= 2 ? self[2..size].to_a : Array.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def node_arguments=(node_arguments)
|
42
|
+
self[2..size] = node_arguments
|
43
|
+
end
|
44
|
+
|
45
|
+
def height
|
46
|
+
(node_method ? 1 : 0) + self[1..size].to_a.map{|node| node.is_a?(ParseTree) ? node.height : 1 }.max.to_i
|
47
|
+
end
|
48
|
+
|
49
|
+
def inspect
|
50
|
+
super.sub(/^\[/, "(").sub(/\]$/, ")")
|
51
|
+
end
|
52
|
+
alias_method :to_s, :inspect
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def evaluate_node(node)
|
57
|
+
node.is_a?(ParseTree) ? (node.node_method ? node.evaluate : nil) : node if node
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "..", "cry")
|
2
|
+
|
3
|
+
describe Cry::ParseTree, "#evaluate_node" do
|
4
|
+
before(:each) do
|
5
|
+
@parse_tree = Cry::ParseTree.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should be nil if the node is nil" do
|
9
|
+
@parse_tree.send(:evaluate_node, nil).should be_nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be nil if the node is an uninitialized Cry::ParseTree" do
|
13
|
+
@parse_tree.send(:evaluate_node, Cry::ParseTree.new).should be_nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should be the evaluated node if the everything is a terminal" do
|
17
|
+
@parse_tree.send(:evaluate_node, Cry::ParseTree.new(:+, 1, 2)).should == 3
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should be the recursively evaluated node if something is a Cry::ParseTree" do
|
21
|
+
@parse_tree.send(:evaluate_node, Cry::ParseTree.new(:+, Cry::ParseTree.new(:+, 1, 2), 2)).should == 5
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "..", "cry")
|
2
|
+
|
3
|
+
describe Cry::ParseTree, "#evaluate, with terminal object and parameters" do
|
4
|
+
it "should be able to evaluate an expression for a simple parse tree" do
|
5
|
+
parse_tree = Cry::ParseTree.new(:to_s, 1)
|
6
|
+
parse_tree.evaluate.should == "1"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should be able to evaluate an expression for a complex parse tree" do
|
10
|
+
parse_tree = Cry::ParseTree.new(:new, Array, 2, 1)
|
11
|
+
parse_tree.evaluate.should == [1, 1]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe Cry::ParseTree, "#evaluate, with terminal object, and Cry::ParseTree parameters" do
|
16
|
+
it "should be able to evaluate an expression for a simple parse tree" do
|
17
|
+
parse_tree = Cry::ParseTree.new( :+, 1, Cry::ParseTree.new(:*, 2, 2) )
|
18
|
+
parse_tree.evaluate.should == 5
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should be able to evaluate an expression for a complex parse tree" do
|
22
|
+
parse_tree = Cry::ParseTree.new( :+, 2, Cry::ParseTree.new( :+, 1, Cry::ParseTree.new(:*, 2, 2) ) )
|
23
|
+
parse_tree.evaluate.should == 7
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe Cry::ParseTree, "#evaluate, with terminal parameters, and Cry::ParseTree object" do
|
28
|
+
it "should be able to evaluate an expression for a simple parse tree" do
|
29
|
+
parse_tree = Cry::ParseTree.new( :+, Cry::ParseTree.new(:*, 2, 2), 1 )
|
30
|
+
parse_tree.evaluate.should == 5
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should be able to evaluate an expression for a complex parse tree" do
|
34
|
+
parse_tree = Cry::ParseTree.new( :+, Cry::ParseTree.new( :+, 1, Cry::ParseTree.new(:*, 2, 2) ), 2 )
|
35
|
+
parse_tree.evaluate.should == 7
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe Cry::ParseTree, "#evaluate, for complex mixed parameters" do
|
40
|
+
it "should be able to evaluate" do
|
41
|
+
parse_tree = Cry::ParseTree.new(
|
42
|
+
:+, Cry::ParseTree.new(:+, 1, 2),
|
43
|
+
Cry::ParseTree.new(:+, Cry::ParseTree.new(:+, 1, 2),
|
44
|
+
Cry::ParseTree.new(:*, Cry::ParseTree.new(:+, 1, 2),
|
45
|
+
Cry::ParseTree.new(:+, 1, 2) ) )
|
46
|
+
)
|
47
|
+
parse_tree.evaluate.should == 15
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should work with Arrays" do
|
51
|
+
parse_tree = Cry::ParseTree.new( :+, [1, 2], Cry::ParseTree.new(:new, Array, 1, 3) )
|
52
|
+
parse_tree.evaluate.should == [1, 2, 3]
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should work with lambdas" do
|
56
|
+
Cry::ParseTree.new(:call, lambda{|from, backwards_greeting| Cry::ParseTree.new(:+, Cry::ParseTree.new(:join, Cry::ParseTree.new(:reverse, backwards_greeting), " "), from).evaluate }, " from lisp", ["world", "hello"]).evaluate.should == "hello world from lisp"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should work with block parameters as lambdas" do
|
60
|
+
Cry::ParseTree.new(:inject, [1, 2, 3], 0, lambda{|sum, i| sum + i }).evaluate.should == 6
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should raise the original error if the block parameters as lambda attempt failes" do
|
64
|
+
lambda { Cry::ParseTree.new(:inject, [1, 2, 3], 0, "not a Proc").evaluate }.should raise_error(ArgumentError)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should be able to create new classes" do
|
68
|
+
Cry::ParseTree.new(:instance_variable_set, self, '@klass', Class.new ).evaluate
|
69
|
+
@klass.should be_kind_of(Class)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should work with the main 'self' runtime" do
|
73
|
+
Cry::ParseTree.new(:instance_variable_set, self, '@parse_tree', 'Cry::ParseTree.new(:*, Cry::ParseTree.new(:+, 1, 3), 23).evaluate' ).evaluate
|
74
|
+
Cry::ParseTree.new(:eval, Kernel, @parse_tree).evaluate.should == 92
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "..", "cry")
|
2
|
+
|
3
|
+
describe Cry::ParseTree, "#height" do
|
4
|
+
it "should be 0 for an uninitialized Cry::ParseTree" do
|
5
|
+
Cry::ParseTree.new.height.should == 0
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should be 1 for a Cry::ParseTree with only a method" do
|
9
|
+
Cry::ParseTree.new(:to_s).height.should == 1
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be 2 for a Cry::ParseTree with a method and an object" do
|
13
|
+
Cry::ParseTree.new(:to_s, 1).height.should == 2
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should work with nil" do
|
17
|
+
Cry::ParseTree.new(:to_s, nil).height.should == 2
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should compute height for a simple Cry::ParseTree with one parameter" do
|
21
|
+
parse_tree = Cry::ParseTree.new(:+, 1, 2)
|
22
|
+
parse_tree.height.should == 2
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should compute height for a simple Cry::ParseTree with multiple parameters" do
|
26
|
+
parse_tree = Cry::ParseTree.new(:new, Array, 2, 1)
|
27
|
+
parse_tree.height.should == 2
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should compute height for a simple nested Cry::ParseTree with a heavier left side" do
|
31
|
+
parse_tree = Cry::ParseTree.new( :+, Cry::ParseTree.new(:*, 2, 2), 1 )
|
32
|
+
parse_tree.height.should == 3
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should compute height for a simple nested Cry::ParseTree with a heavier right side" do
|
36
|
+
parse_tree = Cry::ParseTree.new( :+, 1, Cry::ParseTree.new(:*, 2, 2) )
|
37
|
+
parse_tree.height.should == 3
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should compute height for a complex nested Cry::ParseTree with a heavier left side" do
|
41
|
+
parse_tree = Cry::ParseTree.new( :+, Cry::ParseTree.new(:*, 2, Cry::ParseTree.new(:*, 2, 2)), Cry::ParseTree.new(:*, 2, 2) )
|
42
|
+
parse_tree.height.should == 4
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should compute height for a complex nested Cry::ParseTree with a heavier right side" do
|
46
|
+
parse_tree = Cry::ParseTree.new( :+, Cry::ParseTree.new(:*, 2, 2), Cry::ParseTree.new(:*, Cry::ParseTree.new(:*, 2, 2), 2) )
|
47
|
+
parse_tree.height.should == 4
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should compute height for a very complex nested Cry::ParseTree" do
|
51
|
+
parse_tree = Cry::ParseTree.new(
|
52
|
+
:+, Cry::ParseTree.new(:+, 1, Cry::ParseTree.new(:+, 1, 2) ),
|
53
|
+
Cry::ParseTree.new(:+, Cry::ParseTree.new(:+, 1, 2),
|
54
|
+
Cry::ParseTree.new(:*, Cry::ParseTree.new(:+, 1, 2),
|
55
|
+
Cry::ParseTree.new(:+,
|
56
|
+
Cry::ParseTree.new(:+, 1,
|
57
|
+
Cry::ParseTree.new(:+, 1, 2)), 2) ) )
|
58
|
+
)
|
59
|
+
parse_tree.height.should == 7
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should compute height for a non-binary tree" do
|
63
|
+
parse_tree = Cry::ParseTree.new(
|
64
|
+
:foobar, Object, 1, 2, Cry::ParseTree.new(:+,
|
65
|
+
Cry::ParseTree.new(:+, 1, 2), Cry::ParseTree.new(:+, 1,
|
66
|
+
Cry::ParseTree.new(:+, 1, 2))), 4)
|
67
|
+
|
68
|
+
parse_tree.height.should == 5
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "..", "cry")
|
2
|
+
|
3
|
+
describe Cry::ParseTree, "#inspect, distinguishing itself from Array#inspect" do
|
4
|
+
it "should use parantheses instead of brackets" do
|
5
|
+
p = Cry::ParseTree.new(:+, 1, 2)
|
6
|
+
p.inspect.should == "(:+, 1, 2)"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should work with Arrays" do
|
10
|
+
p = Cry::ParseTree.new(:+, 1, [2, 3])
|
11
|
+
p.inspect.should == "(:+, 1, [2, 3])"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should work with nested Cry::ParseTrees" do
|
15
|
+
p = Cry::ParseTree.new(:+, 1, Cry::ParseTree.new(:+, 2, 3))
|
16
|
+
p.inspect.should == "(:+, 1, (:+, 2, 3))"
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "..", "cry")
|
2
|
+
|
3
|
+
describe Cry::ParseTree, "#node_arguments" do
|
4
|
+
it "should be empty if the list is empty" do
|
5
|
+
Cry::ParseTree.new.node_arguments.should be_empty
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should be emtpy if the list has one element" do
|
9
|
+
Cry::ParseTree.new(:self).node_arguments.should be_empty
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be empty if the list has two elements" do
|
13
|
+
Cry::ParseTree.new(:to_s, 1).node_arguments.should be_empty
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return an Array" do
|
17
|
+
Cry::ParseTree.new(:+, 1, 2).node_arguments.class.should == Array
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return the single element remainder if the list has more than two elements, and its elements only have terminals" do
|
21
|
+
Cry::ParseTree.new(:+, 1, 2).node_arguments.should == [2]
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return the multiple element remainder if the list has more than two elements, and its elements only have terminals" do
|
25
|
+
Cry::ParseTree.new(:new, Array, 2, 1).node_arguments.should == [2, 1]
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should return the remainder of the elements if the list has more than two elements, and its elements have Cry::ParseTrees" do
|
29
|
+
Cry::ParseTree.new(:new, Array, 2, Cry::ParseTree.new(:+, 1, 2)).node_arguments.should == [2, [:+, 1, 2]]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe Cry::ParseTree, "#node_arguments=" do
|
34
|
+
it "should be able to set on a new Cry::ParseTree" do
|
35
|
+
parse_tree = Cry::ParseTree.new
|
36
|
+
parse_tree.node_arguments = [1]
|
37
|
+
parse_tree.node_arguments.should == [1]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should be able to set when node_arguments is emtpy" do
|
41
|
+
parse_tree = Cry::ParseTree.new(:+, 1)
|
42
|
+
parse_tree.node_arguments = [2]
|
43
|
+
parse_tree.node_arguments.should == [2]
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should be able to set with a single object" do
|
47
|
+
parse_tree = Cry::ParseTree.new(:+, 1, 2)
|
48
|
+
parse_tree.node_arguments = 5
|
49
|
+
parse_tree.node_arguments.should == [5]
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should be able to set with a single element Array" do
|
53
|
+
parse_tree = Cry::ParseTree.new(:+, 1, 2)
|
54
|
+
parse_tree.node_arguments = [5]
|
55
|
+
parse_tree.node_arguments.should == [5]
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should be able to set with a multiple element Array" do
|
59
|
+
parse_tree = Cry::ParseTree.new(:new, Array)
|
60
|
+
parse_tree.node_arguments = [2, 1]
|
61
|
+
parse_tree.node_arguments.should == [2, 1]
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should be able to set when node_object is already set" do
|
65
|
+
parse_tree = Cry::ParseTree.new(:+, 1, 2)
|
66
|
+
parse_tree.node_arguments = [4]
|
67
|
+
parse_tree.node_arguments.should == [4]
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should be able to set with a Cry::ParseTree" do
|
71
|
+
parse_tree = Cry::ParseTree.new(:+, 1, 2)
|
72
|
+
parse_tree.node_arguments = Cry::ParseTree.new
|
73
|
+
parse_tree.node_arguments.should == Cry::ParseTree.new
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should be able to set with a Cry::ParseTree in an Array" do
|
77
|
+
parse_tree = Cry::ParseTree.new(:+, 1, 2)
|
78
|
+
parse_tree.node_arguments = [Cry::ParseTree.new]
|
79
|
+
parse_tree.node_arguments.should == [Cry::ParseTree.new]
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should be able to overwrite current arguments with a new Array, when more arguments are added" do
|
83
|
+
parse_tree = Cry::ParseTree.new(:foobar, Object, 1, 2)
|
84
|
+
parse_tree.node_arguments = [3, 4, 5]
|
85
|
+
parse_tree.node_arguments.should == [3, 4, 5]
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should be able to overwrite current arguments with a new Array, when less arguments are added" do
|
89
|
+
parse_tree = Cry::ParseTree.new(:foobar, Object, 1, 2, 3)
|
90
|
+
parse_tree.node_arguments = [4, 5]
|
91
|
+
parse_tree.node_arguments.should == [4, 5]
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "..", "cry")
|
2
|
+
|
3
|
+
describe Cry::ParseTree, "#node_method" do
|
4
|
+
it "should be nil if the list is empty" do
|
5
|
+
Cry::ParseTree.new.node_method.should be_nil
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should be the first element as a symbol if the list has one element" do
|
9
|
+
Cry::ParseTree.new("self").node_method.should == :self
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be the first element as a symbol if the list has more than one element" do
|
13
|
+
Cry::ParseTree.new(:+, 1, 2).node_method.should == :+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Cry::ParseTree, "#node_method=" do
|
18
|
+
it "should be able to set on a new Cry::ParseTree" do
|
19
|
+
parse_tree = Cry::ParseTree.new
|
20
|
+
parse_tree.node_method = :+
|
21
|
+
parse_tree.node_method.should == :+
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should be able to set when node_method is nil" do
|
25
|
+
parse_tree = Cry::ParseTree.new(nil, 1, 2)
|
26
|
+
parse_tree.node_method = :+
|
27
|
+
parse_tree.node_method.should == :+
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should be able to set when node_method is already set" do
|
31
|
+
parse_tree = Cry::ParseTree.new(:+, 1, 2)
|
32
|
+
parse_tree.node_method = :*
|
33
|
+
parse_tree.node_method.should == :*
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "..", "cry")
|
2
|
+
|
3
|
+
describe Cry::ParseTree, "#node_object" do
|
4
|
+
it "should be nil if the list is empty" do
|
5
|
+
Cry::ParseTree.new.node_object.should be_nil
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should be nil if the list has one element" do
|
9
|
+
Cry::ParseTree.new(:self).node_object.should be_nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be the second element if the list has more than one element, and it is a terminal" do
|
13
|
+
Cry::ParseTree.new(:+, 1, 2).node_object.should == 1
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should be the second element if the list has more than one element, and it is a Cry::ParseTree" do
|
17
|
+
Cry::ParseTree.new(:+, Cry::ParseTree.new(:+, 1, 2), 2).node_object.should == [:+, 1, 2]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe Cry::ParseTree, "#node_object=" do
|
22
|
+
it "should be able to set on a new Cry::ParseTree" do
|
23
|
+
parse_tree = Cry::ParseTree.new
|
24
|
+
parse_tree.node_object = 1
|
25
|
+
parse_tree.node_object.should == 1
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should be able to set when node_object is nil" do
|
29
|
+
parse_tree = Cry::ParseTree.new(:+, nil, 2)
|
30
|
+
parse_tree.node_object = 1
|
31
|
+
parse_tree.node_object.should == 1
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should be able to set when node_object is already set" do
|
35
|
+
parse_tree = Cry::ParseTree.new(:+, 1, 2)
|
36
|
+
parse_tree.node_object = 4
|
37
|
+
parse_tree.node_object.should == 4
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should be able to set with a Cry::ParseTree" do
|
41
|
+
parse_tree = Cry::ParseTree.new(:+, nil, 2)
|
42
|
+
parse_tree.node_object = Cry::ParseTree.new
|
43
|
+
parse_tree.node_object.should == Cry::ParseTree.new
|
44
|
+
end
|
45
|
+
end
|
data/spec/spec.opts
ADDED
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: larrytheliquid-Cry
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Larry Diehl (larrytheliquid)
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-06-04 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: A CommonLisp CLOS-like ParseTree in Ruby... read (and write) it and weep.
|
17
|
+
email: larrytheliquid@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- README.rdoc
|
26
|
+
- Rakefile
|
27
|
+
- cry.rb
|
28
|
+
- lib/parse_tree.rb
|
29
|
+
- MIT-LICENSE
|
30
|
+
- spec/parse_tree/public/evaluate_spec.rb
|
31
|
+
- spec/parse_tree/public/height_spec.rb
|
32
|
+
- spec/parse_tree/public/inspect_spec.rb
|
33
|
+
- spec/parse_tree/public/new_spec.rb
|
34
|
+
- spec/parse_tree/public/node_arguments_spec.rb
|
35
|
+
- spec/parse_tree/public/node_method_spec.rb
|
36
|
+
- spec/parse_tree/public/node_object_spec.rb
|
37
|
+
- spec/parse_tree/private/evaluate_node_spec.rb
|
38
|
+
- spec/spec.opts
|
39
|
+
has_rdoc: true
|
40
|
+
homepage: http://github.com/larrytheliquid/cry/tree/master
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options:
|
43
|
+
- --main
|
44
|
+
- README.rdoc
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
version:
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
version:
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.0.1
|
63
|
+
signing_key:
|
64
|
+
specification_version: 2
|
65
|
+
summary: A lazily evaluated and easy to use Ruby parse tree.
|
66
|
+
test_files:
|
67
|
+
- spec/parse_tree/public/evaluate_spec.rb
|
68
|
+
- spec/parse_tree/public/height_spec.rb
|
69
|
+
- spec/parse_tree/public/inspect_spec.rb
|
70
|
+
- spec/parse_tree/public/new_spec.rb
|
71
|
+
- spec/parse_tree/public/node_arguments_spec.rb
|
72
|
+
- spec/parse_tree/public/node_method_spec.rb
|
73
|
+
- spec/parse_tree/public/node_object_spec.rb
|
74
|
+
- spec/parse_tree/private/evaluate_node_spec.rb
|
75
|
+
- spec/spec.opts
|