| #!/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 |