larrytheliquid-Cry 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|