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