aniero-treehouse 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/Manifest.txt +43 -0
- data/README.txt +102 -0
- data/Rakefile +25 -0
- data/examples/simple_assignment.rb +54 -0
- data/lib/treehouse.rb +52 -0
- data/lib/treehouse/metaid.rb +16 -0
- data/lib/treehouse/node.rb +79 -0
- data/lib/treehouse/node_creator.rb +28 -0
- data/lib/treehouse/node_definition.rb +106 -0
- data/lib/treehouse/visitor.rb +49 -0
- data/lib/treehouse/visitor_definition.rb +49 -0
- data/spec/fixtures/assignments.txt +7 -0
- data/spec/fixtures/ey00-s00348.xen +14 -0
- data/spec/grammars/assignments.rb +38 -0
- data/spec/grammars/assignments.treetop +42 -0
- data/spec/grammars/dot_xen.rb +122 -0
- data/spec/grammars/dot_xen.treetop +100 -0
- data/spec/grammars/magic.rb +63 -0
- data/spec/integration/assignments_spec.rb +45 -0
- data/spec/integration/dot_xen_spec.rb +86 -0
- data/spec/integration/magic_spec.rb +40 -0
- data/spec/node_creator_spec.rb +47 -0
- data/spec/node_definition_spec.rb +60 -0
- data/spec/node_spec.rb +131 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/treehouse_spec.rb +17 -0
- data/spec/visitor_definition_spec.rb +44 -0
- data/spec/visitor_spec.rb +48 -0
- data/tasks/ann.rake +81 -0
- data/tasks/bones.rake +21 -0
- data/tasks/gem.rake +126 -0
- data/tasks/git.rake +41 -0
- data/tasks/manifest.rake +49 -0
- data/tasks/notes.rake +28 -0
- data/tasks/post_load.rake +39 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +57 -0
- data/tasks/setup.rb +268 -0
- data/tasks/spec.rake +55 -0
- data/tasks/svn.rake +48 -0
- data/tasks/test.rake +38 -0
- data/treehouse.gemspec +38 -0
- metadata +124 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
2
|
+
|
3
|
+
require Treehouse.path(%w(spec grammars assignments))
|
4
|
+
|
5
|
+
describe AssignmentsLanguage::Grammar do
|
6
|
+
|
7
|
+
it "has nodes defined" do
|
8
|
+
consts = AssignmentsLanguage::Grammar.constants
|
9
|
+
consts.should include("Assignments")
|
10
|
+
consts.should include("Assignment")
|
11
|
+
consts.should include("BlankLine")
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
describe AssignmentsLanguage::Parser, ".parse" do
|
17
|
+
|
18
|
+
before(:each) do
|
19
|
+
@input = File.read(Treehouse.path(%w(spec fixtures assignments.txt)))
|
20
|
+
end
|
21
|
+
|
22
|
+
it "parses a file and returns a Treehouse AST" do
|
23
|
+
AssignmentsLanguage::Parser.parse(@input).should be_a_kind_of(Treehouse::Node)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
describe AssignmentsLanguage do
|
29
|
+
it "has a string visitor defined" do
|
30
|
+
AssignmentsLanguage.const_get("StringVisitor").ancestors.should include(Treehouse::Visitor)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe AssignmentsLanguage::StringVisitor do
|
35
|
+
before(:each) do
|
36
|
+
@input = File.read(Treehouse.path(%w(spec fixtures assignments.txt)))
|
37
|
+
@ast = AssignmentsLanguage::Parser.parse(@input)
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#visit" do
|
41
|
+
it "traverses the AST and collects the values" do
|
42
|
+
AssignmentsLanguage::StringVisitor.visit(@ast).should == "foo = bar\nbaz = blech\nno = way\n"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
2
|
+
|
3
|
+
require Treehouse.path(%w(spec grammars dot_xen))
|
4
|
+
|
5
|
+
describe DotXen::Parser, ".parse" do
|
6
|
+
before(:each) do
|
7
|
+
data = File.read(Treehouse.path(%w(spec fixtures ey00-s00348.xen)))
|
8
|
+
@ast = DotXen::Parser.parse(data)
|
9
|
+
end
|
10
|
+
it "returns an AST" do
|
11
|
+
@ast.should_not be_nil
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "with a parsed AST" do
|
15
|
+
it "has a comment" do
|
16
|
+
@ast.should have(1).comments
|
17
|
+
end
|
18
|
+
|
19
|
+
it "has 3 disks" do
|
20
|
+
@ast.should have(3).disks
|
21
|
+
end
|
22
|
+
|
23
|
+
it "has vars" do
|
24
|
+
@ast.should have_at_least(5).vars
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
describe DotXen::HashVisitor do
|
32
|
+
before(:all) do
|
33
|
+
data = File.read(Treehouse.path(%w(spec fixtures ey00-s00348.xen)))
|
34
|
+
@ast = DotXen::Parser.parse(data)
|
35
|
+
end
|
36
|
+
|
37
|
+
describe ".visit" do
|
38
|
+
it "returns a hash representation of the AST" do
|
39
|
+
DotXen::HashVisitor.visit(@ast).should == {
|
40
|
+
:comments => [" -*- mode: python; -*-"],
|
41
|
+
:disks => [
|
42
|
+
"phy:/dev/ey00-data4/root-s00348,sda1,w",
|
43
|
+
"phy:/dev/ey00-data4/swap-s00348,sda2,w",
|
44
|
+
"phy:/dev/ey00-data4/gfs-00218,sdb1,w!"
|
45
|
+
],
|
46
|
+
:vars => {
|
47
|
+
"name" => "ey00-s00348",
|
48
|
+
"kernel" => "/boot/vmlinuz-2.6.18-xenU",
|
49
|
+
"memory" => 712,
|
50
|
+
"cpu_cap" => 100,
|
51
|
+
"vcpus" => 1,
|
52
|
+
"root" => "/dev/sda1 ro",
|
53
|
+
"maxmem" => 4096,
|
54
|
+
"vif" => ["bridge=xenbr0"]
|
55
|
+
}
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe DotXen::StringVisitor do
|
62
|
+
before(:all) do
|
63
|
+
data = File.read(Treehouse.path(%w(spec fixtures ey00-s00348.xen)))
|
64
|
+
@ast = DotXen::Parser.parse(data)
|
65
|
+
end
|
66
|
+
describe ".visit" do
|
67
|
+
it "returns a string representation of the AST" do
|
68
|
+
DotXen::StringVisitor.visit(@ast).should == <<-EOS
|
69
|
+
# -*- mode: python; -*-
|
70
|
+
kernel = '/boot/vmlinuz-2.6.18-xenU'
|
71
|
+
memory = 712
|
72
|
+
maxmem = 4096
|
73
|
+
name = 'ey00-s00348'
|
74
|
+
vif = [ 'bridge=xenbr0' ]
|
75
|
+
root = "/dev/sda1 ro"
|
76
|
+
vcpus = 1
|
77
|
+
cpu_cap = 100
|
78
|
+
disk = [
|
79
|
+
"phy:/dev/ey00-data4/root-s00348,sda1,w",
|
80
|
+
"phy:/dev/ey00-data4/swap-s00348,sda2,w",
|
81
|
+
"phy:/dev/ey00-data4/gfs-00218,sdb1,w!"
|
82
|
+
]
|
83
|
+
EOS
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
2
|
+
|
3
|
+
require Treehouse.path(%w(spec grammars magic))
|
4
|
+
|
5
|
+
describe MagicAssignments::Parser do
|
6
|
+
describe ".parse" do
|
7
|
+
before(:each) do
|
8
|
+
@input = File.read(Treehouse.path(%w(spec fixtures assignments.txt)))
|
9
|
+
@result = MagicAssignments::Parser.parse(@input)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "returns an AST" do
|
13
|
+
@result.should be_an_instance_of(MagicAssignments::AST::Assignments)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "has the right number of nodes" do
|
17
|
+
@result.should have(7).assignments
|
18
|
+
end
|
19
|
+
|
20
|
+
it "has an assignment with correct values" do
|
21
|
+
@result.assignments.first.should be_an_instance_of(MagicAssignments::AST::Assignment)
|
22
|
+
@result.assignments.first.lhs.value.should == "foo"
|
23
|
+
@result.assignments.first.rhs.value.should == "bar"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe MagicAssignments::HashVisitor do
|
30
|
+
describe ".visit" do
|
31
|
+
it "returns a hash representation of the assignments" do
|
32
|
+
ast = MagicAssignments::Parser.parse(File.read(Treehouse.path(%w(spec fixtures assignments.txt))))
|
33
|
+
MagicAssignments::HashVisitor.visit(ast).should == {
|
34
|
+
"foo" => "bar",
|
35
|
+
"baz" => "blech",
|
36
|
+
"no" => "way"
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[spec_helper])
|
2
|
+
|
3
|
+
describe Treehouse::NodeCreator do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
SomeNode = Class.new(Treehouse::Node)
|
7
|
+
end
|
8
|
+
after(:all) do
|
9
|
+
Object.send(:remove_const, "SomeNode")
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#initialize" do
|
13
|
+
|
14
|
+
it "takes a class as an argument" do
|
15
|
+
nc = Treehouse::NodeCreator.new(SomeNode)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#new" do
|
20
|
+
before(:each) do
|
21
|
+
@nc = Treehouse::NodeCreator.new(SomeNode)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "takes parameters as if it were a treetop syntax node" do
|
25
|
+
@nc.new("what", 0..3)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns a treetop syntax node" do
|
29
|
+
node = @nc.new("what", 0..3)
|
30
|
+
node.should be_an_instance_of(Treetop::Runtime::SyntaxNode)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "defines a build method on the syntax node" do
|
34
|
+
node = @nc.new("what", 0..3)
|
35
|
+
node.methods.should include("build")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "creates an instance of the defined class when build is called on the resulting syntax node" do
|
39
|
+
node = @nc.new("what", 0..3)
|
40
|
+
mock_node = mock("node")
|
41
|
+
SomeNode.should_receive(:new).with(node).and_return(mock_node)
|
42
|
+
node.build.should == mock_node
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[spec_helper])
|
2
|
+
|
3
|
+
describe Treehouse::NodeDefinition do
|
4
|
+
module TestNodes
|
5
|
+
include Treehouse::NodeDefinition
|
6
|
+
end
|
7
|
+
|
8
|
+
it "adds a node method when included" do
|
9
|
+
TestNodes.methods.should include("node")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "adds a create_node method when included" do
|
13
|
+
TestNodes.methods.should include("create_node")
|
14
|
+
end
|
15
|
+
|
16
|
+
describe ".node" do
|
17
|
+
before(:each) do
|
18
|
+
TestNodes.class_eval { node :foo, :bar, :baz }
|
19
|
+
end
|
20
|
+
after(:each) do
|
21
|
+
TestNodes.send(:remove_const, "Foo")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "defines a class" do
|
25
|
+
TestNodes.constants.should include("Foo")
|
26
|
+
TestNodes::Foo.ancestors.should include(Treehouse::Node)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "defines a class with an attribute for each of the provided arguments" do
|
30
|
+
TestNodes::Foo.instance_methods.should include("bar")
|
31
|
+
TestNodes::Foo.instance_methods.should include("baz")
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
describe ".create_node" do
|
37
|
+
before(:all) do
|
38
|
+
TestNodes.class_eval { node :foo_node }
|
39
|
+
end
|
40
|
+
after(:all) do
|
41
|
+
TestNodes.send(:remove_const, "FooNode")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "takes a node name as an argument" do
|
45
|
+
TestNodes.create_node(:foo_node)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "returns an instance of NodeCreator" do
|
49
|
+
TestNodes.create_node(:foo_node).should be_an_instance_of(Treehouse::NodeCreator)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "instantiates the node creator with the class corresponding to the node name" do
|
53
|
+
obj = Object.new
|
54
|
+
Treehouse::NodeCreator.should_receive(:new).with(TestNodes::FooNode).and_return(obj)
|
55
|
+
TestNodes.create_node(:foo_node).should == obj
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
data/spec/node_spec.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[spec_helper])
|
2
|
+
|
3
|
+
describe Treehouse::Node do
|
4
|
+
|
5
|
+
describe ".create" do
|
6
|
+
it "returns a class that inherits from Treehouse::Node" do
|
7
|
+
klass = Treehouse::Node.create
|
8
|
+
klass.should be_an_instance_of(Class)
|
9
|
+
klass.ancestors.should include(Treehouse::Node)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "with attribute names" do
|
13
|
+
before(:each) do
|
14
|
+
@node = Treehouse::Node.create(:foo, :bar)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "creates a class with the given attributes" do
|
18
|
+
n = @node.new(:foo => 1, :bar => 2)
|
19
|
+
n.foo.should == 1
|
20
|
+
n.bar.should == 2
|
21
|
+
end
|
22
|
+
|
23
|
+
it "creates attributes with a default of raising an exception if not initialized" do
|
24
|
+
n = @node.new(:foo => 1) # no :bar
|
25
|
+
n.foo.should == 1
|
26
|
+
lambda { n.bar }.should raise_error(RuntimeError, "no value given for bar")
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "with an attribute hash" do
|
32
|
+
before(:each) do
|
33
|
+
@node = Treehouse::Node.create(:lhs => :left_value, :rhs => :right_value)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "creates a class with attributes matching the hash keys" do
|
37
|
+
@node.attributes.sort.should == ["lhs", "rhs"]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "creates attributes with a default of raising an exception if not set" do
|
41
|
+
n = @node.new
|
42
|
+
lambda { n.lhs }.should raise_error(RuntimeError, "no value given for lhs")
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns a class with an attribute mapping" do
|
46
|
+
@node.attribute_mapping.should == {"lhs" => :left_value, "rhs" => :right_value}
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "with a mix of named attributes and hash attributes" do
|
52
|
+
before(:each) do
|
53
|
+
@node = Treehouse::Node.create(:one, :two, :three => :value)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "creates a class with attributes matching the named attributes and hash keys" do
|
57
|
+
@node.attributes.should == %w(one two three)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "updates the attribute mapping" do
|
61
|
+
@node.attribute_mapping.should == {"three" => :value}
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
describe ".new" do
|
69
|
+
before(:each) do
|
70
|
+
@node = Treehouse::Node.create(:child, :value => :data)
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "with empty args" do
|
74
|
+
it "initializes a node without touching the attributes" do
|
75
|
+
n = @node.new
|
76
|
+
lambda { n.child }.should raise_error(RuntimeError)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "with a hash" do
|
81
|
+
it "initializes each of the attributes to the given value" do
|
82
|
+
n = @node.new(:child => 1, :value => 2)
|
83
|
+
n.child.should == 1
|
84
|
+
n.value.should == 2
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "with an instance of Treetop::Runtime::SyntaxNode" do
|
89
|
+
before(:each) do
|
90
|
+
@child = mock_syntax_node :build => "child value"
|
91
|
+
@top = mock_syntax_node :child => @child, :data => "data"
|
92
|
+
end
|
93
|
+
|
94
|
+
it "sets the named values by calling build on the named child node" do
|
95
|
+
@top.should_receive(:child).and_return(@child)
|
96
|
+
@child.should_receive(:build).and_return("child value")
|
97
|
+
n = @node.new(@top)
|
98
|
+
n.child.should == "child value"
|
99
|
+
end
|
100
|
+
|
101
|
+
it "calls the specified method directly for hash values" do
|
102
|
+
@top.should_receive(:data).and_return do
|
103
|
+
puts "called from #{caller.detect {|c| c !~ /rspec/}}"
|
104
|
+
"foo"
|
105
|
+
end
|
106
|
+
n = @node.new(@top)
|
107
|
+
n.value.should == "foo"
|
108
|
+
end
|
109
|
+
|
110
|
+
it "calls build on each element of a referenced node value if that value is an array" do
|
111
|
+
@top.should_receive(:child).and_return([@child, @child])
|
112
|
+
@child.should_receive(:build).exactly(2).times.and_return("one", "two")
|
113
|
+
n = @node.new(@top)
|
114
|
+
n.child.should == %w(one two)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "only calls build on elements of an array if they respond to that method" do
|
118
|
+
@top.should_receive(:child).and_return([@child, "blah"])
|
119
|
+
@node.new(@top).child.should == ["child value", "blah"]
|
120
|
+
end
|
121
|
+
|
122
|
+
it "yields the syntax node instance if a mapped attribute is a lambda" do
|
123
|
+
@node = Treehouse::Node.create(:value => lambda { |x| @x = x })
|
124
|
+
@node.new(@top)
|
125
|
+
@x.should == @top
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib treehouse]))
|
2
|
+
|
3
|
+
Spec::Runner.configure do |config|
|
4
|
+
# == Mock Framework
|
5
|
+
#
|
6
|
+
# RSpec uses it's own mocking framework by default. If you prefer to
|
7
|
+
# use mocha, flexmock or RR, uncomment the appropriate line:
|
8
|
+
#
|
9
|
+
# config.mock_with :mocha
|
10
|
+
# config.mock_with :flexmock
|
11
|
+
# config.mock_with :rr
|
12
|
+
|
13
|
+
# borrowed from rspec_on_rails' mock_model
|
14
|
+
def mock_syntax_node(stubs={})
|
15
|
+
m = mock "mock syntax node", stubs
|
16
|
+
m.send(:__mock_proxy).instance_eval do
|
17
|
+
def @target.is_a?(other)
|
18
|
+
Treetop::Runtime::SyntaxNode.ancestors.include?(other)
|
19
|
+
end
|
20
|
+
def @target.kind_of?(other)
|
21
|
+
Treetop::Runtime::SyntaxNode.ancestors.include?(other)
|
22
|
+
end
|
23
|
+
def @target.instance_of?(other)
|
24
|
+
other == Treetop::Runtime::SyntaxNode
|
25
|
+
end
|
26
|
+
def @target.class
|
27
|
+
Treetop::Runtime::SyntaxNode
|
28
|
+
end
|
29
|
+
end
|
30
|
+
yield m if block_given?
|
31
|
+
m
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|