diff options
Diffstat (limited to 'runtime/Ruby/test/functional/debugging/debug-mode.rb')
-rw-r--r-- | runtime/Ruby/test/functional/debugging/debug-mode.rb | 688 |
1 files changed, 688 insertions, 0 deletions
diff --git a/runtime/Ruby/test/functional/debugging/debug-mode.rb b/runtime/Ruby/test/functional/debugging/debug-mode.rb new file mode 100644 index 0000000..6db9e51 --- /dev/null +++ b/runtime/Ruby/test/functional/debugging/debug-mode.rb @@ -0,0 +1,688 @@ +#!/usr/bin/ruby +# encoding: utf-8 + +require 'antlr3' +require 'fileutils' +require 'antlr3/test/functional' +#require 'antlr3/test/diff' + +class ANTLRDebugger < Thread + self.abort_on_exception = true + attr_accessor :events, :success, :port + include Timeout + + def initialize( port ) + @events = [] + @success = false + @port = port + + super do + timeout( 2 ) do + begin + @socket = TCPSocket.open( 'localhost', @port ) + #Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0) + #@socket.connect( Socket.pack_sockaddr_in(@port, '127.0.0.1') ) + rescue Errno::ECONNREFUSED => error + if $VERBOSE + $stderr.printf( + "%s:%s received connection refuse error: %p\n", + __FILE__, __LINE__, error + ) + $stderr.puts( "sleeping for 0.1 seconds before retrying" ) + end + sleep( 0.01 ) + retry + end + end + + @socket.readline.strip.should == 'ANTLR 2' + @socket.readline.strip.start_with?( 'grammar "' ).should == true + ack + loop do + event = @socket.readline.strip + @events << event.split( "\t" ) + ack + break if event == 'terminate' + end + + @socket.close + @success = true + end + + end + + def ack + @socket.write( "ACK\n" ) + @socket.flush + end + +end # ANTLRDebugger + +class TestDebugGrammars < ANTLR3::Test::Functional + compile_options :debug => true + + #include ANTLR3::Test::Diff + + def parse( grammar, rule, input, options = {} ) + @grammar = inline_grammar( grammar ) + @grammar.compile( self.class.compile_options ) + @grammar_path = File.expand_path( @grammar.path ) + for output_file in @grammar.target_files + self.class.import( output_file ) + end + grammar_module = self.class.const_get( @grammar.name ) + listener = options[ :listener ] or debugger = ANTLRDebugger.new( port = 49100 ) + + begin + lexer = grammar_module::Lexer.new( input ) + tokens = ANTLR3::CommonTokenStream.new( lexer ) + options[ :debug_listener ] = listener + parser = grammar_module::Parser.new( tokens, options ) + parser.send( rule ) + ensure + if listener.nil? + debugger.join + return( debugger ) + end + end + end + + example 'basic debug-mode parser using a RecordEventListener' do + grammar = %q< + grammar BasicParser; // line 1 + options {language=Ruby;} // line 2 + a : ID EOF; // line 3 + ID : 'a'..'z'+ ; // line 4 + WS : (' '|'\n') {$channel=HIDDEN;} ; + > + listener = ANTLR3::Debug::RecordEventListener.new + parse( grammar, :a, 'a', :listener => listener ) + lt_events, found = listener.events.partition { |event| event.start_with?( "(look): " ) } + lt_events.should_not be_empty + + expected = [ "(enter_rule): rule=a", + "(location): line=3 position=1", + "(enter_alternative): number=1", + "(location): line=3 position=5", + "(location): line=3 position=8", + "(location): line=3 position=11", + "(exit_rule): rule=a" ] + found.should == expected + end + + example 'debug-mode parser using a socket proxy to transmit events' do + grammar = %q< + grammar SocketProxy; // line 1 + options {language=Ruby;} // line 2 + a : ID EOF; // line 3 + ID : 'a'..'z'+ ; // line 4 + WS : (' '|'\n') {$channel=HIDDEN;} ; + > + debugger = parse( grammar, :a, 'a' ) + debugger.success.should be_true + expected = [ + [ 'enter_rule', @grammar_path, 'a' ], + [ 'location', '3', '1' ], + [ 'enter_alternative', '1' ], + [ 'location', '3', '5' ], + [ 'look', '1', '0', '4', 'default', '1', '0', '"a"' ], + [ 'look', '1', '0', '4', 'default', '1', '0', '"a"' ], + [ 'consume_token', '0', '4', 'default', '1', '0', '"a"' ], + [ 'location', '3', '8' ], + [ 'look', '1', '-1', '-1', 'default', '0', '-1', 'nil' ], + [ 'look', '1', '-1', '-1', 'default', '0', '-1', 'nil' ], + [ 'consume_token', '-1', '-1', 'default', '0', '-1', 'nil' ], + [ 'location', '3', '11' ], + [ 'exit_rule', @grammar_path, 'a' ], + [ 'terminate' ] + ] + + debugger.events.should == expected + end + + example 'debug-mode parser events triggered by recognition errors' do + grammar = %q< + grammar RecognitionError; + options { language=Ruby; } + a : ID EOF; + ID : 'a'..'z'+ ; + WS : (' '|'\n') {$channel=HIDDEN;} ; + > + debugger = parse( grammar, :a, "a b" ) + debugger.success.should be_true + + expected = [ + [ "enter_rule", @grammar_path, "a" ], + [ "location", "3", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "5" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_token", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_hidden_token", "1", "5", "hidden", "1", "1", '" "' ], + [ "location", "3", "8" ], + [ "look", "1", "2", "4", "default", "1", "2", "\"b\"" ], + [ "look", "1", "2", "4", "default", "1", "2", "\"b\"" ], + [ "look", "2", "-1", "-1", "default", "0", "-1", "nil" ], + [ "look", "1", "2", "4", "default", "1", "2", "\"b\"" ], + [ "begin_resync" ], + [ "consume_token", "2", "4", "default", "1", "2", "\"b\"" ], + [ "end_resync" ], + [ "recognition_exception", "ANTLR3::Error::UnwantedToken", "2", "1", "2" ], + [ "consume_token", "-1", "-1", "default", "0", "-1", "nil" ], + [ "location", "3", "11" ], + [ "exit_rule", @grammar_path, "a" ], + [ "terminate" ] + ] + debugger.events.should == expected + end + + example 'debug-mode parser events triggered by semantic predicate evaluation' do + grammar = %q< + grammar SemPred; + options { language=Ruby; } + a : {true}? ID EOF; + ID : 'a'..'z'+ ; + WS : (' '|'\n') {$channel=HIDDEN;} ; + > + + debugger = parse( grammar, :a, "a" ) + debugger.success.should be_true + + expected = [ + [ "enter_rule", @grammar_path, "a" ], + [ "location", "3", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "5" ], + [ "semantic_predicate", "true", '"true"' ], + [ "location", "3", "13" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_token", "0", "4", "default", "1", "0", "\"a\"" ], + [ "location", "3", "16" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "consume_token", "-1", "-1", "default", "0", "-1", "nil" ], + [ "location", "3", "19" ], + [ "exit_rule", @grammar_path, "a" ], + [ "terminate" ] + ] + debugger.events.should == expected + end + + example 'debug-mode parser events triggered by recognizing a (...)+ block' do + grammar = %q< + grammar PositiveClosureBlock; + options { language=Ruby; } + a : ID ( ID | INT )+ EOF; + ID : 'a'..'z'+ ; + INT : '0'..'9'+ ; + WS : (' '|'\n') {$channel=HIDDEN;} ; + > + + debugger = parse( grammar, :a, "a 1 b c 3" ) + debugger.success.should be_true + + expected = [ + [ "enter_rule", @grammar_path, "a" ], + [ "location", "3", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "5" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_token", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_hidden_token", "1", "6", "hidden", "1", "1", '" "' ], + [ "location", "3", "8" ], + [ "enter_subrule", "1" ], + [ "enter_decision", "1" ], + [ "look", "1", "2", "5", "default", "1", "2", "\"1\"" ], + [ "exit_decision", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "8" ], + [ "look", "1", "2", "5", "default", "1", "2", "\"1\"" ], + [ "consume_token", "2", "5", "default", "1", "2", "\"1\"" ], + [ "consume_hidden_token", "3", "6", "hidden", "1", "3", '" "' ], + [ "enter_decision", "1" ], + [ "look", "1", "4", "4", "default", "1", "4", "\"b\"" ], + [ "exit_decision", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "8" ], + [ "look", "1", "4", "4", "default", "1", "4", "\"b\"" ], + [ "consume_token", "4", "4", "default", "1", "4", "\"b\"" ], + [ "consume_hidden_token", "5", "6", "hidden", "1", "5", '" "' ], + [ "enter_decision", "1" ], + [ "look", "1", "6", "4", "default", "1", "6", "\"c\"" ], + [ "exit_decision", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "8" ], + [ "look", "1", "6", "4", "default", "1", "6", "\"c\"" ], + [ "consume_token", "6", "4", "default", "1", "6", "\"c\"" ], + [ "consume_hidden_token", "7", "6", "hidden", "1", "7", '" "' ], + [ "enter_decision", "1" ], + [ "look", "1", "8", "5", "default", "1", "8", "\"3\"" ], + [ "exit_decision", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "8" ], + [ "look", "1", "8", "5", "default", "1", "8", "\"3\"" ], + [ "consume_token", "8", "5", "default", "1", "8", "\"3\"" ], + [ "enter_decision", "1" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "exit_decision", "1" ], + [ "exit_subrule", "1" ], + [ "location", "3", "22" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "consume_token", "-1", "-1", "default", "0", "-1", "nil" ], + [ "location", "3", "25" ], + [ "exit_rule", @grammar_path, "a" ], + [ "terminate" ] + ] + + debugger.events.should == expected + end + + example 'debug-mode parser events triggered by recognizing a (...)* block' do + grammar = %q< + grammar ClosureBlock; + options { language=Ruby; } + a : ID ( ID | INT )* EOF; + ID : 'a'..'z'+ ; + INT : '0'..'9'+ ; + WS : (' '|'\n') {$channel=HIDDEN;} ; + > + + debugger = parse( grammar, :a, "a 1 b c 3" ) + debugger.success.should be_true + + expected = [ + [ "enter_rule", @grammar_path, "a" ], + [ "location", "3", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "5" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_token", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_hidden_token", "1", "6", "hidden", "1", "1", '" "' ], + [ "location", "3", "8" ], + [ "enter_subrule", "1" ], + [ "enter_decision", "1" ], + [ "look", "1", "2", "5", "default", "1", "2", "\"1\"" ], + [ "exit_decision", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "8" ], + [ "look", "1", "2", "5", "default", "1", "2", "\"1\"" ], + [ "consume_token", "2", "5", "default", "1", "2", "\"1\"" ], + [ "consume_hidden_token", "3", "6", "hidden", "1", "3", '" "' ], + [ "enter_decision", "1" ], + [ "look", "1", "4", "4", "default", "1", "4", "\"b\"" ], + [ "exit_decision", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "8" ], + [ "look", "1", "4", "4", "default", "1", "4", "\"b\"" ], + [ "consume_token", "4", "4", "default", "1", "4", "\"b\"" ], + [ "consume_hidden_token", "5", "6", "hidden", "1", "5", '" "' ], + [ "enter_decision", "1" ], + [ "look", "1", "6", "4", "default", "1", "6", "\"c\"" ], + [ "exit_decision", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "8" ], + [ "look", "1", "6", "4", "default", "1", "6", "\"c\"" ], + [ "consume_token", "6", "4", "default", "1", "6", "\"c\"" ], + [ "consume_hidden_token", "7", "6", "hidden", "1", "7", '" "' ], + [ "enter_decision", "1" ], + [ "look", "1", "8", "5", "default", "1", "8", "\"3\"" ], + [ "exit_decision", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "8" ], + [ "look", "1", "8", "5", "default", "1", "8", "\"3\"" ], + [ "consume_token", "8", "5", "default", "1", "8", "\"3\"" ], + [ "enter_decision", "1" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "exit_decision", "1" ], + [ "exit_subrule", "1" ], + [ "location", "3", "22" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "consume_token", "-1", "-1", "default", "0", "-1", "nil" ], + [ "location", "3", "25" ], + [ "exit_rule", @grammar_path, "a" ], + [ "terminate" ] + ] + debugger.events.should == expected + end + + example 'debug-mode parser events triggered by a mismatched set error' do + grammar = %q< + grammar MismatchedSetError; + options { language=Ruby; } + a : ID ( ID | INT ) EOF; + ID : 'a'..'z'+ ; + INT : '0'..'9'+ ; + WS : (' '|'\n') {$channel=HIDDEN;} ; + > + + debugger = parse( grammar, :a, "a" ) + debugger.success.should be_true + + expected = [ + [ "enter_rule", @grammar_path, "a" ], + [ "location", "3", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "5" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_token", "0", "4", "default", "1", "0", "\"a\"" ], + [ "location", "3", "8" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "recognition_exception", "ANTLR3::Error::MismatchedSet", "1", "0", "-1" ], + [ "recognition_exception", "ANTLR3::Error::MismatchedSet", "1", "0", "-1" ], + [ "begin_resync" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "end_resync" ], + [ "location", "3", "24" ], + [ "exit_rule", @grammar_path, "a" ], + [ "terminate" ] + ] + + debugger.events.should == expected + end + + example 'debug-mode parser block-location events for subrules' do + grammar = %q< + grammar Block; + options { language=Ruby; } + a : ID ( b | c ) EOF; + b : ID; + c : INT; + ID : 'a'..'z'+ ; + INT : '0'..'9'+ ; + WS : (' '|'\n') {$channel=HIDDEN;} ; + > + + debugger = parse( grammar, :a, "a 1" ) + debugger.success.should be_true + + expected = [ + [ "enter_rule", @grammar_path, "a" ], + [ "location", "3", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "5" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_token", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_hidden_token", "1", "6", "hidden", "1", "1", '" "' ], + [ "location", "3", "8" ], + [ "enter_subrule", "1" ], + [ "enter_decision", "1" ], + [ "look", "1", "2", "5", "default", "1", "2", "\"1\"" ], + [ "exit_decision", "1" ], + [ "enter_alternative", "2" ], + [ "location", "3", "14" ], + [ "enter_rule", @grammar_path, "c" ], + [ "location", "5", "1" ], + [ "enter_alternative", "1" ], + [ "location", "5", "5" ], + [ "look", "1", "2", "5", "default", "1", "2", "\"1\"" ], + [ "look", "1", "2", "5", "default", "1", "2", "\"1\"" ], + [ "consume_token", "2", "5", "default", "1", "2", "\"1\"" ], + [ "location", "5", "8" ], + [ "exit_rule", @grammar_path, "c" ], + [ "exit_subrule", "1" ], + [ "location", "3", "18" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "consume_token", "-1", "-1", "default", "0", "-1", "nil" ], + [ "location", "3", "21" ], + [ "exit_rule", @grammar_path, "a" ], + [ "terminate" ] + ] + debugger.events.should == expected + end + + example 'debug-mode parser events triggered by a no viable alternative error' do + grammar = %q< + grammar NoViableAlt; + options { language=Ruby; } + a : ID ( b | c ) EOF; + b : ID; + c : INT; + ID : 'a'..'z'+ ; + INT : '0'..'9'+ ; + BANG : '!' ; + WS : (' '|'\n') {$channel=HIDDEN;} ; + > + + debugger = parse( grammar, :a, "a !" ) + debugger.success.should be_true + + expected = [ + [ "enter_rule", @grammar_path, "a" ], + [ "location", "3", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "5" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_token", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_hidden_token", "1", "7", "hidden", "1", "1", '" "' ], + [ "location", "3", "8" ], + [ "enter_subrule", "1" ], + [ "enter_decision", "1" ], + [ "look", "1", "2", "6", "default", "1", "2", "\"!\"" ], + [ "look", "1", "2", "6", "default", "1", "2", "\"!\"" ], + [ "recognition_exception", "ANTLR3::Error::NoViableAlternative", "2", "1", "2" ], + [ "exit_decision", "1" ], + [ "exit_subrule", "1" ], + [ "recognition_exception", "ANTLR3::Error::NoViableAlternative", "2", "1", "2" ], + [ "begin_resync" ], + [ "look", "1", "2", "6", "default", "1", "2", "\"!\"" ], + [ "consume_token", "2", "6", "default", "1", "2", "\"!\"" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "end_resync" ], + [ "location", "3", "21" ], + [ "exit_rule", @grammar_path, "a" ], + [ "terminate" ] + ] + debugger.events.should == expected + end + + example 'debug-mode parser block-location events triggered by rules' do + grammar = %q< + grammar RuleBlock; + options { language=Ruby; } + a : b | c; + b : ID; + c : INT; + ID : 'a'..'z'+ ; + INT : '0'..'9'+ ; + WS : (' '|'\n') {$channel=HIDDEN;} ; + > + + debugger = parse( grammar, :a, "1" ) + debugger.success.should be_true + + expected = [ + [ "enter_rule", @grammar_path, "a" ], + [ "location", "3", "1" ], + [ "enter_decision", "1" ], + [ "look", "1", "0", "5", "default", "1", "0", "\"1\"" ], + [ "exit_decision", "1" ], + [ "enter_alternative", "2" ], + [ "location", "3", "9" ], + [ "enter_rule", @grammar_path, "c" ], + [ "location", "5", "1" ], + [ "enter_alternative", "1" ], + [ "location", "5", "5" ], + [ "look", "1", "0", "5", "default", "1", "0", "\"1\"" ], + [ "look", "1", "0", "5", "default", "1", "0", "\"1\"" ], + [ "consume_token", "0", "5", "default", "1", "0", "\"1\"" ], + [ "location", "5", "8" ], + [ "exit_rule", @grammar_path, "c" ], + [ "location", "3", "10" ], + [ "exit_rule", @grammar_path, "a" ], + [ "terminate" ] + ] + + debugger.events.should == expected + end + + example 'debug-mode parser block-location events triggered by single-alternative rules' do + grammar = %q< + grammar RuleBlockSingleAlt; + options { language=Ruby; } + a : b; + b : ID; + ID : 'a'..'z'+ ; + INT : '0'..'9'+ ; + WS : (' '|'\n') {$channel=HIDDEN;} ; + > + + debugger = parse( grammar, :a, "a" ) + debugger.success.should be_true + + expected = [ + [ "enter_rule", @grammar_path, "a" ], + [ "location", "3", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "5" ], + [ "enter_rule", @grammar_path, "b" ], + [ "location", "4", "1" ], + [ "enter_alternative", "1" ], + [ "location", "4", "5" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_token", "0", "4", "default", "1", "0", "\"a\"" ], + [ "location", "4", "7" ], + [ "exit_rule", @grammar_path, "b" ], + [ "location", "3", "6" ], + [ "exit_rule", @grammar_path, "a" ], + [ "terminate" ] + ] + + debugger.events.should == expected + end + + example 'debug-mode parser block-location events triggered by single-alternative subrules' do + grammar = %q< + grammar BlockSingleAlt; + options { language=Ruby; } + a : ( b ); + b : ID; + ID : 'a'..'z'+ ; + INT : '0'..'9'+ ; + WS : (' '|'\n') {$channel=HIDDEN;} ; + > + + debugger = parse( grammar, :a, "a" ) + debugger.success.should be_true + + expected = [ + [ "enter_rule", @grammar_path, "a" ], + [ "location", "3", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "5" ], + [ "enter_alternative", "1" ], + [ "location", "3", "7" ], + [ "enter_rule", @grammar_path, "b" ], + [ "location", "4", "1" ], + [ "enter_alternative", "1" ], + [ "location", "4", "5" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_token", "0", "4", "default", "1", "0", "\"a\"" ], + [ "location", "4", "7" ], + [ "exit_rule", @grammar_path, "b" ], + [ "location", "3", "10" ], + [ "exit_rule", @grammar_path, "a" ], + [ "terminate" ] + ] + debugger.events.should == expected + end + + example 'debug-mode parser block-location events triggered by invoking a cyclic DFA for prediction' do + grammar = %q< + grammar DFA; + options { language=Ruby; } + a : ( b | c ) EOF; + b : ID* INT; + c : ID+ BANG; + ID : 'a'..'z'+ ; + INT : '0'..'9'+ ; + BANG : '!'; + WS : (' '|'\n') {$channel=HIDDEN;} ; + > + + debugger = parse( grammar, :a, "a!" ) + debugger.success.should be_true + + expected = [ + [ "enter_rule", @grammar_path, "a" ], + [ "location", "3", "1" ], + [ "enter_alternative", "1" ], + [ "location", "3", "5" ], + [ "enter_subrule", "1" ], + [ "enter_decision", "1" ], + [ "mark", "0" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_token", "0", "4", "default", "1", "0", "\"a\"" ], + [ "look", "1", "1", "6", "default", "1", "1", "\"!\"" ], + [ "consume_token", "1", "6", "default", "1", "1", "\"!\"" ], + [ "rewind", "0" ], + [ "exit_decision", "1" ], + [ "enter_alternative", "2" ], + [ "location", "3", "11" ], + [ "enter_rule", @grammar_path, "c" ], + [ "location", "5", "1" ], + [ "enter_alternative", "1" ], + [ "location", "5", "5" ], + [ "enter_subrule", "3" ], + [ "enter_decision", "3" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "exit_decision", "3" ], + [ "enter_alternative", "1" ], + [ "location", "5", "5" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "look", "1", "0", "4", "default", "1", "0", "\"a\"" ], + [ "consume_token", "0", "4", "default", "1", "0", "\"a\"" ], + [ "enter_decision", "3" ], + [ "look", "1", "1", "6", "default", "1", "1", "\"!\"" ], + [ "exit_decision", "3" ], + [ "exit_subrule", "3" ], + [ "location", "5", "9" ], + [ "look", "1", "1", "6", "default", "1", "1", "\"!\"" ], + [ "look", "1", "1", "6", "default", "1", "1", "\"!\"" ], + [ "consume_token", "1", "6", "default", "1", "1", "\"!\"" ], + [ "location", "5", "13" ], + [ "exit_rule", @grammar_path, "c" ], + [ "exit_subrule", "1" ], + [ "location", "3", "15" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "look", "1", "-1", "-1", "default", "0", "-1", "nil" ], + [ "consume_token", "-1", "-1", "default", "0", "-1", "nil" ], + [ "location", "3", "18" ], + [ "exit_rule", @grammar_path, "a" ], + [ "terminate" ] + ] + debugger.events.should == expected + end + + example 'debug-mode AST-building parser events' do + grammar = %q/ + grammar BasicAST; + options { + language=Ruby; + output=AST; + } + a : ( b | c ) EOF!; + b : ID* INT -> ^(INT ID*); + c : ID+ BANG -> ^(BANG ID+); + ID : 'a'..'z'+ ; + INT : '0'..'9'+ ; + BANG : '!'; + WS : (' '|'\n') {$channel=HIDDEN;} ; + / + listener = ANTLR3::Debug::RecordEventListener.new + parse( grammar, :a, "a!", :listener => listener ) + end + +end |