antlr3 1.2.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/ANTLR-LICENSE.txt +26 -0
- data/History.txt +66 -0
- data/README.txt +139 -0
- data/bin/antlr4ruby +33 -0
- data/java/RubyTarget.java +524 -0
- data/java/antlr-full-3.2.1.jar +0 -0
- data/lib/antlr3.rb +176 -0
- data/lib/antlr3/constants.rb +88 -0
- data/lib/antlr3/debug.rb +701 -0
- data/lib/antlr3/debug/event-hub.rb +210 -0
- data/lib/antlr3/debug/record-event-listener.rb +25 -0
- data/lib/antlr3/debug/rule-tracer.rb +55 -0
- data/lib/antlr3/debug/socket.rb +360 -0
- data/lib/antlr3/debug/trace-event-listener.rb +92 -0
- data/lib/antlr3/dfa.rb +247 -0
- data/lib/antlr3/dot.rb +174 -0
- data/lib/antlr3/error.rb +657 -0
- data/lib/antlr3/main.rb +561 -0
- data/lib/antlr3/modes/ast-builder.rb +41 -0
- data/lib/antlr3/modes/filter.rb +56 -0
- data/lib/antlr3/profile.rb +322 -0
- data/lib/antlr3/recognizers.rb +1280 -0
- data/lib/antlr3/streams.rb +985 -0
- data/lib/antlr3/streams/interactive.rb +91 -0
- data/lib/antlr3/streams/rewrite.rb +412 -0
- data/lib/antlr3/test/call-stack.rb +57 -0
- data/lib/antlr3/test/config.rb +23 -0
- data/lib/antlr3/test/core-extensions.rb +269 -0
- data/lib/antlr3/test/diff.rb +165 -0
- data/lib/antlr3/test/functional.rb +207 -0
- data/lib/antlr3/test/grammar.rb +371 -0
- data/lib/antlr3/token.rb +592 -0
- data/lib/antlr3/tree.rb +1415 -0
- data/lib/antlr3/tree/debug.rb +163 -0
- data/lib/antlr3/tree/visitor.rb +84 -0
- data/lib/antlr3/tree/wizard.rb +481 -0
- data/lib/antlr3/util.rb +149 -0
- data/lib/antlr3/version.rb +27 -0
- data/samples/ANTLRv3Grammar.g +621 -0
- data/samples/Cpp.g +749 -0
- data/templates/AST.stg +335 -0
- data/templates/ASTDbg.stg +40 -0
- data/templates/ASTParser.stg +153 -0
- data/templates/ASTTreeParser.stg +272 -0
- data/templates/Dbg.stg +192 -0
- data/templates/Ruby.stg +1514 -0
- data/test/functional/ast-output/auto-ast.rb +797 -0
- data/test/functional/ast-output/construction.rb +555 -0
- data/test/functional/ast-output/hetero-nodes.rb +753 -0
- data/test/functional/ast-output/rewrites.rb +1327 -0
- data/test/functional/ast-output/tree-rewrite.rb +1662 -0
- data/test/functional/debugging/debug-mode.rb +689 -0
- data/test/functional/debugging/profile-mode.rb +165 -0
- data/test/functional/debugging/rule-tracing.rb +74 -0
- data/test/functional/delegation/import.rb +379 -0
- data/test/functional/lexer/basic.rb +559 -0
- data/test/functional/lexer/filter-mode.rb +245 -0
- data/test/functional/lexer/nuances.rb +47 -0
- data/test/functional/lexer/properties.rb +104 -0
- data/test/functional/lexer/syn-pred.rb +32 -0
- data/test/functional/lexer/xml.rb +206 -0
- data/test/functional/main/main-scripts.rb +245 -0
- data/test/functional/parser/actions.rb +224 -0
- data/test/functional/parser/backtracking.rb +244 -0
- data/test/functional/parser/basic.rb +282 -0
- data/test/functional/parser/calc.rb +98 -0
- data/test/functional/parser/ll-star.rb +143 -0
- data/test/functional/parser/nuances.rb +165 -0
- data/test/functional/parser/predicates.rb +103 -0
- data/test/functional/parser/properties.rb +242 -0
- data/test/functional/parser/rule-methods.rb +132 -0
- data/test/functional/parser/scopes.rb +274 -0
- data/test/functional/token-rewrite/basic.rb +318 -0
- data/test/functional/token-rewrite/via-parser.rb +100 -0
- data/test/functional/tree-parser/basic.rb +750 -0
- data/test/unit/sample-input/file-stream-1 +2 -0
- data/test/unit/sample-input/teststreams.input2 +2 -0
- data/test/unit/test-dfa.rb +52 -0
- data/test/unit/test-exceptions.rb +44 -0
- data/test/unit/test-recognizers.rb +55 -0
- data/test/unit/test-scheme.rb +62 -0
- data/test/unit/test-streams.rb +459 -0
- data/test/unit/test-tree-wizard.rb +535 -0
- data/test/unit/test-trees.rb +854 -0
- metadata +205 -0
@@ -0,0 +1,210 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
module ANTLR3
|
5
|
+
module Debug
|
6
|
+
=begin rdoc ANTLR3::Debug::EventHub
|
7
|
+
|
8
|
+
A special event listener that intercepts debug events and forwards them to other
|
9
|
+
debug event listners. As debug-mode recognizers are able to send event
|
10
|
+
information to only one listener, EventHubs provide a simple solution in
|
11
|
+
situations where multiple event listners are desired.
|
12
|
+
|
13
|
+
=end
|
14
|
+
class EventHub
|
15
|
+
include ANTLR3::Debug::EventListener
|
16
|
+
attr_reader :listeners
|
17
|
+
|
18
|
+
def initialize(*listeners)
|
19
|
+
@listeners = [listeners].flatten!
|
20
|
+
@listeners.compact!
|
21
|
+
end
|
22
|
+
|
23
|
+
def add(*listeners)
|
24
|
+
@listeners.push(*listeners)
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_child(root, child)
|
28
|
+
for listener in @listeners
|
29
|
+
listener.add_child(root, child)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def backtrack(level)
|
34
|
+
for listener in @listeners
|
35
|
+
listener.backtrack(level)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def become_root(new_root, old_root)
|
40
|
+
for listener in @listeners
|
41
|
+
listener.become_root(new_root, old_root)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def begin_backtrack(level)
|
46
|
+
for listener in @listeners
|
47
|
+
listener.begin_backtrack(level)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def begin_resync()
|
52
|
+
for listener in @listeners
|
53
|
+
listener.begin_resync()
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def commence()
|
58
|
+
for listener in @listeners
|
59
|
+
listener.commence()
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def consume_hidden_token(tree)
|
64
|
+
for listener in @listeners
|
65
|
+
listener.consume_hidden_token(tree)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def consume_node(tree)
|
70
|
+
for listener in @listeners
|
71
|
+
listener.consume_node(tree)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def consume_token(tree)
|
76
|
+
for listener in @listeners
|
77
|
+
listener.consume_token(tree)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def create_node(node, token)
|
82
|
+
for listener in @listeners
|
83
|
+
listener.create_node(node, token)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def end_backtrack(level, successful)
|
88
|
+
for listener in @listeners
|
89
|
+
listener.end_backtrack(level, successful)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def end_resync()
|
94
|
+
for listener in @listeners
|
95
|
+
listener.end_resync()
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def enter_alternative(alt)
|
100
|
+
for listener in @listeners
|
101
|
+
listener.enter_alternative(alt)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def enter_decision(decision_number)
|
106
|
+
for listener in @listeners
|
107
|
+
listener.enter_decision(decision_number)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def enter_rule(grammar_file_name, rule_name)
|
112
|
+
for listener in @listeners
|
113
|
+
listener.enter_rule(grammar_file_name, rule_name)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def enter_sub_rule(decision_number)
|
118
|
+
for listener in @listeners
|
119
|
+
listener.enter_sub_rule(decision_number)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def error_node(tree)
|
124
|
+
for listener in @listeners
|
125
|
+
listener.error_node(tree)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def exit_decision(decision_number)
|
130
|
+
for listener in @listeners
|
131
|
+
listener.exit_decision(decision_number)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def exit_rule(grammar_file_name, rule_name)
|
136
|
+
for listener in @listeners
|
137
|
+
listener.exit_rule(grammar_file_name, rule_name)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def exit_sub_rule(decision_number)
|
142
|
+
for listener in @listeners
|
143
|
+
listener.exit_sub_rule(decision_number)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def flat_node(tree)
|
148
|
+
for listener in @listeners
|
149
|
+
listener.flat_node(tree)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def location(line, position)
|
154
|
+
for listener in @listeners
|
155
|
+
listener.location(line, position)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def look(i, tree)
|
160
|
+
for listener in @listeners
|
161
|
+
listener.look(i, tree)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def mark(marker)
|
166
|
+
for listener in @listeners
|
167
|
+
listener.mark(marker)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def recognition_exception(exception)
|
172
|
+
for listener in @listeners
|
173
|
+
listener.recognition_exception(exception)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def resync()
|
178
|
+
for listener in @listeners
|
179
|
+
listener.resync()
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def rewind(marker)
|
184
|
+
for listener in @listeners
|
185
|
+
listener.rewind(marker)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def semantic_predicate(result, predicate)
|
190
|
+
for listener in @listeners
|
191
|
+
listener.semantic_predicate(result, predicate)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def set_token_boundaries(tree, token_start_index, token_stop_index)
|
196
|
+
for listener in @listeners
|
197
|
+
listener.set_token_boundaries(tree, token_start_index, token_stop_index)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def terminate()
|
202
|
+
for listener in @listeners
|
203
|
+
listener.terminate()
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
module ANTLR3
|
5
|
+
module Debug
|
6
|
+
|
7
|
+
=begin rdoc ANTLR3::Debug::RecordEventListener
|
8
|
+
|
9
|
+
A debug listener that records intercepted events as strings in an array.
|
10
|
+
|
11
|
+
=end
|
12
|
+
class RecordEventListener < TraceEventListener
|
13
|
+
attr_reader :events
|
14
|
+
def initialize( adaptor = nil )
|
15
|
+
super
|
16
|
+
@events = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def record(event_message, *interpolation_arguments)
|
20
|
+
event_message = event_message.to_s
|
21
|
+
@events << event_message % interpolation_arguments
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end # module Debug
|
25
|
+
end # module ANTLR3
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
module ANTLR3
|
5
|
+
module Debug
|
6
|
+
=begin rdoc ANTLR3::Debug::RuleTracer
|
7
|
+
|
8
|
+
RuleTracer is simple debug event listener that writes the names of rule methods
|
9
|
+
as they are entered and exitted to an output stream.
|
10
|
+
|
11
|
+
=end
|
12
|
+
class RuleTracer
|
13
|
+
include EventListener
|
14
|
+
|
15
|
+
ARROW_IN = '--> '.freeze
|
16
|
+
ARROW_OUT = '<-- '.freeze
|
17
|
+
|
18
|
+
attr_reader :level
|
19
|
+
attr_accessor :spaces_per_indent, :device
|
20
|
+
|
21
|
+
def initialize(options = {})
|
22
|
+
@input = options[:input]
|
23
|
+
@level = 0
|
24
|
+
@spaces_per_indent = options[:spaces_per_indent] || 2
|
25
|
+
@device = options[:device] || options[:output] || $stderr
|
26
|
+
end
|
27
|
+
|
28
|
+
def enter_rule(grammar_file, name)
|
29
|
+
indent = @level * @spaces_per_indent
|
30
|
+
|
31
|
+
@device.print(' ' * indent, ARROW_IN, name)
|
32
|
+
if @input
|
33
|
+
input_symbol = @input.look || :EOF
|
34
|
+
@device.puts(" look = %p" % input_symbol)
|
35
|
+
else @device.print("\n")
|
36
|
+
end
|
37
|
+
|
38
|
+
@level += 1
|
39
|
+
end
|
40
|
+
|
41
|
+
def exit_rule(grammar_file, name)
|
42
|
+
@level -= 1
|
43
|
+
|
44
|
+
indent = @level * @spaces_per_indent
|
45
|
+
|
46
|
+
@device.print(' ' * indent, ARROW_OUT, name)
|
47
|
+
if @input
|
48
|
+
input_symbol = (@input.look || :EOF)
|
49
|
+
@device.puts(" look = %p" % input_symbol)
|
50
|
+
else @device.print("\n")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,360 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'socket'
|
5
|
+
|
6
|
+
module ANTLR3
|
7
|
+
module Debug
|
8
|
+
|
9
|
+
|
10
|
+
=begin rdoc ANTLR3::Debug::EventSocketProxy
|
11
|
+
|
12
|
+
A proxy debug event listener that forwards events over a socket to
|
13
|
+
a debugger (or any other listener) using a simple text-based protocol;
|
14
|
+
one event per line. ANTLRWorks listens on server socket with a
|
15
|
+
RemoteDebugEventSocketListener instance. These two objects must therefore
|
16
|
+
be kept in sync. New events must be handled on both sides of socket.
|
17
|
+
|
18
|
+
=end
|
19
|
+
class EventSocketProxy
|
20
|
+
include EventListener
|
21
|
+
|
22
|
+
SOCKET_ADDR_PACK = 'snCCCCa8'.freeze
|
23
|
+
|
24
|
+
def initialize(recognizer, options = {})
|
25
|
+
super()
|
26
|
+
@grammar_file_name = recognizer.grammar_file_name
|
27
|
+
@adaptor = options[:adaptor]
|
28
|
+
@port = options[:port] || DEFAULT_PORT
|
29
|
+
@log = options[:log]
|
30
|
+
@socket = nil
|
31
|
+
@connection = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def log!(message, *interpolation_arguments)
|
35
|
+
@log and @log.printf(message, *interpolation_arguments)
|
36
|
+
end
|
37
|
+
|
38
|
+
def handshake
|
39
|
+
unless @socket
|
40
|
+
begin
|
41
|
+
@socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
42
|
+
@socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
|
43
|
+
@socket.bind(Socket.pack_sockaddr_in( @port, '' ))
|
44
|
+
@socket.listen(1)
|
45
|
+
log!("waiting for incoming connection on port %i\n", @port)
|
46
|
+
|
47
|
+
@connection, addr = @socket.accept
|
48
|
+
port, host = Socket.unpack_sockaddr_in(addr)
|
49
|
+
log!("Accepted connection from %s:%s\n", host, port)
|
50
|
+
|
51
|
+
@connection.setsockopt(Socket::SOL_TCP, Socket::TCP_NODELAY, 1)
|
52
|
+
|
53
|
+
write('ANTLR %s', PROTOCOL_VERSION)
|
54
|
+
write('grammar %p', @grammar_file_name)
|
55
|
+
ack
|
56
|
+
rescue IOError => error
|
57
|
+
log!("handshake failed due to an IOError:\n")
|
58
|
+
log!(" %s: %s", error.class, error.message)
|
59
|
+
log!(" Backtrace: ")
|
60
|
+
log!(" - %s", error.backtrace.join("\n - "))
|
61
|
+
@connection and @connection.close
|
62
|
+
@socket and @socket.close
|
63
|
+
@socket = nil
|
64
|
+
raise
|
65
|
+
end
|
66
|
+
end
|
67
|
+
return self
|
68
|
+
end
|
69
|
+
|
70
|
+
def write(message, *interpolation_arguments)
|
71
|
+
message << ?\n
|
72
|
+
log!("---> #{message}", *interpolation_arguments)
|
73
|
+
@connection.printf(message, *interpolation_arguments)
|
74
|
+
@connection.flush
|
75
|
+
end
|
76
|
+
|
77
|
+
def ack
|
78
|
+
line = @connection.readline
|
79
|
+
log!("<--- %s", line)
|
80
|
+
line
|
81
|
+
end
|
82
|
+
|
83
|
+
def transmit(event, *interpolation_arguments)
|
84
|
+
write(event, *interpolation_arguments)
|
85
|
+
ack()
|
86
|
+
rescue IOError
|
87
|
+
@connection.close
|
88
|
+
raise
|
89
|
+
end
|
90
|
+
|
91
|
+
def commence
|
92
|
+
# don't bother sending event; listener will trigger upon connection
|
93
|
+
end
|
94
|
+
|
95
|
+
def terminate
|
96
|
+
transmit 'terminate'
|
97
|
+
@connection.close
|
98
|
+
@socket.close
|
99
|
+
end
|
100
|
+
|
101
|
+
def enter_rule( grammar_file_name, rule_name )
|
102
|
+
transmit "%s\t%s\t%s", __method__, grammar_file_name, rule_name
|
103
|
+
end
|
104
|
+
|
105
|
+
def enter_alternative( alt )
|
106
|
+
transmit "%s\t%s", __method__, alt
|
107
|
+
end
|
108
|
+
|
109
|
+
def exit_rule( grammar_file_name, rule_name )
|
110
|
+
transmit "%s\t%s\t%s", __method__, grammar_file_name, rule_name
|
111
|
+
end
|
112
|
+
|
113
|
+
def enter_subrule( decision_number )
|
114
|
+
transmit "%s\t%i", __method__, decision_number
|
115
|
+
end
|
116
|
+
|
117
|
+
def exit_subrule( decision_number )
|
118
|
+
transmit "%s\t%i", __method__, decision_number
|
119
|
+
end
|
120
|
+
|
121
|
+
def enter_decision( decision_number )
|
122
|
+
transmit "%s\t%i", __method__, decision_number
|
123
|
+
end
|
124
|
+
|
125
|
+
def exit_decision( decision_number )
|
126
|
+
transmit "%s\t%i", __method__, decision_number
|
127
|
+
end
|
128
|
+
|
129
|
+
def consume_token( token )
|
130
|
+
transmit "%s\t%s", __method__, serialize_token( token )
|
131
|
+
end
|
132
|
+
|
133
|
+
def consume_hidden_token( token )
|
134
|
+
transmit "%s\t%s", __method__, serialize_token( token )
|
135
|
+
end
|
136
|
+
|
137
|
+
def look(i, item)
|
138
|
+
case item
|
139
|
+
when AST::Tree
|
140
|
+
look_tree( i, item )
|
141
|
+
when nil
|
142
|
+
else
|
143
|
+
transmit "%s\t%i\t%s", __method__, i, serialize_token(item)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def mark(i)
|
148
|
+
transmit "%s\t%i", __method__, i
|
149
|
+
end
|
150
|
+
|
151
|
+
def rewind(i = nil)
|
152
|
+
i ? transmit( "%s\t%i", __method__, i ) : transmit( '%s', __method__ )
|
153
|
+
end
|
154
|
+
|
155
|
+
def begin_backtrack( level )
|
156
|
+
transmit "%s\t%i", __method__, level
|
157
|
+
end
|
158
|
+
def end_backtrack( level, successful )
|
159
|
+
transmit "%s\t%i\t%p", __method__, level, (successful ? true : false)
|
160
|
+
end
|
161
|
+
|
162
|
+
def location( line, position )
|
163
|
+
transmit "%s\t%i\t%i", __method__, line, position
|
164
|
+
end
|
165
|
+
|
166
|
+
def recognition_exception( exception )
|
167
|
+
transmit "%s\t%p\t%i\t%i\t%i", __method__, exception.class,
|
168
|
+
exception.index, exception.line, exception.column
|
169
|
+
end
|
170
|
+
|
171
|
+
def begin_resync
|
172
|
+
transmit '%s', __method__
|
173
|
+
end
|
174
|
+
|
175
|
+
def end_resync
|
176
|
+
transmit '%s', __method__
|
177
|
+
end
|
178
|
+
|
179
|
+
def semantic_predicate( result, predicate )
|
180
|
+
pure_boolean = !(!result)
|
181
|
+
transmit "%s\t%s\t%s", __method__, pure_boolean, escape_newlines( predicate )
|
182
|
+
end
|
183
|
+
|
184
|
+
def consume_node( tree )
|
185
|
+
transmit "%s\t%s", __method__, serialize_node( tree )
|
186
|
+
end
|
187
|
+
|
188
|
+
def adaptor
|
189
|
+
@adaptor ||= ANTLR3::CommonTreeAdaptor.new
|
190
|
+
end
|
191
|
+
|
192
|
+
def look_tree( i, tree )
|
193
|
+
transmit "%s\t%s\t%s", __method__, i, serialize_node( tree )
|
194
|
+
end
|
195
|
+
|
196
|
+
def flat_node( tree )
|
197
|
+
transmit "%s\t%i", __method__, adaptor.unique_id( tree )
|
198
|
+
end
|
199
|
+
|
200
|
+
def error_node( tree )
|
201
|
+
transmit "%s\t%i\t%i\t%p", __method__, adaptor.unique_id( tree ),
|
202
|
+
Token::INVALID_TOKEN_TYPE, escape_newlines( tree.to_s )
|
203
|
+
end
|
204
|
+
|
205
|
+
def create_node( node, token = nil )
|
206
|
+
if token
|
207
|
+
transmit "%s\t%i\t%i", __method__, adaptor.unique_id( node ),
|
208
|
+
token.token_index
|
209
|
+
else
|
210
|
+
transmit "%s\t%i\t%i\t%p", __method__, adaptor.unique_id( node ),
|
211
|
+
adaptor.type_of( node ), adaptor.text_of( node )
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def become_root( new_root, old_root )
|
216
|
+
transmit "%s\t%i\t%i", __method__, adaptor.unique_id( new_root ),
|
217
|
+
adaptor.unique_id( old_root )
|
218
|
+
end
|
219
|
+
|
220
|
+
def add_child( root, child )
|
221
|
+
transmit "%s\t%i\t%i", __method__, adaptor.unique_id( root ),
|
222
|
+
adaptor.unique_id( child )
|
223
|
+
end
|
224
|
+
|
225
|
+
def set_token_boundaries( t, token_start_index, token_stop_index )
|
226
|
+
transmit "%s\t%i\t%i\t%i", __method__, adaptor.unique_id( t ),
|
227
|
+
token_start_index, token_stop_index
|
228
|
+
end
|
229
|
+
|
230
|
+
attr_accessor :adaptor
|
231
|
+
|
232
|
+
def serialize_token( token )
|
233
|
+
[token.token_index, token.type, token.channel,
|
234
|
+
token.line, token.column,
|
235
|
+
escape_newlines( token.text )].join( "\t" )
|
236
|
+
end
|
237
|
+
|
238
|
+
def serialize_node( node )
|
239
|
+
adaptor ||= ANTLR3::AST::CommonTreeAdaptor.new
|
240
|
+
id = adaptor.unique_id( node )
|
241
|
+
type = adaptor.type_of( node )
|
242
|
+
token = adaptor.token( node )
|
243
|
+
line = token.line rescue -1
|
244
|
+
col = token.column rescue -1
|
245
|
+
index = adaptor.token_start_index( node )
|
246
|
+
[ id, type, line, col, index ].join( "\t" )
|
247
|
+
end
|
248
|
+
|
249
|
+
|
250
|
+
def escape_newlines( text )
|
251
|
+
text.inspect.tap do |t|
|
252
|
+
t.gsub!(/%/, '%%')
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
=begin rdoc ANTLR3::Debug::RemoteEventSocketListener
|
258
|
+
|
259
|
+
A debugging event listener which intercepts debug event messages sent by a EventSocketProxy
|
260
|
+
over an IP socket.
|
261
|
+
|
262
|
+
=end
|
263
|
+
class RemoteEventSocketListener < ::Thread
|
264
|
+
autoload :StringIO, 'stringio'
|
265
|
+
ESCAPE_MAP = Hash.new { |h, k| k }
|
266
|
+
ESCAPE_MAP.update(
|
267
|
+
?n => ?\n, ?t => ?\t, ?a => ?\a, ?b => ?\b, ?e => ?\e,
|
268
|
+
?f => ?\f, ?r => ?\r, ?v => ?\v
|
269
|
+
)
|
270
|
+
|
271
|
+
attr_reader :host, :port
|
272
|
+
|
273
|
+
def initialize( options = {} )
|
274
|
+
@listener = listener
|
275
|
+
@host = options.fetch( :host, 'localhost' )
|
276
|
+
@port = options.fetch( :port, DEFAULT_PORT )
|
277
|
+
@buffer = StringIO.new
|
278
|
+
super do
|
279
|
+
connect do
|
280
|
+
handshake
|
281
|
+
loop do
|
282
|
+
yield( read_event )
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
private
|
289
|
+
|
290
|
+
def handshake
|
291
|
+
@version = @socket.readline.split("\t")[-1]
|
292
|
+
@grammar_file = @socket.readline.split("\t")[-1]
|
293
|
+
ack
|
294
|
+
end
|
295
|
+
|
296
|
+
def ack
|
297
|
+
@socket.puts("ack")
|
298
|
+
@socket.flush
|
299
|
+
end
|
300
|
+
|
301
|
+
def unpack_event(event)
|
302
|
+
event.nil? and raise( StopIteration )
|
303
|
+
event.chomp!
|
304
|
+
name, *elements = event.split("\t",-1)
|
305
|
+
name = name.to_sym
|
306
|
+
name == :terminate and raise StopIteration
|
307
|
+
elements.map! do |elem|
|
308
|
+
elem.empty? and next(nil)
|
309
|
+
case elem
|
310
|
+
when /^\d+$/ then Integer(elem)
|
311
|
+
when /^\d+\.\d+$/ then Float(elem)
|
312
|
+
when /^true$/ then true
|
313
|
+
when /^false$/ then false
|
314
|
+
when /^"(.*)"$/ then parse_string($1)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
elements.unshift(name)
|
318
|
+
return( elements )
|
319
|
+
end
|
320
|
+
|
321
|
+
def read_event
|
322
|
+
event = @socket.readline or raise( StopIteration )
|
323
|
+
ack
|
324
|
+
return unpack_event( event )
|
325
|
+
end
|
326
|
+
|
327
|
+
def connect
|
328
|
+
TCPSocket.open(@host, @port) do |socket|
|
329
|
+
@socket = socket
|
330
|
+
yield
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
def parse_string( string )
|
335
|
+
@buffer.string = string
|
336
|
+
@buffer.rewind
|
337
|
+
out = ''
|
338
|
+
until @buffer.eof?
|
339
|
+
case c = @buffer.getc
|
340
|
+
when ?\\ # escape
|
341
|
+
nc = @buffer.getc
|
342
|
+
out <<
|
343
|
+
if nc.between?( ?0, ?9 ) # octal integer
|
344
|
+
@buffer.ungetc( nc )
|
345
|
+
@buffer.read( 3 ).to_i( 8 ).chr
|
346
|
+
elsif nc == ?x
|
347
|
+
@buffer.read( 2 ).to_i( 16 ).chr
|
348
|
+
else
|
349
|
+
ESCAPE_MAP[ nc ]
|
350
|
+
end
|
351
|
+
else
|
352
|
+
out << c
|
353
|
+
end
|
354
|
+
end
|
355
|
+
return out
|
356
|
+
end
|
357
|
+
|
358
|
+
end # class RemoteEventSocketListener
|
359
|
+
end # module Debug
|
360
|
+
end # module ANTLR3
|