#!/usr/bin/ruby # encoding: utf-8 require 'antlr3' require 'antlr3/test/functional' ENV.delete( 'RUBYOPT' ) ENV[ 'RUBYLIB' ] = ANTLR3.library_path class TestMainUtility < ANTLR3::Test::Functional example 'overriding the built-in script action using the @main named-action' do grammar = inline_grammar( <<-'END' ) lexer grammar MainOverride; options { language = Ruby; } @main { raise( "the main block ran" ) } ID: ('a'..'z' | '\u00c0'..'\u00ff')+; WS: ' '+ { $channel = HIDDEN; }; END # when this grammar is compiled and the resulting ruby files # are loaded as a library, the custom @main block # should not be executed proc { compile_and_load( grammar ) }.should_not raise_error # this assertion verifies that the main region is executed # when the parser script is run directly lexer_script = grammar.target_files.first out = `ruby #{ lexer_script } 2>&1`.chomp out.should =~ /the main block ran/ end example 'using Lexer.main() to run the built-in lexer utility script on a source file' do input_path = local_path( 'input.txt' ) open( input_path, 'w' ) { |f| f.write( "yada yada" ) } compile_and_load inline_grammar( <<-'END' ) lexer grammar LexerMainWithSourceFile; options { language = Ruby; } ID: 'a'..'z'+; WS: ' '+ { $channel = HIDDEN; }; END begin output = StringIO.new input = File.open( input_path ) LexerMainWithSourceFile::Lexer.main( [], :input => input, :output => output ) out_lines = output.string.split( /\n/ ) out_lines.should have( 3 ).things ensure File.delete( input_path ) end end example 'using Lexer.main to run the built-in lexer utility script on input from $stdin' do input = StringIO.new( "yada yada" ) # <- used to simulate $stdin output = StringIO.new compile_and_load inline_grammar( <<-'END' ) lexer grammar LexerMainFromStdIO; options { language = Ruby; } ID: 'a'..'z'+; WS: ' '+ { $channel = HIDDEN; }; END LexerMainFromStdIO::Lexer.main( [], :input => input, :output => output ) lines = output.string.split( /\n/ ) lines.should have( 3 ).things end example 'using Parser.main to run the built-in parser script utility with a combo grammar' do compile_and_load inline_grammar( <<-'END' ) grammar MainForCombined; options { language = Ruby; } r returns [res]: (ID)+ EOF { $res = $text; }; ID: 'a'..'z'+; WS: ' '+ { $channel = HIDDEN; }; END output = StringIO.new input = StringIO.new( 'yada yada' ) MainForCombined::Parser.main( %w(--rule r --lexer-name MainForCombined::Lexer), :input => input, :output => output ) lines = output.string.split( "\n" ) lines.should have( 4 ).things end example 'using built-in main to inspect AST constructed by an AST-building parser' do compile_and_load inline_grammar( <<-'END' ) grammar ASTParserMain; options { language = Ruby; output = AST; } r: ID OP^ ID EOF!; ID: 'a'..'z'+; OP: '+'; WS: ' '+ { $channel = HIDDEN; }; END output = StringIO.new input = StringIO.new 'yada + yada' ASTParserMain::Parser.main( %w(--rule r --lexer-name ASTParserMain::Lexer), :input => input, :output => output ) output = output.string.strip output.should == "(+ yada yada)" end example "using a tree parser's built-in main" do compile_and_load inline_grammar( <<-'END' ) grammar TreeMain; options { language = Ruby; output = AST; } r: ID OP^ ID EOF!; ID: 'a'..'z'+; OP: '+'; WS: ' '+ { $channel = HIDDEN; }; END compile_and_load inline_grammar( <<-'END' ) tree grammar TreeMainWalker; options { language=Ruby; ASTLabelType=CommonTree; tokenVocab=TreeMain; } r returns [res]: ^(OP a=ID b=ID) { $res = "\%s \%s \%s" \% [$a.text, $OP.text, $b.text] } ; END output = StringIO.new input = StringIO.new 'a+b' TreeMainWalker::TreeParser.main( %w(--rule r --parser-name TreeMain::Parser --parser-rule r --lexer-name TreeMain::Lexer), :input => input, :output => output ) output = output.string.strip output.should == '"a + b"' end example "using a tree parser's built-in main to inspect AST rewrite output" do compile_and_load inline_grammar( <<-'END' ) grammar TreeRewriteMain; options { language = Ruby; output = AST; } r: ID OP^ ID EOF!; ID: 'a'..'z'+; OP: '+'; WS: ' '+ { $channel = HIDDEN; }; END compile_and_load inline_grammar( <<-'END' ) tree grammar TreeRewriteMainWalker; options { language=Ruby; ASTLabelType=CommonTree; tokenVocab=TreeRewriteMain; output=AST; } tokens { ARG; } r: ^(OP a=ID b=ID) -> ^(OP ^(ARG ID) ^(ARG ID)); END output = StringIO.new input = StringIO.new 'a+b' TreeRewriteMainWalker::TreeParser.main( %w(--rule r --parser-name TreeRewriteMain::Parser --parser-rule r --lexer-name TreeRewriteMain::Lexer), :input => input, :output => output ) output = output.string.strip output.should == '(+ (ARG a) (ARG b))' end example 'using built-in main with a delegating grammar' do inline_grammar( <<-'END' ) parser grammar MainSlave; options { language=Ruby; } a : B; END master = inline_grammar( <<-'END' ) grammar MainMaster; options { language=Ruby; } import MainSlave; s returns [res]: a { $res = $a.text }; B : 'b' ; // defines B from inherited token space WS : (' '|'\n') {skip} ; END master.compile for file in master.target_files require( file ) end output = StringIO.new input = StringIO.new 'b' MainMaster::Parser.main( %w(--rule s --lexer-name MainMaster::Lexer), :input => input, :output => output ) output = output.string.strip output.should == 'b'.inspect end #test :LexerEncoding do # broken!("Non-ASCII encodings have not been implemented yet") # grammar = inline_grammar(<<-'END') # lexer grammar T3; # options { # language = Ruby; # } # # ID: ('a'..'z' | '\u00c0'..'\u00ff')+; # WS: ' '+ { $channel = HIDDEN; }; # END # compile grammar # input = StringIO.new("föö bär") # output = StringIO.new('') # lexer_class.main(%w(--encoding utf-8), :input => input, :output => output) # puts output.string # lines = output.string.split(/\n/) # lines.should have(3).things #end end