1 #!/usr/bin/ruby 2 # encoding: utf-8 3 4 require 'antlr3/test/functional' 5 6 class TestScopes1 < ANTLR3::Test::Functional 7 8 inline_grammar( <<-'END' ) 9 grammar SimpleScope; 10 11 options { 12 language = Ruby; 13 } 14 15 prog 16 scope { 17 name 18 } 19 : ID {$prog::name=$ID.text;} 20 ; 21 22 ID : ('a'..'z')+ 23 ; 24 25 WS : (' '|'\n'|'\r')+ {$channel=HIDDEN} 26 ; 27 END 28 29 example "parsing 'foobar'" do 30 lexer = SimpleScope::Lexer.new( 'foobar' ) 31 parser = SimpleScope::Parser.new lexer 32 parser.prog 33 end 34 end 35 36 class TestScopes2 < ANTLR3::Test::Functional 37 inline_grammar( <<-'END' ) 38 grammar LotsaScopes; 39 40 options { 41 language = Ruby; 42 } 43 44 /* global scopes */ 45 46 scope aScope { 47 names; 48 } 49 50 @members { 51 def emit_error_message(msg) 52 # do nothing 53 end 54 55 def report_error(error) 56 raise error 57 end 58 } 59 60 a 61 scope aScope; 62 : {$aScope::names = []} ID* 63 ; 64 65 66 /* rule scopes, from the book, final beta, p.147 */ 67 68 b[v] 69 scope {x} 70 : {$b::x = v;} b2 71 ; 72 73 b2 74 : b3 75 ; 76 77 b3 78 : {$b::x}?=> ID // only visible, if b was called with True 79 | NUM 80 ; 81 82 83 /* rule scopes, from the book, final beta, p.148 */ 84 85 c returns [res] 86 scope { 87 symbols 88 } 89 @init { 90 $c::symbols = Set.new; 91 } 92 : '{' c1* c2+ '}' 93 { $res = $c::symbols; } 94 ; 95 96 c1 97 : 'int' ID {$c::symbols.add($ID.text)} ';' 98 ; 99 100 c2 101 : ID '=' NUM ';' 102 { 103 $c::symbols.include?($ID.text) or raise RuntimeError, $ID.text 104 } 105 ; 106 107 /* recursive rule scopes, from the book, final beta, p.150 */ 108 109 d returns [res] 110 scope { 111 symbols 112 } 113 @init { 114 $d::symbols = Set.new 115 } 116 : '{' d1* d2* '}' 117 { $res = $d::symbols; } 118 ; 119 120 d1 121 : 'int' ID {$d::symbols.add($ID.text)} ';' 122 ; 123 124 d2 125 : ID '=' NUM ';' 126 { 127 catch(:found) do 128 level = ($d.length - 1).downto(0) do |s| 129 $d[s].symbols.include?($ID.text) and throw(:found) 130 end 131 raise $ID.text 132 end 133 } 134 | d 135 ; 136 137 /* recursive rule scopes, access bottom-most scope */ 138 139 e returns [res] 140 scope { 141 a 142 } 143 @after { 144 $res = $e::a; 145 } 146 : NUM { $e[0]::a = Integer($NUM.text); } 147 | '{' e '}' 148 ; 149 150 151 /* recursive rule scopes, access with negative index */ 152 153 f returns [res] 154 scope { 155 a 156 } 157 @after { 158 $res = $f::a; 159 } 160 : NUM { $f[-2]::a = Integer($NUM.text); } 161 | '{' f '}' 162 ; 163 164 165 /* tokens */ 166 167 ID : ('a'..'z')+ 168 ; 169 170 NUM : ('0'..'9')+ 171 ; 172 173 WS : (' '|'\n'|'\r')+ {$channel=HIDDEN} 174 ; 175 END 176 177 example "parsing 'foobar' with rule a" do 178 lexer = LotsaScopes::Lexer.new( "foobar" ) 179 parser = LotsaScopes::Parser.new lexer 180 parser.a 181 end 182 183 example "failing to parse 'foobar' with rule b[false]" do 184 lexer = LotsaScopes::Lexer.new( "foobar" ) 185 parser = LotsaScopes::Parser.new lexer 186 proc { parser.b( false ) }.should raise_error( ANTLR3::RecognitionError ) 187 end 188 189 example "parsing 'foobar' with rule b[true]" do 190 lexer = LotsaScopes::Lexer.new( "foobar" ) 191 parser = LotsaScopes::Parser.new lexer 192 parser.b( true ) 193 end 194 195 example "parsing a decl block with rule c" do 196 lexer = LotsaScopes::Lexer.new( <<-END.here_indent! ) 197 | { 198 | int i; 199 | int j; 200 | i = 0; 201 | } 202 END 203 parser = LotsaScopes::Parser.new lexer 204 205 symbols = parser.c 206 symbols.should have( 2 ).things 207 symbols.should include 'i' 208 symbols.should include 'j' 209 end 210 211 example "failing to parse undeclared symbols with rule c" do 212 lexer = LotsaScopes::Lexer.new( <<-END.here_indent! ) 213 | { 214 | int i; 215 | int j; 216 | i = 0; 217 | x = 4; 218 | } 219 END 220 parser = LotsaScopes::Parser.new lexer 221 222 proc { parser.c }.should raise_error RuntimeError, 'x' 223 end 224 225 example "parsing nested declaration blocks" do 226 lexer = LotsaScopes::Lexer.new( <<-END.here_indent! ) 227 | { 228 | int i; 229 | int j; 230 | i = 0; 231 | { 232 | int i; 233 | int x; 234 | x = 5; 235 | } 236 | } 237 END 238 parser = LotsaScopes::Parser.new lexer 239 240 symbols = parser.d 241 symbols.should have( 2 ).things 242 symbols.should include 'i' 243 symbols.should include 'j' 244 end 245 246 example "parsing a deeply nested set of blocks with rule e" do 247 lexer = LotsaScopes::Lexer.new( <<-END.here_indent! ) 248 | { { { { 12 } } } } 249 END 250 251 parser = LotsaScopes::Parser.new lexer 252 parser.e.should == 12 253 end 254 255 example "parsing a deeply nested set of blocks with rule f" do 256 lexer = LotsaScopes::Lexer.new( <<-END.here_indent! ) 257 | { { { { 12 } } } } 258 END 259 260 parser = LotsaScopes::Parser.new lexer 261 parser.f.should == nil 262 end 263 264 example "parsing a 2-level nested set of blocks with rule f" do 265 lexer = LotsaScopes::Lexer.new( <<-END.here_indent! ) 266 | { { 12 } } 267 END 268 parser = LotsaScopes::Parser.new lexer 269 270 parser.f.should == nil 271 end 272 273 end 274