class ANTLR3::Debug::EventSocketProxy

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.

Constants

SOCKET_ADDR_PACK

Attributes

adaptor[RW]

Public Class Methods

new( recognizer, options = {} ) click to toggle source
Calls superclass method
# 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

Public Instance Methods

ack() click to toggle source
# File lib/antlr3/debug/socket.rb, line 78
def ack
  line = @connection.readline
  log!( "<--- %s", line )
  line
end
adaptor() click to toggle source
# File lib/antlr3/debug/socket.rb, line 189
def adaptor
  @adaptor ||= ANTLR3::CommonTreeAdaptor.new
end
add_child( root, child ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# File lib/antlr3/debug/socket.rb, line 156
def begin_backtrack( level )
  transmit "%s\t%i", :begin_backtrack, level
end
begin_resync() click to toggle source
# File lib/antlr3/debug/socket.rb, line 172
def begin_resync
  transmit '%s', :begin_resync
end
commence() click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# 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_resync() click to toggle source
# File lib/antlr3/debug/socket.rb, line 176
def end_resync
  transmit '%s', :end_resync
end
enter_alternative( alt ) click to toggle source
# File lib/antlr3/debug/socket.rb, line 106
def enter_alternative( alt )
  transmit "%s\t%s", :enter_alternative, alt
end
enter_decision( decision_number ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# File lib/antlr3/debug/socket.rb, line 197
def flat_node( tree )
  transmit "%s\t%i", :flat_node, adaptor.unique_id( tree )
end
handshake() click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# File lib/antlr3/debug/socket.rb, line 34
def log!( message, *interpolation_arguments )
  @log and @log.printf( message, *interpolation_arguments )
end
look( i, item ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# File lib/antlr3/debug/socket.rb, line 148
def mark( i )
  transmit "%s\t%i", :mark, i
end
recognition_exception( exception ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# 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 ) click to toggle source
# 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
terminate() click to toggle source
# File lib/antlr3/debug/socket.rb, line 96
def terminate
  transmit 'terminate'
  @connection.close
  @socket.close
end
transmit( event, *interpolation_arguments ) click to toggle source
# 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 ) click to toggle source
# 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