Home | History | Annotate | Download | only in parser
      1 #!/usr/bin/ruby
      2 # encoding: utf-8
      3 
      4 require 'antlr3/test/functional'
      5 
      6 class TestLLStarParser < ANTLR3::Test::Functional
      7   inline_grammar( <<-'END' )
      8     grammar LLStar;
      9     
     10     options { language = Ruby; }
     11     @header {  require 'stringio' }
     12     @init { @output = StringIO.new() }
     13     @members {
     14       def output
     15         @output.string
     16       end
     17     }
     18     
     19     program
     20         :   declaration+
     21         ;
     22     
     23     /** In this rule, the functionHeader left prefix on the last two
     24      *  alternatives is not LL(k) for a fixed k.  However, it is
     25      *  LL(*).  The LL(*) algorithm simply scans ahead until it sees
     26      *  either the ';' or the '{' of the block and then it picks
     27      *  the appropriate alternative.  Lookhead can be arbitrarily
     28      *  long in theory, but is <=10 in most cases.  Works great.
     29      *  Use ANTLRWorks to see the look use (step by Location)
     30      *  and look for blue tokens in the input window pane. :)
     31      */
     32     declaration
     33         :   variable
     34         |   functionHeader ';'
     35       { @output.puts( $functionHeader.name + " is a declaration") }
     36         |   functionHeader block
     37       { @output.puts( $functionHeader.name + " is a definition") }
     38         ;
     39     
     40     variable
     41         :   type declarator ';'
     42         ;
     43     
     44     declarator
     45         :   ID 
     46         ;
     47     
     48     functionHeader returns [name]
     49         :   type ID '(' ( formalParameter ( ',' formalParameter )* )? ')'
     50       {$name = $ID.text}
     51         ;
     52     
     53     formalParameter
     54         :   type declarator        
     55         ;
     56     
     57     type
     58         :   'int'   
     59         |   'char'  
     60         |   'void'
     61         |   ID        
     62         ;
     63     
     64     block
     65         :   '{'
     66                 variable*
     67                 stat*
     68             '}'
     69         ;
     70     
     71     stat: forStat
     72         | expr ';'      
     73         | block
     74         | assignStat ';'
     75         | ';'
     76         ;
     77     
     78     forStat
     79         :   'for' '(' assignStat ';' expr ';' assignStat ')' block        
     80         ;
     81     
     82     assignStat
     83         :   ID '=' expr        
     84         ;
     85     
     86     expr:   condExpr
     87         ;
     88     
     89     condExpr
     90         :   aexpr ( ('==' | '<') aexpr )?
     91         ;
     92     
     93     aexpr
     94         :   atom ( '+' atom )*
     95         ;
     96     
     97     atom
     98         : ID      
     99         | INT      
    100         | '(' expr ')'
    101         ; 
    102     
    103     ID  :   ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
    104         ;
    105     
    106     INT :	('0'..'9')+
    107         ;
    108     
    109     WS  :   (   ' '
    110             |   '\t'
    111             |   '\r'
    112             |   '\n'
    113             )+
    114             {$channel=HIDDEN}
    115         ;
    116   END
    117   
    118   
    119   example "parsing with a LL(*) grammar" do
    120     lexer = LLStar::Lexer.new( <<-'END'.fixed_indent( 0 ) )
    121       char c;
    122       int x;
    123       
    124       void bar(int x);
    125       
    126       int foo(int y, char d) {
    127         int i;
    128         for (i=0; i<3; i=i+1) {
    129           x=3;
    130           y=5;
    131         }
    132       }
    133     END
    134     parser = LLStar::Parser.new lexer
    135     
    136     parser.program
    137     parser.output.should == <<-'END'.fixed_indent( 0 )
    138       bar is a declaration
    139       foo is a definition
    140     END
    141   end
    142   
    143 end
    144