Class: ANTLR3::Debug::EventSocketProxy

Inherits:
Object
  • Object
show all
Includes:
EventListener
Defined in:
lib/antlr3/debug/socket.rb

Overview

A proxy debug event listener that forwards events over a socket to a debugger (or any other listener) using a simple text-based protocol; one event per line. ANTLRWorks listens on server socket with a RemoteDebugEventSocketListener instance. These two objects must therefore be kept in sync. New events must be handled on both sides of socket.

Constant Summary collapse

SOCKET_ADDR_PACK =
'snCCCCa8'.freeze

Constants included from EventListener

ANTLR3::Debug::EventListener::EVENTS, ANTLR3::Debug::EventListener::PROTOCOL_VERSION

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from EventListener

#backtrack, #examine_rule_memoization, #on, #resync

Constructor Details

#initialize(recognizer, options = {}) ⇒ EventSocketProxy

Returns a new instance of EventSocketProxy.



24
25
26
27
28
29
30
31
32
# File 'lib/antlr3/debug/socket.rb', line 24

def initialize( recognizer, options = {} )
  super()
  @grammar_file_name = recognizer.grammar_file_name
  @adaptor = options[ :adaptor ]
  @port = options[ :port ] || DEFAULT_PORT
  @log = options[ :log ]
  @socket = nil
  @connection = nil
end

Instance Attribute Details

#adaptorObject

Returns the value of attribute adaptor.



189
190
191
# File 'lib/antlr3/debug/socket.rb', line 189

def adaptor
  @adaptor ||= ANTLR3::CommonTreeAdaptor.new
end

Instance Method Details

#ackObject



78
79
80
81
82
# File 'lib/antlr3/debug/socket.rb', line 78

def ack
  line = @connection.readline
  log!( "<--- %s", line )
  line
end

#add_child(root, child) ⇒ Object



221
222
223
224
# File 'lib/antlr3/debug/socket.rb', line 221

def add_child( root, child )
  transmit "%s\t%i\t%i", :add_child, adaptor.unique_id( root ),
           adaptor.unique_id( child )
end

#become_root(new_root, old_root) ⇒ Object



216
217
218
219
# File 'lib/antlr3/debug/socket.rb', line 216

def become_root( new_root, old_root )
  transmit "%s\t%i\t%i", :become_root, adaptor.unique_id( new_root ),
            adaptor.unique_id( old_root )
end

#begin_backtrack(level) ⇒ Object



156
157
158
# File 'lib/antlr3/debug/socket.rb', line 156

def begin_backtrack( level )
  transmit "%s\t%i", :begin_backtrack, level
end

#begin_resyncObject



172
173
174
# File 'lib/antlr3/debug/socket.rb', line 172

def begin_resync
  transmit '%s', :begin_resync
end

#commenceObject



92
93
94
# File 'lib/antlr3/debug/socket.rb', line 92

def commence
  # don't bother sending event; listener will trigger upon connection
end

#consume_hidden_token(token) ⇒ Object



134
135
136
# File 'lib/antlr3/debug/socket.rb', line 134

def consume_hidden_token( token )
  transmit "%s\t%s", :consume_hidden_token, serialize_token( token )
end

#consume_node(tree) ⇒ Object



185
186
187
# File 'lib/antlr3/debug/socket.rb', line 185

def consume_node( tree )
  transmit "%s\t%s", :consume_node, serialize_node( tree )
end

#consume_token(token) ⇒ Object



130
131
132
# File 'lib/antlr3/debug/socket.rb', line 130

def consume_token( token )
  transmit "%s\t%s", :consume_token, serialize_token( token )
end

#create_node(node, token = nil) ⇒ Object



206
207
208
209
210
211
212
213
214
# File 'lib/antlr3/debug/socket.rb', line 206

def create_node( node, token = nil )
  if token
    transmit "%s\t%i\t%i", :create_node, adaptor.unique_id( node ),
            token.token_index
  else
    transmit "%s\t%i\t%i\t%p", :create_node, adaptor.unique_id( node ),
        adaptor.type_of( node ), adaptor.text_of( node )
  end
end

#end_backtrack(level, successful) ⇒ Object



159
160
161
# File 'lib/antlr3/debug/socket.rb', line 159

def end_backtrack( level, successful )
  transmit "%s\t%i\t%p", :end_backtrack, level, ( successful ? true : false )
end

#end_resyncObject



176
177
178
# File 'lib/antlr3/debug/socket.rb', line 176

def end_resync
  transmit '%s', :end_resync
end

#enter_alternative(alt) ⇒ Object



106
107
108
# File 'lib/antlr3/debug/socket.rb', line 106

def enter_alternative( alt )
  transmit "%s\t%s", :enter_alternative, alt
end

#enter_decision(decision_number) ⇒ Object



122
123
124
# File 'lib/antlr3/debug/socket.rb', line 122

def enter_decision( decision_number )
  transmit "%s\t%i", :enter_decision, decision_number
end

#enter_rule(grammar_file_name, rule_name) ⇒ Object



102
103
104
# File 'lib/antlr3/debug/socket.rb', line 102

def enter_rule( grammar_file_name, rule_name )
  transmit "%s\t%s\t%s", :enter_rule, grammar_file_name, rule_name
end

#enter_subrule(decision_number) ⇒ Object



114
115
116
# File 'lib/antlr3/debug/socket.rb', line 114

def enter_subrule( decision_number )
  transmit "%s\t%i", :enter_subrule, decision_number
end

#error_node(tree) ⇒ Object



201
202
203
204
# File 'lib/antlr3/debug/socket.rb', line 201

def error_node( tree )
  transmit "%s\t%i\t%i\t%p", :error_node, adaptor.unique_id( tree ),
          Token::INVALID_TOKEN_TYPE, escape_newlines( tree.to_s )
end

#escape_newlines(text) ⇒ Object



251
252
253
254
255
# File 'lib/antlr3/debug/socket.rb', line 251

def escape_newlines( text )
  text.inspect.tap do |t|
    t.gsub!( /%/, '%%' )
  end
end

#exit_decision(decision_number) ⇒ Object



126
127
128
# File 'lib/antlr3/debug/socket.rb', line 126

def exit_decision( decision_number )
  transmit "%s\t%i", :exit_decision, decision_number
end

#exit_rule(grammar_file_name, rule_name) ⇒ Object



110
111
112
# File 'lib/antlr3/debug/socket.rb', line 110

def exit_rule( grammar_file_name, rule_name )
  transmit "%s\t%s\t%s", :exit_rule, grammar_file_name, rule_name
end

#exit_subrule(decision_number) ⇒ Object



118
119
120
# File 'lib/antlr3/debug/socket.rb', line 118

def exit_subrule( decision_number )
  transmit "%s\t%i", :exit_subrule, decision_number
end

#flat_node(tree) ⇒ Object



197
198
199
# File 'lib/antlr3/debug/socket.rb', line 197

def flat_node( tree )
  transmit "%s\t%i", :flat_node, adaptor.unique_id( tree )
end

#handshakeObject



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/antlr3/debug/socket.rb', line 38

def handshake
  unless @socket
    begin
      @socket = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
      @socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
      @socket.bind( Socket.pack_sockaddr_in( @port, '' ) )
      @socket.listen( 1 )
      log!( "waiting for incoming connection on port %i\n", @port )
      
      @connection, addr = @socket.accept
      port, host = Socket.unpack_sockaddr_in( addr )
      log!( "Accepted connection from %s:%s\n", host, port )
      
      proto_number = ( Socket::SOL_TCP rescue 6 )
      @connection.setsockopt( proto_number, Socket::TCP_NODELAY, 1 )
      
      write( 'ANTLR %s', PROTOCOL_VERSION )
      write( 'grammar %p', @grammar_file_name )
      ack
    rescue IOError => error
      log!( "handshake failed due to an IOError:\n" )
      log!( "  %s: %s", error.class, error.message )
      log!( "  Backtrace: " )
      log!( "  - %s", error.backtrace.join( "\n  - " ) )
      @connection and @connection.close
      @socket and @socket.close
      @socket = nil
      raise
    end
  end
  return self
end

#location(line, position) ⇒ Object



163
164
165
# File 'lib/antlr3/debug/socket.rb', line 163

def location( line, position )
  transmit "%s\t%i\t%i", :location, line, position
end

#log!(message, *interpolation_arguments) ⇒ Object



34
35
36
# File 'lib/antlr3/debug/socket.rb', line 34

def log!( message, *interpolation_arguments )
  @log and @log.printf( message, *interpolation_arguments )
end

#look(i, item) ⇒ Object



138
139
140
141
142
143
144
145
146
# File 'lib/antlr3/debug/socket.rb', line 138

def look( i, item )
  case item
  when AST::Tree
    look_tree( i, item )
  when nil
  else
    transmit "%s\t%i\t%s", :look, i, serialize_token( item )
  end
end

#look_tree(i, tree) ⇒ Object



193
194
195
# File 'lib/antlr3/debug/socket.rb', line 193

def look_tree( i, tree )
  transmit "%s\t%s\t%s", :look_tree, i, serialize_node( tree )
end

#mark(i) ⇒ Object



148
149
150
# File 'lib/antlr3/debug/socket.rb', line 148

def mark( i )
  transmit "%s\t%i", :mark, i
end

#recognition_exception(exception) ⇒ Object



167
168
169
170
# File 'lib/antlr3/debug/socket.rb', line 167

def recognition_exception( exception )
  transmit "%s\t%p\t%i\t%i\t%i", :recognition_exception, exception.class,
    exception.index, exception.line, exception.column
end

#rewind(i = nil) ⇒ Object



152
153
154
# File 'lib/antlr3/debug/socket.rb', line 152

def rewind( i = nil )
  i ? transmit( "%s\t%i", :rewind, i ) : transmit( '%s', :rewind )
end

#semantic_predicate(result, predicate) ⇒ Object



180
181
182
183
# File 'lib/antlr3/debug/socket.rb', line 180

def semantic_predicate( result, predicate )
  pure_boolean = !( !result )
  transmit "%s\t%s\t%s", :semantic_predicate, pure_boolean, escape_newlines( predicate )
end

#serialize_node(node) ⇒ Object



239
240
241
242
243
244
245
246
247
248
# File 'lib/antlr3/debug/socket.rb', line 239

def serialize_node( node )
  adaptor ||= ANTLR3::AST::CommonTreeAdaptor.new
  id = adaptor.unique_id( node )
  type = adaptor.type_of( node )
  token = adaptor.token( node )
  line = token.line rescue -1
  col  = token.column rescue -1
  index = adaptor.token_start_index( node )
  [ id, type, line, col, index ].join( "\t" )
end

#serialize_token(token) ⇒ Object



233
234
235
236
237
# File 'lib/antlr3/debug/socket.rb', line 233

def serialize_token( token )
  [ token.token_index, token.type, token.channel,
   token.line, token.column,
   escape_newlines( token.text ) ].join( "\t" )
end

#set_token_boundaries(t, token_start_index, token_stop_index) ⇒ Object



226
227
228
229
# File 'lib/antlr3/debug/socket.rb', line 226

def set_token_boundaries( t, token_start_index, token_stop_index )
  transmit "%s\t%i\t%i\t%i", :set_token_boundaries, adaptor.unique_id( t ),
                             token_start_index, token_stop_index
end

#terminateObject



96
97
98
99
100
# File 'lib/antlr3/debug/socket.rb', line 96

def terminate
  transmit 'terminate'
  @connection.close
  @socket.close
end

#transmit(event, *interpolation_arguments) ⇒ Object



84
85
86
87
88
89
90
# File 'lib/antlr3/debug/socket.rb', line 84

def transmit( event, *interpolation_arguments )
  write( event, *interpolation_arguments )
  ack()
rescue IOError
  @connection.close
  raise
end

#write(message, *interpolation_arguments) ⇒ Object



71
72
73
74
75
76
# File 'lib/antlr3/debug/socket.rb', line 71

def write( message, *interpolation_arguments )
  message << ?\n
  log!( "---> #{ message }", *interpolation_arguments )
  @connection.printf( message, *interpolation_arguments )
  @connection.flush
end