Home | History | Annotate | Download | only in main
      1 #!/usr/bin/ruby
      2 # encoding: utf-8
      3 
      4 require 'antlr3'
      5 require 'antlr3/test/functional'
      6 
      7 ENV.delete( 'RUBYOPT' )
      8 ENV[ 'RUBYLIB' ] = ANTLR3.library_path
      9 
     10 class TestMainUtility < ANTLR3::Test::Functional
     11   
     12   example 'overriding the built-in script action using the @main named-action' do
     13     grammar = inline_grammar( <<-'END' )
     14       lexer grammar MainOverride;
     15       options { language = Ruby; }
     16       
     17       @main {
     18         raise( "the main block ran" )
     19       }
     20       
     21       ID: ('a'..'z' | '\u00c0'..'\u00ff')+;
     22       WS: ' '+ { $channel = HIDDEN; };
     23     END
     24     
     25     # when this grammar is compiled and the resulting ruby files
     26     # are loaded as a library, the custom @main block
     27     # should not be executed
     28     proc { compile_and_load( grammar ) }.should_not raise_error
     29     
     30     # this assertion verifies that the main region is executed
     31     # when the parser script is run directly
     32     lexer_script = grammar.target_files.first
     33     out = `ruby #{ lexer_script } 2>&1`.chomp
     34     out.should =~ /the main block ran/
     35   end
     36   
     37   example 'using Lexer.main() to run the built-in lexer utility script on a source file' do
     38     input_path = local_path( 'input.txt' )
     39     open( input_path, 'w' ) { |f| f.write( "yada yada" ) }
     40     
     41     compile_and_load inline_grammar( <<-'END' )
     42       lexer grammar LexerMainWithSourceFile;
     43       options { language = Ruby; }
     44       
     45       ID: 'a'..'z'+;
     46       WS: ' '+ { $channel = HIDDEN; };
     47     END
     48     
     49     begin
     50       output = StringIO.new
     51       input = File.open( input_path )
     52       LexerMainWithSourceFile::Lexer.main( [], :input => input, :output => output )
     53       
     54       out_lines = output.string.split( /\n/ )
     55       out_lines.should have( 3 ).things
     56     ensure
     57       File.delete( input_path )
     58     end
     59   end
     60 
     61   example 'using Lexer.main to run the built-in lexer utility script on input from $stdin' do
     62     input = StringIO.new( "yada yada" )    # <- used to simulate $stdin
     63     output = StringIO.new
     64     
     65     compile_and_load inline_grammar( <<-'END' )
     66       lexer grammar LexerMainFromStdIO;
     67       options { language = Ruby; }
     68       
     69       ID: 'a'..'z'+;
     70       WS: ' '+ { $channel = HIDDEN; };
     71     END
     72     
     73     LexerMainFromStdIO::Lexer.main( [], :input => input, :output => output )
     74     lines = output.string.split( /\n/ )
     75     lines.should have( 3 ).things
     76   end
     77 
     78   example 'using Parser.main to run the built-in parser script utility with a combo grammar' do
     79     compile_and_load inline_grammar( <<-'END' )
     80       grammar MainForCombined;
     81       options { language = Ruby; }
     82       r returns [res]: (ID)+ EOF { $res = $text; };
     83       
     84       ID: 'a'..'z'+;
     85       WS: ' '+ { $channel = HIDDEN; };
     86     END
     87     
     88     output = StringIO.new
     89     input = StringIO.new( 'yada yada' )
     90     
     91     MainForCombined::Parser.main( 
     92         %w(--rule r --lexer-name MainForCombined::Lexer),
     93         :input => input, :output => output )
     94     lines = output.string.split( "\n" )
     95     lines.should have( 4 ).things
     96   end
     97   
     98   example 'using built-in main to inspect AST constructed by an AST-building parser' do
     99     compile_and_load inline_grammar( <<-'END' )
    100       grammar ASTParserMain;
    101       options {
    102         language = Ruby;
    103         output = AST;
    104       }
    105       r: ID OP^ ID EOF!;
    106       
    107       ID: 'a'..'z'+;
    108       OP: '+';
    109       WS: ' '+ { $channel = HIDDEN; };
    110     END
    111     
    112     output = StringIO.new
    113     input  = StringIO.new 'yada + yada'
    114     ASTParserMain::Parser.main( 
    115       %w(--rule r --lexer-name ASTParserMain::Lexer),
    116       :input => input, :output => output )
    117     output = output.string.strip
    118     output.should == "(+ yada yada)"
    119   end
    120   
    121   example "using a tree parser's built-in main" do
    122     compile_and_load inline_grammar( <<-'END' )
    123       grammar TreeMain;
    124       options {
    125         language = Ruby;
    126         output = AST;
    127       }
    128       
    129       r: ID OP^ ID EOF!;
    130       
    131       ID: 'a'..'z'+;
    132       OP: '+';
    133       WS: ' '+ { $channel = HIDDEN; };
    134     END
    135     compile_and_load inline_grammar( <<-'END' )
    136       tree grammar TreeMainWalker;
    137       options {
    138         language=Ruby;
    139         ASTLabelType=CommonTree;
    140         tokenVocab=TreeMain;
    141       }
    142       r returns [res]: ^(OP a=ID b=ID)
    143         { $res = "\%s \%s \%s" \% [$a.text, $OP.text, $b.text] }
    144         ;
    145     END
    146     
    147     output = StringIO.new
    148     input  = StringIO.new 'a+b'
    149     
    150     TreeMainWalker::TreeParser.main( 
    151       %w(--rule r --parser-name TreeMain::Parser
    152          --parser-rule r --lexer-name TreeMain::Lexer),
    153       :input => input, :output => output )
    154     output = output.string.strip
    155     output.should == '"a + b"'
    156   end
    157   
    158   example "using a tree parser's built-in main to inspect AST rewrite output" do
    159     compile_and_load inline_grammar( <<-'END' )
    160       grammar TreeRewriteMain;
    161       options {
    162         language = Ruby;
    163         output = AST;
    164       }
    165       
    166       r: ID OP^ ID EOF!;
    167       
    168       ID: 'a'..'z'+;
    169       OP: '+';
    170       WS: ' '+ { $channel = HIDDEN; };
    171     END
    172     compile_and_load inline_grammar( <<-'END' )
    173       tree grammar TreeRewriteMainWalker;
    174       options {
    175         language=Ruby;
    176         ASTLabelType=CommonTree;
    177         tokenVocab=TreeRewriteMain;
    178         output=AST;
    179       }
    180       tokens { ARG; }
    181       r: ^(OP a=ID b=ID) -> ^(OP ^(ARG ID) ^(ARG ID));
    182     END
    183     
    184     output = StringIO.new
    185     input  = StringIO.new 'a+b'
    186     TreeRewriteMainWalker::TreeParser.main( 
    187       %w(--rule r --parser-name TreeRewriteMain::Parser
    188          --parser-rule r --lexer-name TreeRewriteMain::Lexer),
    189       :input => input, :output => output
    190     )
    191     
    192     output = output.string.strip
    193     output.should == '(+ (ARG a) (ARG b))'
    194   end
    195   
    196   example 'using built-in main with a delegating grammar' do
    197     inline_grammar( <<-'END' )
    198       parser grammar MainSlave;
    199       options { language=Ruby; }
    200       a : B;
    201     END
    202     master = inline_grammar( <<-'END' )
    203       grammar MainMaster;
    204       options { language=Ruby; }
    205       import MainSlave;
    206       s returns [res]: a { $res = $a.text };
    207       B : 'b' ; // defines B from inherited token space
    208       WS : (' '|'\n') {skip} ;
    209     END
    210     master.compile
    211     for file in master.target_files
    212       require( file )
    213     end
    214     
    215     output = StringIO.new
    216     input = StringIO.new 'b'
    217     
    218     MainMaster::Parser.main( 
    219       %w(--rule s --lexer-name MainMaster::Lexer),
    220       :input => input, :output => output )
    221     output = output.string.strip
    222     output.should == 'b'.inspect
    223   end
    224 
    225   #test :LexerEncoding do
    226   #  broken!("Non-ASCII encodings have not been implemented yet")
    227   #  grammar = inline_grammar(<<-'END')
    228   #    lexer grammar T3;
    229   #    options {
    230   #      language = Ruby;
    231   #      }
    232   #
    233   #    ID: ('a'..'z' | '\u00c0'..'\u00ff')+;
    234   #    WS: ' '+ { $channel = HIDDEN; };
    235   #  END
    236   #  compile grammar
    237   #  input = StringIO.new("f br")
    238   #  output = StringIO.new('')
    239   #  lexer_class.main(%w(--encoding utf-8), :input => input, :output => output)
    240   #  puts output.string
    241   #  lines = output.string.split(/\n/)
    242   #  lines.should have(3).things
    243   #end
    244 
    245 end
    246