antlr3 1.6.0 → 1.6.3
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 +8 -0
- data/Manifest.txt +94 -0
- data/README.txt +1 -1
- data/Rakefile +58 -0
- data/bin/antlr4ruby +101 -7
- data/java/antlr-full-3.2.1.jar +0 -0
- data/lib/antlr3.rb +38 -10
- data/lib/antlr3/constants.rb +13 -5
- data/lib/antlr3/debug.rb +57 -57
- data/lib/antlr3/dfa.rb +138 -68
- data/lib/antlr3/dot.rb +32 -32
- data/lib/antlr3/error.rb +85 -78
- data/lib/antlr3/main.rb +191 -187
- data/lib/antlr3/profile.rb +71 -70
- data/lib/antlr3/recognizers.rb +261 -226
- data/lib/antlr3/streams.rb +85 -84
- data/lib/antlr3/streams/interactive.rb +20 -27
- data/lib/antlr3/streams/rewrite.rb +89 -89
- data/lib/antlr3/task.rb +42 -33
- data/lib/antlr3/template.rb +2 -2
- data/lib/antlr3/template/group-lexer.rb +1 -1
- data/lib/antlr3/token.rb +76 -68
- data/lib/antlr3/tree.rb +125 -121
- data/lib/antlr3/tree/visitor.rb +1 -1
- data/lib/antlr3/tree/wizard.rb +1 -1
- data/lib/antlr3/util.rb +32 -33
- data/lib/antlr3/version.rb +3 -3
- data/templates/Ruby.stg +1 -1
- data/test/unit/test-streams.rb +11 -10
- data/test/unit/test-template.rb +206 -204
- metadata +4 -2
data/lib/antlr3/tree/wizard.rb
CHANGED
data/lib/antlr3/util.rb
CHANGED
@@ -6,10 +6,10 @@ module Util
|
|
6
6
|
|
7
7
|
module_function
|
8
8
|
|
9
|
-
def snake_case(str)
|
10
|
-
str = str.to_s.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
11
|
-
str.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
12
|
-
str.tr!("-", "_")
|
9
|
+
def snake_case( str )
|
10
|
+
str = str.to_s.gsub( /([A-Z]+)([A-Z][a-z])/,'\1_\2' )
|
11
|
+
str.gsub!( /([a-z\d])([A-Z])/,'\1_\2' )
|
12
|
+
str.tr!( "-", "_" )
|
13
13
|
str.downcase!
|
14
14
|
str
|
15
15
|
end
|
@@ -21,10 +21,10 @@ module_function
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def tidy( here_doc, flow = false )
|
24
|
-
here_doc.gsub!(/^ *\| ?/, '')
|
24
|
+
here_doc.gsub!( /^ *\| ?/, '' )
|
25
25
|
if flow
|
26
26
|
here_doc.strip!
|
27
|
-
here_doc.gsub!(/\s+/, ' ')
|
27
|
+
here_doc.gsub!( /\s+/, ' ' )
|
28
28
|
end
|
29
29
|
return here_doc
|
30
30
|
end
|
@@ -45,37 +45,37 @@ private
|
|
45
45
|
def shared_attribute( name, *additional_members )
|
46
46
|
attr_reader name
|
47
47
|
|
48
|
-
additional_writers = additional_members.inject('') do |src, attr|
|
49
|
-
src << "@#{attr} = value if @#{attr}\n"
|
48
|
+
additional_writers = additional_members.inject( '' ) do |src, attr|
|
49
|
+
src << "@#{ attr } = value if @#{ attr }\n"
|
50
50
|
end
|
51
51
|
|
52
|
-
file, line, = caller[1].split(':', 3)
|
53
|
-
class_eval(<<-END, file, line.to_i)
|
54
|
-
def #{name}= value
|
55
|
-
@#{name} = value
|
52
|
+
file, line, = caller[ 1 ].split( ':', 3 )
|
53
|
+
class_eval( <<-END, file, line.to_i )
|
54
|
+
def #{ name }= value
|
55
|
+
@#{ name } = value
|
56
56
|
|
57
57
|
each_delegate do |del|
|
58
|
-
del.#{name} = value
|
58
|
+
del.#{ name } = value
|
59
59
|
end
|
60
60
|
|
61
|
-
#{additional_writers}
|
61
|
+
#{ additional_writers }
|
62
62
|
end
|
63
63
|
END
|
64
64
|
end
|
65
65
|
|
66
66
|
def abstract( name, message = nil )
|
67
|
-
message ||= "abstract method -- #{self.class}::#{name} has not been implemented"
|
68
|
-
file, line, = caller[1].split(':', 3)
|
69
|
-
class_eval(<<-END, file, line.to_i)
|
70
|
-
def #{name}( * )
|
71
|
-
raise TypeError, #{message.to_s.inspect}
|
67
|
+
message ||= "abstract method -- #{ self.class }::#{ name } has not been implemented"
|
68
|
+
file, line, = caller[ 1 ].split( ':', 3 )
|
69
|
+
class_eval( <<-END, file, line.to_i )
|
70
|
+
def #{ name }( * )
|
71
|
+
raise TypeError, #{ message.to_s.inspect }
|
72
72
|
end
|
73
73
|
END
|
74
74
|
end
|
75
75
|
|
76
76
|
def alias_accessor( alias_name, attr_name )
|
77
77
|
alias_method( alias_name, attr_name )
|
78
|
-
alias_method( :"#{alias_name}=", :"#{attr_name}=" )
|
78
|
+
alias_method( :"#{ alias_name }=", :"#{ attr_name }=" )
|
79
79
|
end
|
80
80
|
|
81
81
|
end
|
@@ -91,8 +91,8 @@ class Integer
|
|
91
91
|
#
|
92
92
|
# CREDIT Florian Gross
|
93
93
|
|
94
|
-
def at_least(x)
|
95
|
-
(self >= x) ? self : x
|
94
|
+
def at_least( x )
|
95
|
+
( self >= x ) ? self : x
|
96
96
|
end
|
97
97
|
|
98
98
|
# Returns the greater of self or x.
|
@@ -102,8 +102,8 @@ class Integer
|
|
102
102
|
#
|
103
103
|
# CREDIT Florian Gross
|
104
104
|
|
105
|
-
def at_most(x)
|
106
|
-
(self <= x) ? self : x
|
105
|
+
def at_most( x )
|
106
|
+
( self <= x ) ? self : x
|
107
107
|
end
|
108
108
|
|
109
109
|
# Returns self if above the given lower bound, or
|
@@ -119,7 +119,7 @@ class Integer
|
|
119
119
|
#
|
120
120
|
# CREDIT Trans
|
121
121
|
|
122
|
-
def bound(lower, upper=nil)
|
122
|
+
def bound( lower, upper=nil )
|
123
123
|
return lower if self < lower
|
124
124
|
return self unless upper
|
125
125
|
return upper if self > upper
|
@@ -130,7 +130,7 @@ end
|
|
130
130
|
|
131
131
|
|
132
132
|
class Range
|
133
|
-
def covers?(range)
|
133
|
+
def covers?( range )
|
134
134
|
range.first >= first or return false
|
135
135
|
if exclude_end?
|
136
136
|
range.exclude_end? ? last >= range.last : last > range.last
|
@@ -139,17 +139,16 @@ class Range
|
|
139
139
|
end
|
140
140
|
end
|
141
141
|
|
142
|
-
def covered_by?(range)
|
143
|
-
range.covers?(self)
|
142
|
+
def covered_by?( range )
|
143
|
+
range.covers?( self )
|
144
144
|
end
|
145
145
|
|
146
|
-
def overlaps?(range)
|
147
|
-
range.include?(first) or include?(range.first)
|
146
|
+
def overlaps?( range )
|
147
|
+
range.include?( first ) or include?( range.first )
|
148
148
|
end
|
149
149
|
|
150
|
-
def disjoint?(range)
|
151
|
-
not overlaps?(range)
|
150
|
+
def disjoint?( range )
|
151
|
+
not overlaps?( range )
|
152
152
|
end
|
153
153
|
|
154
154
|
end
|
155
|
-
|
data/lib/antlr3/version.rb
CHANGED
@@ -11,7 +11,7 @@ module ANTLR3
|
|
11
11
|
ANTLR_MINOR_VERSION = 2
|
12
12
|
ANTLR_PATCH_VERSION = 1
|
13
13
|
ANTLR_VERSION = [ ANTLR_MAJOR_VERSION, ANTLR_MINOR_VERSION, ANTLR_PATCH_VERSION ].freeze
|
14
|
-
ANTLR_VERSION_STRING = ANTLR_VERSION.join('.')
|
14
|
+
ANTLR_VERSION_STRING = ANTLR_VERSION.join( '.' )
|
15
15
|
ANTLR_VERSION_STRING.chomp!( '.0' ) # versioning drops minor version at 0
|
16
16
|
ANTLR_VERSION_STRING.freeze
|
17
17
|
|
@@ -20,8 +20,8 @@ module ANTLR3
|
|
20
20
|
#
|
21
21
|
MAJOR_VERSION = 1
|
22
22
|
MINOR_VERSION = 6
|
23
|
-
PATCH_VERSION =
|
23
|
+
PATCH_VERSION = 3
|
24
24
|
VERSION = [ MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION ]
|
25
|
-
VERSION_STRING = VERSION.join('.').freeze
|
25
|
+
VERSION_STRING = VERSION.join( '.' ).freeze
|
26
26
|
|
27
27
|
end
|
data/templates/Ruby.stg
CHANGED
data/test/unit/test-streams.rb
CHANGED
@@ -10,7 +10,7 @@ include ANTLR3
|
|
10
10
|
|
11
11
|
class TestStringStream < Test::Unit::TestCase
|
12
12
|
def setup
|
13
|
-
@stream = StringStream.new("oh\nhey!\n")
|
13
|
+
@stream = StringStream.new( "oh\nhey!\n" )
|
14
14
|
end
|
15
15
|
|
16
16
|
def test_size
|
@@ -202,6 +202,7 @@ class TestFileStream < Test::Unit::TestCase
|
|
202
202
|
|
203
203
|
|
204
204
|
def test_no_encoding
|
205
|
+
|
205
206
|
path = File.join(File.dirname(__FILE__), 'sample-input/file-stream-1')
|
206
207
|
@stream = FileStream.new(path)
|
207
208
|
|
@@ -253,23 +254,23 @@ class TestCommonTokenStream < Test::Unit::TestCase
|
|
253
254
|
# vvvvvvvv tests vvvvvvvvv
|
254
255
|
def test_init
|
255
256
|
@source = MockSource.new
|
256
|
-
@stream = CommonTokenStream.new(@source)
|
257
|
+
@stream = CommonTokenStream.new( @source )
|
257
258
|
@stream.position.should == 0
|
258
259
|
end
|
259
260
|
|
260
261
|
def test_rebuild
|
261
262
|
@source1 = MockSource.new
|
262
263
|
@source2 = MockSource.new
|
263
|
-
@source2.tokens << new_token(10, :channel => ANTLR3::HIDDEN) << new_token(11)
|
264
|
-
@stream = CommonTokenStream.new(@source1)
|
264
|
+
@source2.tokens << new_token( 10, :channel => ANTLR3::HIDDEN ) << new_token( 11 )
|
265
|
+
@stream = CommonTokenStream.new( @source1 )
|
265
266
|
|
266
267
|
@stream.position.should == 0
|
267
|
-
@stream.tokens.should
|
268
|
+
@stream.tokens.length.should == 0
|
268
269
|
|
269
|
-
@stream.rebuild(@source2)
|
270
|
+
@stream.rebuild( @source2 )
|
270
271
|
@stream.token_source.should == @source2
|
271
272
|
@stream.position.should == 1
|
272
|
-
@stream.tokens.should have(2).things
|
273
|
+
@stream.tokens.should have( 2 ).things
|
273
274
|
end
|
274
275
|
|
275
276
|
def test_look_empty_source
|
@@ -326,7 +327,7 @@ class TestCommonTokenStream < Test::Unit::TestCase
|
|
326
327
|
@source = MockSource.new
|
327
328
|
@source.tokens << new_token(12) << new_token(13)
|
328
329
|
@stream = CommonTokenStream.new(@source)
|
329
|
-
@stream.look(0).should
|
330
|
+
@stream.look(0).should == nil
|
330
331
|
end
|
331
332
|
|
332
333
|
def test_lb_beyond_begin
|
@@ -337,9 +338,9 @@ class TestCommonTokenStream < Test::Unit::TestCase
|
|
337
338
|
new_token(13)
|
338
339
|
@stream = CommonTokenStream.new(@source)
|
339
340
|
|
340
|
-
@stream.look(-1).should
|
341
|
+
@stream.look(-1).should == nil
|
341
342
|
2.times { @stream.consume }
|
342
|
-
@stream.look(-3).should
|
343
|
+
@stream.look(-3).should == nil
|
343
344
|
end
|
344
345
|
|
345
346
|
def test_fill_buffer
|
data/test/unit/test-template.rb
CHANGED
@@ -12,237 +12,239 @@ SAMPLE_GROUP_FILE = File.join(
|
|
12
12
|
File.dirname( __FILE__ ), 'sample-input', 'template-group'
|
13
13
|
)
|
14
14
|
|
15
|
-
describe Template do
|
15
|
+
describe Template::Context do
|
16
|
+
example "creating an empty context" do
|
17
|
+
context = Template::Context.new
|
18
|
+
context.instance_variables.should be_empty
|
19
|
+
end
|
16
20
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
example "creating a context with a variable map" do
|
24
|
-
context = Template::Context.new(
|
25
|
-
:a => 1, :b => 2
|
26
|
-
)
|
27
|
-
|
28
|
-
vars = context.instance_variables.map { | i | i.to_s }
|
29
|
-
vars.should include( '@a' )
|
30
|
-
vars.should include( '@b' )
|
31
|
-
|
32
|
-
context.instance_variable_get( '@a' ).should == 1
|
33
|
-
context.instance_variable_get( '@b' ).should == 2
|
34
|
-
end
|
21
|
+
example "creating a context with a variable map" do
|
22
|
+
context = Template::Context.new(
|
23
|
+
:a => 1, :b => 2
|
24
|
+
)
|
35
25
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
)
|
40
|
-
|
41
|
-
context[ :a ].should == 1
|
42
|
-
context[ 'a' ].should == 1
|
43
|
-
context[ :b ].should == 2
|
44
|
-
context[ 'b' ].should == 2
|
45
|
-
end
|
26
|
+
vars = context.instance_variables.map { | i | i.to_s }
|
27
|
+
vars.should include( '@a' )
|
28
|
+
vars.should include( '@b' )
|
46
29
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
30
|
+
context.instance_variable_get( '@a' ).should == 1
|
31
|
+
context.instance_variable_get( '@b' ).should == 2
|
32
|
+
end
|
33
|
+
|
34
|
+
example "fetching variable values from []" do
|
35
|
+
context = Template::Context.new(
|
36
|
+
:a => 1, :b => 2
|
37
|
+
)
|
38
|
+
|
39
|
+
context[ :a ].should == 1
|
40
|
+
context[ 'a' ].should == 1
|
41
|
+
context[ :b ].should == 2
|
42
|
+
context[ 'b' ].should == 2
|
43
|
+
end
|
44
|
+
|
45
|
+
example "defining variables with []=" do
|
46
|
+
context = Template::Context.new( :a => 3 )
|
47
|
+
context[ :a ] = 1
|
48
|
+
context[ 'b' ] = 2
|
55
49
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
50
|
+
context.instance_variable_get( '@a' ).should == 1
|
51
|
+
context.instance_variable_get( '@b' ).should == 2
|
52
|
+
end
|
53
|
+
|
54
|
+
example "using method missing to assign values" do
|
55
|
+
context = Template::Context.new( :a => 3 )
|
56
|
+
context.a = 1
|
57
|
+
context.b = 2
|
64
58
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
59
|
+
context.instance_variable_get( '@a' ).should == 1
|
60
|
+
context.instance_variable_get( '@b' ).should == 2
|
61
|
+
end
|
62
|
+
|
63
|
+
example "using method missing to get variable values" do
|
64
|
+
context = Template::Context.new( :a => 1, :b => 2)
|
71
65
|
|
66
|
+
context.a.should == 1
|
67
|
+
context.b.should == 2
|
72
68
|
end
|
73
69
|
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
shared_examples_for "template groups" do
|
74
|
+
include ANTLR3::Util
|
74
75
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
template_class.should be_a_kind_of Class
|
90
|
-
template_class.superclass.should equal Template::Context
|
91
|
-
template_class.should be < @group # it should include the group module
|
92
|
-
end
|
76
|
+
example "template definitions" do
|
77
|
+
templates = @group.templates
|
78
|
+
templates.should_not be_empty
|
79
|
+
templates.should equal @group::TEMPLATES
|
80
|
+
|
81
|
+
names = templates.keys
|
82
|
+
|
83
|
+
names.should have(3).things
|
84
|
+
for template_name in TEMPLATE_NAMES
|
85
|
+
names.should include template_name
|
86
|
+
template_class = templates[ template_name ]
|
87
|
+
template_class.should be_a_kind_of Class
|
88
|
+
template_class.superclass.should equal Template::Context
|
89
|
+
template_class.should be < @group # it should include the group module
|
93
90
|
end
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
@group.template_defined?( :somethign_else ).should be_false
|
91
|
+
end
|
92
|
+
|
93
|
+
example "template_defined?( name ) should verify whether a template is defined in a group" do
|
94
|
+
for name in TEMPLATE_NAMES
|
95
|
+
@group.template_defined?( name ).should be_true
|
96
|
+
@group.template_defined?( name.to_s ).should be_true
|
102
97
|
end
|
103
98
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
99
|
+
@group.template_defined?( :something_else ).should be_false
|
100
|
+
end
|
101
|
+
|
102
|
+
example "template method definitions" do
|
103
|
+
for name in TEMPLATE_NAMES
|
104
|
+
@group.should respond_to( name )
|
105
|
+
@group.should respond_to( "#{ name }!" )
|
106
|
+
if RUBY_VERSION =~ /^1\.9/
|
107
|
+
@group.private_instance_methods.should include name.to_sym
|
108
|
+
@group.private_instance_methods.should include :"#{ name }!"
|
109
|
+
else
|
108
110
|
@group.private_instance_methods.should include name.to_s
|
109
111
|
@group.private_instance_methods.should include "#{ name }!"
|
110
112
|
end
|
111
113
|
end
|
112
|
-
|
113
|
-
example "template method operation" do
|
114
|
-
value = @group.class_definition
|
115
|
-
value.should be_a_kind_of Template::Context
|
116
|
-
|
117
|
-
value = @group.class_definition!
|
118
|
-
value.should be_a_kind_of String
|
119
|
-
|
120
|
-
value = @group.attribute( :name => 'a' )
|
121
|
-
value.should be_a_kind_of Template::Context
|
122
|
-
end
|
123
114
|
end
|
124
115
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
before :each do
|
129
|
-
@group = Template::Group.new do
|
130
|
-
extend ANTLR3::Util
|
131
|
-
define_template( :class_definition, tidy( <<-'END'.chomp ) )
|
132
|
-
| class <%= @name %><% if @superclass %> < <%= @superclass %><% end %>
|
133
|
-
| % if @attributes
|
134
|
-
|
|
135
|
-
| % for attr, access in @attributes
|
136
|
-
| <%= attribute( :name => attr, :access => ( access || 'rw' ) ).to_s.chomp %>
|
137
|
-
| % end
|
138
|
-
| % end
|
139
|
-
| % if @methods
|
140
|
-
| % for method in ( @methods || [] )
|
141
|
-
| <%= method( method ) %>
|
142
|
-
| % end
|
143
|
-
| % end
|
144
|
-
| end
|
145
|
-
END
|
146
|
-
|
147
|
-
define_template( :attribute, tidy( <<-'END'.chomp ) )
|
148
|
-
| % case @access.to_s.downcase
|
149
|
-
| % when 'r'
|
150
|
-
| attr_reader :<%= @name %>
|
151
|
-
| % when 'w'
|
152
|
-
| attr_writer :<%= @name %>
|
153
|
-
| % else
|
154
|
-
| attr_accessor :<%= @name %>
|
155
|
-
| % end
|
156
|
-
END
|
157
|
-
|
158
|
-
define_template( :method, tidy( <<-'END'.chomp ) )
|
159
|
-
|
|
160
|
-
| def <%= @name %><% if @arguments and not @arguments.empty? %>( <%= @arguments.join( ', ' ) %> )<% end %>
|
161
|
-
| <%= @body.gsub( /^/, ' ' ) %>
|
162
|
-
| end
|
163
|
-
END
|
164
|
-
end
|
165
|
-
end
|
116
|
+
example "template method operation" do
|
117
|
+
value = @group.class_definition
|
118
|
+
value.should be_a_kind_of Template::Context
|
166
119
|
|
167
|
-
|
120
|
+
value = @group.class_definition!
|
121
|
+
value.should be_a_kind_of String
|
168
122
|
|
169
|
-
|
170
|
-
|
171
|
-
%w( family ),
|
172
|
-
%w( name r )
|
173
|
-
]
|
174
|
-
|
175
|
-
methods = [
|
176
|
-
MethodDescription.new( 'eat', %q[puts( "ate %s %s" % [ number, @name ] )], %w( number ) ),
|
177
|
-
MethodDescription.new( :to_s, '@name.to_s.dup' )
|
178
|
-
]
|
179
|
-
|
180
|
-
vegetable = @group.class_definition(
|
181
|
-
:name => 'Vegetable',
|
182
|
-
:superclass => 'Food',
|
183
|
-
:attributes => attributes,
|
184
|
-
:methods => methods
|
185
|
-
)
|
186
|
-
|
187
|
-
vegetable.to_s.should == tidy( <<-END.chomp )
|
188
|
-
| class Vegetable < Food
|
189
|
-
|
|
190
|
-
| attr_accessor :family
|
191
|
-
| attr_reader :name
|
192
|
-
|
|
193
|
-
| def eat( number )
|
194
|
-
| puts( "ate %s %s" % [ number, @name ] )
|
195
|
-
| end
|
196
|
-
|
|
197
|
-
| def to_s
|
198
|
-
| @name.to_s.dup
|
199
|
-
| end
|
200
|
-
| end
|
201
|
-
END
|
202
|
-
end
|
123
|
+
value = @group.attribute( :name => 'a' )
|
124
|
+
value.should be_a_kind_of Template::Context
|
203
125
|
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe Template::Group, "dynamic template definition" do
|
129
|
+
include ANTLR3::Util
|
204
130
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
131
|
+
before :each do
|
132
|
+
@group = Template::Group.new do
|
133
|
+
extend ANTLR3::Util
|
134
|
+
define_template( :class_definition, tidy( <<-'END'.chomp ) )
|
135
|
+
| class <%= @name %><% if @superclass %> < <%= @superclass %><% end %>
|
136
|
+
| % if @attributes
|
137
|
+
|
|
138
|
+
| % for attr, access in @attributes
|
139
|
+
| <%= attribute( :name => attr, :access => ( access || 'rw' ) ).to_s.chomp %>
|
140
|
+
| % end
|
141
|
+
| % end
|
142
|
+
| % if @methods
|
143
|
+
| % for method in ( @methods || [] )
|
144
|
+
| <%= method( method ) %>
|
145
|
+
| % end
|
146
|
+
| % end
|
147
|
+
| end
|
148
|
+
END
|
222
149
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
150
|
+
define_template( :attribute, tidy( <<-'END'.chomp ) )
|
151
|
+
| % case @access.to_s.downcase
|
152
|
+
| % when 'r'
|
153
|
+
| attr_reader :<%= @name %>
|
154
|
+
| % when 'w'
|
155
|
+
| attr_writer :<%= @name %>
|
156
|
+
| % else
|
157
|
+
| attr_accessor :<%= @name %>
|
158
|
+
| % end
|
159
|
+
END
|
229
160
|
|
230
|
-
|
231
|
-
| class Vegetable < Food
|
232
|
-
|
|
233
|
-
| attr_accessor :family
|
234
|
-
| attr_reader :name
|
161
|
+
define_template( :method, tidy( <<-'END'.chomp ) )
|
235
162
|
|
|
236
|
-
| def
|
237
|
-
|
|
163
|
+
| def <%= @name %><% if @arguments and not @arguments.empty? %>( <%= @arguments.join( ', ' ) %> )<% end %>
|
164
|
+
| <%= @body.gsub( /^/, ' ' ) %>
|
238
165
|
| end
|
239
|
-
|
|
240
|
-
| def to_s
|
241
|
-
| @name.to_s.dup
|
242
|
-
| end
|
243
|
-
| end
|
244
166
|
END
|
245
167
|
end
|
246
|
-
|
247
168
|
end
|
169
|
+
|
170
|
+
it_should_behave_like "template groups"
|
171
|
+
|
172
|
+
example "template object string rendering" do
|
173
|
+
attributes = [
|
174
|
+
%w( family ),
|
175
|
+
%w( name r )
|
176
|
+
]
|
177
|
+
|
178
|
+
methods = [
|
179
|
+
MethodDescription.new( 'eat', %q[puts( "ate %s %s" % [ number, @name ] )], %w( number ) ),
|
180
|
+
MethodDescription.new( :to_s, '@name.to_s.dup' )
|
181
|
+
]
|
182
|
+
|
183
|
+
vegetable = @group.class_definition(
|
184
|
+
:name => 'Vegetable',
|
185
|
+
:superclass => 'Food',
|
186
|
+
:attributes => attributes,
|
187
|
+
:methods => methods
|
188
|
+
)
|
189
|
+
|
190
|
+
vegetable.to_s.should == tidy( <<-END.chomp )
|
191
|
+
| class Vegetable < Food
|
192
|
+
|
|
193
|
+
| attr_accessor :family
|
194
|
+
| attr_reader :name
|
195
|
+
|
|
196
|
+
| def eat( number )
|
197
|
+
| puts( "ate %s %s" % [ number, @name ] )
|
198
|
+
| end
|
199
|
+
|
|
200
|
+
| def to_s
|
201
|
+
| @name.to_s.dup
|
202
|
+
| end
|
203
|
+
| end
|
204
|
+
END
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
describe Template::Group, "loading a template definition file" do
|
209
|
+
before :each do
|
210
|
+
@group = Template::Group.load( SAMPLE_GROUP_FILE )
|
211
|
+
end
|
212
|
+
|
213
|
+
it_should_behave_like "template groups"
|
214
|
+
|
215
|
+
example "template object string rendering" do
|
216
|
+
attributes = [
|
217
|
+
%w( family ),
|
218
|
+
%w( name r )
|
219
|
+
]
|
220
|
+
|
221
|
+
methods = [
|
222
|
+
MethodDescription.new( 'eat', %q[puts( "ate %s %s" % [ number, @name ] )], %w( number ) ),
|
223
|
+
MethodDescription.new( :to_s, '@name.to_s.dup' )
|
224
|
+
]
|
225
|
+
|
226
|
+
vegetable = @group.class_definition(
|
227
|
+
:name => 'Vegetable',
|
228
|
+
:superclass => 'Food',
|
229
|
+
:attributes => attributes,
|
230
|
+
:methods => methods
|
231
|
+
)
|
232
|
+
|
233
|
+
vegetable.to_s.should == tidy( <<-END.chomp )
|
234
|
+
| class Vegetable < Food
|
235
|
+
|
|
236
|
+
| attr_accessor :family
|
237
|
+
| attr_reader :name
|
238
|
+
|
|
239
|
+
| def eat( number )
|
240
|
+
| puts( "ate %s %s" % [ number, @name ] )
|
241
|
+
| end
|
242
|
+
|
|
243
|
+
| def to_s
|
244
|
+
| @name.to_s.dup
|
245
|
+
| end
|
246
|
+
| end
|
247
|
+
END
|
248
|
+
end
|
249
|
+
|
248
250
|
end
|