Home | History | Annotate | Download | only in parser
      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