1#!/usr/bin/ruby 2# encoding: utf-8 3 4require 'antlr3' 5require 'antlr3/test/functional' 6 7ENV.delete( 'RUBYOPT' ) 8ENV[ 'RUBYLIB' ] = ANTLR3.library_path 9 10class 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öö bär") 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 245end 246