antlr3 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/ANTLR-LICENSE.txt +26 -0
  2. data/History.txt +66 -0
  3. data/README.txt +139 -0
  4. data/bin/antlr4ruby +33 -0
  5. data/java/RubyTarget.java +524 -0
  6. data/java/antlr-full-3.2.1.jar +0 -0
  7. data/lib/antlr3.rb +176 -0
  8. data/lib/antlr3/constants.rb +88 -0
  9. data/lib/antlr3/debug.rb +701 -0
  10. data/lib/antlr3/debug/event-hub.rb +210 -0
  11. data/lib/antlr3/debug/record-event-listener.rb +25 -0
  12. data/lib/antlr3/debug/rule-tracer.rb +55 -0
  13. data/lib/antlr3/debug/socket.rb +360 -0
  14. data/lib/antlr3/debug/trace-event-listener.rb +92 -0
  15. data/lib/antlr3/dfa.rb +247 -0
  16. data/lib/antlr3/dot.rb +174 -0
  17. data/lib/antlr3/error.rb +657 -0
  18. data/lib/antlr3/main.rb +561 -0
  19. data/lib/antlr3/modes/ast-builder.rb +41 -0
  20. data/lib/antlr3/modes/filter.rb +56 -0
  21. data/lib/antlr3/profile.rb +322 -0
  22. data/lib/antlr3/recognizers.rb +1280 -0
  23. data/lib/antlr3/streams.rb +985 -0
  24. data/lib/antlr3/streams/interactive.rb +91 -0
  25. data/lib/antlr3/streams/rewrite.rb +412 -0
  26. data/lib/antlr3/test/call-stack.rb +57 -0
  27. data/lib/antlr3/test/config.rb +23 -0
  28. data/lib/antlr3/test/core-extensions.rb +269 -0
  29. data/lib/antlr3/test/diff.rb +165 -0
  30. data/lib/antlr3/test/functional.rb +207 -0
  31. data/lib/antlr3/test/grammar.rb +371 -0
  32. data/lib/antlr3/token.rb +592 -0
  33. data/lib/antlr3/tree.rb +1415 -0
  34. data/lib/antlr3/tree/debug.rb +163 -0
  35. data/lib/antlr3/tree/visitor.rb +84 -0
  36. data/lib/antlr3/tree/wizard.rb +481 -0
  37. data/lib/antlr3/util.rb +149 -0
  38. data/lib/antlr3/version.rb +27 -0
  39. data/samples/ANTLRv3Grammar.g +621 -0
  40. data/samples/Cpp.g +749 -0
  41. data/templates/AST.stg +335 -0
  42. data/templates/ASTDbg.stg +40 -0
  43. data/templates/ASTParser.stg +153 -0
  44. data/templates/ASTTreeParser.stg +272 -0
  45. data/templates/Dbg.stg +192 -0
  46. data/templates/Ruby.stg +1514 -0
  47. data/test/functional/ast-output/auto-ast.rb +797 -0
  48. data/test/functional/ast-output/construction.rb +555 -0
  49. data/test/functional/ast-output/hetero-nodes.rb +753 -0
  50. data/test/functional/ast-output/rewrites.rb +1327 -0
  51. data/test/functional/ast-output/tree-rewrite.rb +1662 -0
  52. data/test/functional/debugging/debug-mode.rb +689 -0
  53. data/test/functional/debugging/profile-mode.rb +165 -0
  54. data/test/functional/debugging/rule-tracing.rb +74 -0
  55. data/test/functional/delegation/import.rb +379 -0
  56. data/test/functional/lexer/basic.rb +559 -0
  57. data/test/functional/lexer/filter-mode.rb +245 -0
  58. data/test/functional/lexer/nuances.rb +47 -0
  59. data/test/functional/lexer/properties.rb +104 -0
  60. data/test/functional/lexer/syn-pred.rb +32 -0
  61. data/test/functional/lexer/xml.rb +206 -0
  62. data/test/functional/main/main-scripts.rb +245 -0
  63. data/test/functional/parser/actions.rb +224 -0
  64. data/test/functional/parser/backtracking.rb +244 -0
  65. data/test/functional/parser/basic.rb +282 -0
  66. data/test/functional/parser/calc.rb +98 -0
  67. data/test/functional/parser/ll-star.rb +143 -0
  68. data/test/functional/parser/nuances.rb +165 -0
  69. data/test/functional/parser/predicates.rb +103 -0
  70. data/test/functional/parser/properties.rb +242 -0
  71. data/test/functional/parser/rule-methods.rb +132 -0
  72. data/test/functional/parser/scopes.rb +274 -0
  73. data/test/functional/token-rewrite/basic.rb +318 -0
  74. data/test/functional/token-rewrite/via-parser.rb +100 -0
  75. data/test/functional/tree-parser/basic.rb +750 -0
  76. data/test/unit/sample-input/file-stream-1 +2 -0
  77. data/test/unit/sample-input/teststreams.input2 +2 -0
  78. data/test/unit/test-dfa.rb +52 -0
  79. data/test/unit/test-exceptions.rb +44 -0
  80. data/test/unit/test-recognizers.rb +55 -0
  81. data/test/unit/test-scheme.rb +62 -0
  82. data/test/unit/test-streams.rb +459 -0
  83. data/test/unit/test-tree-wizard.rb +535 -0
  84. data/test/unit/test-trees.rb +854 -0
  85. metadata +205 -0
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+
4
+ module ANTLR3
5
+ module Debug
6
+ =begin rdoc ANTLR3::Debug::EventListener
7
+
8
+ A listener that simply records text representations of the events.
9
+ Useful for debugging the debugging facility ;)
10
+ Subclasses can override the record() method (which defaults to printing to
11
+ stdout) to record the events in a different way.
12
+
13
+ =end
14
+ class TraceEventListener
15
+ include EventListener
16
+
17
+ def initialize(adaptor = nil, device = $stderr)
18
+ super()
19
+ @device = device
20
+ @adaptor = adaptor ||= ANTLR3::AST::CommonTreeAdaptor.new
21
+ end
22
+
23
+ def record(event_message, *interpolation_arguments)
24
+ event_message = event_message.to_s << "\n"
25
+ @device.printf(event_message, *interpolation_arguments)
26
+ end
27
+
28
+ def enter_alternative( alt_number )
29
+ record "(%s): number=%s", __method__, alt_number
30
+ end
31
+
32
+ def enter_rule( grammar_file_name, rule_name )
33
+ record "(%s): rule=%s", __method__, rule_name
34
+ end
35
+
36
+ def exit_rule( grammar_file_name, rule_name )
37
+ record "(%s): rule=%s", __method__, rule_name
38
+ end
39
+
40
+ def enter_subrule( decision_number )
41
+ record "(%s): decision=%s", __method__, decision_number
42
+ end
43
+
44
+ def exit_subrule( decision_number )
45
+ record "(%s): decision=%s", __method__, decision_number
46
+ end
47
+
48
+ def location( line, position )
49
+ record '(%s): line=%s position=%s', __method__, line, position
50
+ end
51
+
52
+ def consume_node( tree )
53
+ record '(%s) unique_id=%s text=%p type=%s[%s]', __method__, @adaptor.unique_id(tree),
54
+ @adaptor.text_of(tree), @adaptor.type_name( tree ), @adaptor.type_of(tree)
55
+ end
56
+
57
+ def look(i, tree)
58
+ record '(%s): k=%s unique_id=%s text=%p type=%s[%s]', __method__, i, @adaptor.unique_id( tree ),
59
+ @adaptor.text_of( tree ), @adaptor.type_name( tree ), @adaptor.type_of( tree )
60
+ end
61
+
62
+ def flat_node( tree )
63
+ record '(%s): unique_id=%s', __method__, @adaptor.unique_id( tree )
64
+ end
65
+
66
+ def create_node(tree, token = nil)
67
+ unless token
68
+ record '(%s): unique_id=%s text=%p type=%s[%s]', __method__, @adaptor.unique_id( tree ),
69
+ @adaptor.text_of( tree ), @adaptor.type_name( tree ), @adaptor.type_of( tree )
70
+ else
71
+ record '(%s): unique_id=%s type=%s[%s]', __method__, @adaptor.unique_id( tree ),
72
+ @adaptor.type_of( tree ), @adaptor.type_name( tree ), @adaptor.type_of( tree )
73
+ end
74
+ end
75
+
76
+ def become_root( new_root, old_root )
77
+ record '(%s): old_root_id=%s new_root_id=%s', __method__, @adaptor.unique_id( new_root ),
78
+ @adaptor.unique_id( old_root )
79
+ end
80
+
81
+ def add_child( root, child )
82
+ record '(%s): root_id=%s child_id=%s', __method__, @adaptor.unique_id( root ),
83
+ @adaptor.unique_id( child )
84
+ end
85
+
86
+ def set_token_boundaries( tree, token_start_index, token_stop_index )
87
+ record '(%s): unique_id=%s index_range=%s..%s', __method__, @adaptor.unique_id( tree ),
88
+ token_start_index, token_stop_index
89
+ end
90
+ end # class TraceEventListener
91
+ end # module Debug
92
+ end # module ANTLR3
@@ -0,0 +1,247 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+
4
+ =begin LICENSE
5
+
6
+ [The "BSD licence"]
7
+ Copyright (c) 2009 Kyle Yetter
8
+ All rights reserved.
9
+
10
+ Redistribution and use in source and binary forms, with or without
11
+ modification, are permitted provided that the following conditions
12
+ are met:
13
+
14
+ 1. Redistributions of source code must retain the above copyright
15
+ notice, this list of conditions and the following disclaimer.
16
+ 2. Redistributions in binary form must reproduce the above copyright
17
+ notice, this list of conditions and the following disclaimer in the
18
+ documentation and/or other materials provided with the distribution.
19
+ 3. The name of the author may not be used to endorse or promote products
20
+ derived from this software without specific prior written permission.
21
+
22
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+
33
+ =end
34
+
35
+ module ANTLR3
36
+
37
+ =begin rdoc ANTLR3::DFA
38
+
39
+ DFA is a class that implements a finite state machine that chooses between
40
+ alternatives in a rule based upon lookahead symbols from an input stream.
41
+
42
+ Deterministic Finite Automata (DFA) are finite state machines that are capable
43
+ of recognizing <i>regular languages</i>. For more background on the subject,
44
+ check out http://en.wikipedia.org/wiki/Deterministic_finite-state_machine or
45
+ check out general ANTLR documentation at http://www.antlr.org
46
+
47
+ ANTLR implements most of its decision logic directly using code branching
48
+ structures in methods. However, for certain types of decisions, ANTLR will
49
+ generate a special DFA class definition to implement a decision.
50
+
51
+ Conceptually, these state machines are defined by a number of states, each state
52
+ represented by an integer indexed upward from zero. State number +0+ is the
53
+ <i>start state</i> of the machine; every prediction will begin in state +0+. At
54
+ each step, the machine examines the next symbol on the input stream, checks the
55
+ value against the transition parameters associated with the current state, and
56
+ either moves to a new state number to repeat the process or decides that the
57
+ machine cannot transition any further. If the machine cannot transition any
58
+ further and the current state is defined as an <i>accept state</i>, an
59
+ alternative has been chosen successfully and the prediction procedure ends. If
60
+ the current state is not an <i>accept state</i>, the prediction has failed and
61
+ there is <i>no viable alternative</i>.
62
+
63
+ In generated code, ANTLR defines DFA states using seven parameters, each defined
64
+ as a member of seven seperate array constants -- +MIN+, +MAX+, +EOT+, +EOF+,
65
+ +SPECIAL+, +ACCEPT+, and +TRANSITION+. The parameters that characterize state
66
+ +s+ are defined by the value of these lists at index +s+.
67
+
68
+ MIN[s]::
69
+ The smallest value of the next input symbol that has
70
+ a transition for state +s+
71
+ MAX[s]::
72
+ The largest value of the next input symbol that has
73
+ a transition for state +s+
74
+ TRANSITION[s]::
75
+ A list that defines the next state number based upon
76
+ the current input symbol.
77
+ EOT[s]::
78
+ If positive, it specifies a state transition in
79
+ situations where a non-matching input symbol does
80
+ not indicate failure.
81
+ SPECIAL[s]::
82
+ If positive, it indicates that the prediction
83
+ algorithm must defer to a special code block
84
+ to determine the next state. The value is used
85
+ by the special state code to determine the next
86
+ state.
87
+ ACCEPT[s]::
88
+ If positive and there are no possible state
89
+ transitions, this is the alternative number
90
+ that has been predicted
91
+ EOF[s]::
92
+ If positive and the input stream has been exhausted,
93
+ this is the alternative number that has been predicted.
94
+
95
+ For more information on the prediction algorithm, check out the #predict method
96
+ below.
97
+
98
+ =end
99
+
100
+ class DFA
101
+ include Constants
102
+ include Error
103
+
104
+ attr_reader :recognizer, :decision_number, :eot, :eof, :min, :max,
105
+ :accept, :special, :transition, :special_block
106
+
107
+ class << self
108
+ attr_reader :decision
109
+
110
+ def unpack(*data)
111
+ data.empty? and return [].freeze
112
+
113
+ n = data.length / 2
114
+ size = 0
115
+ n.times { |i| size += data[2*i] }
116
+ if size > 1024
117
+ values = Hash.new(0)
118
+ data.each_slice(2) do |count, value|
119
+ values[value] += count
120
+ end
121
+ default = values.keys.max_by { |v| values[v] }
122
+
123
+ unpacked = Hash.new(default)
124
+ position = 0
125
+ data.each_slice(2) do |count, value|
126
+ unless value == default
127
+ count.times { |i| unpacked[position + i] = value }
128
+ end
129
+ position += count
130
+ end
131
+ else
132
+ unpacked = []
133
+ data.each_slice(2) do |count, value|
134
+ unpacked.concat Array.new(count, value)
135
+ end
136
+ end
137
+
138
+ return unpacked.freeze
139
+ end
140
+ end
141
+
142
+ def initialize(recognizer, decision_number = nil, eot = nil, eof = nil,
143
+ min = nil, max = nil, accept = nil, special = nil,
144
+ transition = nil, &special_block)
145
+ @recognizer = recognizer
146
+ @decision_number = decision_number || self.class.decision
147
+ @eot = eot || self.class::EOT
148
+ @eof = eof || self.class::EOF
149
+ @min = min || self.class::MIN
150
+ @max = max || self.class::MAX
151
+ @accept = accept || self.class::ACCEPT
152
+ @special = special || self.class::SPECIAL
153
+ @transition = transition || self.class::TRANSITION
154
+ @special_block = special_block
155
+ rescue NameError => e
156
+ raise unless e.message =~ /uninitialized constant/
157
+ constant = e.name
158
+ message = Util.tidy( <<-END )
159
+ | No #{constant} information provided.
160
+ | DFA cannot be instantiated without providing state array information.
161
+ | When DFAs are generated by ANTLR, this information should already be
162
+ | provided in the DFA subclass constants.
163
+ END
164
+ end
165
+
166
+ def predict(input)
167
+ mark = input.mark
168
+ state = 0
169
+
170
+ 50000.times do
171
+ special_state = @special[state]
172
+ if special_state >= 0
173
+ state = @special_block.call(special_state)
174
+ if state == -1
175
+ no_viable_alternative(state, input)
176
+ return 0
177
+ end
178
+ input.consume
179
+ next
180
+ end
181
+ @accept[state] >= 1 and return @accept[state]
182
+
183
+ # look for a normal char transition
184
+
185
+ c = input.peek
186
+ # the @min and @max arrays contain the bounds of the character (or token type)
187
+ # ranges for the transition decisions
188
+ if c.between?(@min[state], @max[state])
189
+ # c - @min[state] is the position of the character within the range
190
+ # so for a range like ?a..?z, a match of ?a would be 0,
191
+ # ?c would be 2, and ?z would be 25
192
+ next_state = @transition[state][c - @min[state]]
193
+ if next_state < 0
194
+ if @eot[state] >= 0
195
+ state = @eot[state]
196
+ input.consume
197
+ next
198
+ end
199
+ no_viable_alternative(state, input)
200
+ return 0
201
+ end
202
+
203
+ state = next_state
204
+ input.consume()
205
+ next
206
+ end
207
+ if @eot[state] >= 0
208
+ state = @eot[state]
209
+ input.consume()
210
+ next
211
+ end
212
+ (c == EOF && @eof[state] >= 0) and return @accept[@eof[state]]
213
+ no_viable_alternative(state, input)
214
+ return 0
215
+ end
216
+
217
+ ANTLR3.bug!( Util.tidy(<<-END) )
218
+ | DFA BANG!
219
+ | The prediction loop has exceeded a maximum limit of 50000 iterations
220
+ | ----
221
+ | decision: #@decision_number
222
+ | description: #{description}
223
+ END
224
+ ensure
225
+ input.rewind(mark)
226
+ end
227
+
228
+ def no_viable_alternative(state, input)
229
+ raise(BacktrackingFailed) if @recognizer.state.backtracking > 0
230
+ except = NoViableAlternative.new(description, @decision_number, state, input)
231
+ error(except)
232
+ raise(except)
233
+ end
234
+
235
+ def error(except)
236
+ # overridable debugging hook
237
+ end
238
+
239
+ def special_state_transition(state, input)
240
+ return -1
241
+ end
242
+
243
+ def description
244
+ return "n/a"
245
+ end
246
+ end
247
+ end
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+
4
+ =begin LICENSE
5
+
6
+ [The "BSD licence"]
7
+ Copyright (c) 2009 Kyle Yetter
8
+ All rights reserved.
9
+
10
+ Redistribution and use in source and binary forms, with or without
11
+ modification, are permitted provided that the following conditions
12
+ are met:
13
+
14
+ 1. Redistributions of source code must retain the above copyright
15
+ notice, this list of conditions and the following disclaimer.
16
+ 2. Redistributions in binary form must reproduce the above copyright
17
+ notice, this list of conditions and the following disclaimer in the
18
+ documentation and/or other materials provided with the distribution.
19
+ 3. The name of the author may not be used to endorse or promote products
20
+ derived from this software without specific prior written permission.
21
+
22
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+
33
+ =end
34
+
35
+ require 'antlr3'
36
+ require 'erb'
37
+
38
+ module ANTLR3
39
+
40
+ =begin rdoc ANTLR3::DOT
41
+
42
+ An extra utility for generating graphviz DOT file representations of ANTLR
43
+ Abstract Syntax Tree nodes.
44
+
45
+ This module has been directly ported to Ruby from the ANTLR Python runtime
46
+ library.
47
+
48
+ =end
49
+
50
+ module DOT
51
+ class Context
52
+ def []=(var, value)
53
+ instance_variable_set(:"@#{var}", value)
54
+ end
55
+ def [](var)
56
+ instance_variable_get(:"@#{var}")
57
+ end
58
+
59
+ def initialize(template, vars = {})
60
+ @__template__ = template
61
+ vars.each do |var, value|
62
+ self[var] = value
63
+ end
64
+ end
65
+
66
+ def to_s
67
+ @__template__.result(binding)
68
+ end
69
+ end
70
+ class TreeGenerator
71
+ TREE_TEMPLATE = ERB.new( Util.tidy(<<-END) )
72
+ | digraph {
73
+ | ordering=out;
74
+ | ranksep=.4;
75
+ | node [shape=plaintext, fixedsize=true, fontsize=11, fontname="Courier",
76
+ | width=.25, height=.25];
77
+ | edge [arrowsize=.5];
78
+ | <%= @nodes.join("\n ") %>
79
+ | <%= @edges.join("\n ") %>
80
+ | }
81
+ END
82
+
83
+ NODE_TEMPLATE = ERB.new( Util.tidy(<<-END) )
84
+ | <%= @name %> [label="<%= @text %>"];
85
+ END
86
+
87
+ EDGE_TEMPLATE = ERB.new( Util.tidy(<<-END) )
88
+ | <%= @parent %> -> <%= @child %>; // "<%= @parent_text %>" -> "<%= @child_text %>"
89
+ END
90
+
91
+ def self.generate(tree, adaptor = nil, tree_template = TREE_TEMPLATE,
92
+ edge_template = EDGE_TEMPLATE)
93
+ new.to_dot(tree, adaptor, tree_template, edge_template)
94
+ end
95
+
96
+ def initialize
97
+ @node_number = 0
98
+ @node_to_number_map = Hash.new do |map, node|
99
+ map[node] = @node_number
100
+ @node_number += 1
101
+ @node_number - 1
102
+ end
103
+ end
104
+
105
+ def to_dot(tree, adaptor = nil, tree_template = TREE_TEMPLATE,
106
+ edge_template = EDGE_TEMPLATE)
107
+ adaptor ||= AST::CommonTreeAdaptor.new
108
+ @node_number = 0
109
+ tree_template = Context.new(tree_template, :nodes => [], :edges => [])
110
+ define_nodes( tree, adaptor, tree_template )
111
+
112
+ @node_number = 0
113
+ define_edges( tree, adaptor, tree_template, edge_template )
114
+ return tree_template.to_s
115
+ end
116
+
117
+ def define_nodes( tree, adaptor, tree_template, known_nodes = nil)
118
+ known_nodes ||= Set.new
119
+ tree.nil? and return
120
+ n = adaptor.child_count( tree )
121
+ n == 0 and return
122
+ number = node_number( tree )
123
+ unless known_nodes.include?( number )
124
+ parent_node_template = node_template_for(adaptor, child)
125
+ tree_template[:nodes] << parent_node_template
126
+ known_nodes.add( number )
127
+ end
128
+
129
+ n.times do |index|
130
+ child = adaptor.child_of( tree, index )
131
+ number = @node_to_number_map[ child ]
132
+ unless known_nodes.include?(number)
133
+ node_template = node_template_for( adaptor, child )
134
+ tree_template[:nodes] << node_template
135
+ known_nodes.add( number )
136
+ end
137
+
138
+ define_nodes(child, adaptor, tree_template, edge_template)
139
+ end
140
+ end
141
+
142
+ def define_edges( tree, adaptor, tree_template, edge_template )
143
+ tree.nil? or return
144
+
145
+ n = adaptor.child_count( tree )
146
+ n == 0 and return
147
+
148
+ parent_name = 'n%i' % @node_to_number_map[ tree ]
149
+ parent_text = adaptor.text_of( tree )
150
+ n.times do |index|
151
+ child = adaptor.child_of( tree, index )
152
+ child_text = adaptor.text_of( child )
153
+ child_name = 'n%i' % @node_to_number_map[ tree ]
154
+ edge_template = Context.new(edge_template,
155
+ :parent => parent_name, :child => child_name,
156
+ :parent_text => parent_text, :child_text => child_text
157
+ )
158
+ tree_template[:edges] << edge_template
159
+ define_edges( child, adaptor, tree_template, edge_template )
160
+ end
161
+ end
162
+
163
+ def node_template_for(adaptor, tree)
164
+ text = adaptor.text_of( tree )
165
+ node_template = Context.new(NODE_TEMPLATE)
166
+ unique_name = 'n%i' % @node_to_number_map[ tree ]
167
+ node_template[:name] = unique_name
168
+ text and text = text.gsub(/"/, '\\"')
169
+ node_template[:text] = text
170
+ return node_template
171
+ end
172
+ end
173
+ end
174
+ end