Home | History | Annotate | Download | only in ast-output
      1 #!/usr/bin/ruby
      2 # encoding: utf-8
      3 
      4 require 'antlr3/test/functional'
      5 
      6 class TestASTConstructingParser < ANTLR3::Test::Functional
      7 
      8   compile inline_grammar( <<-'END' )
      9     grammar ASTBuilder;
     10     options {
     11       language = Ruby;
     12       output = AST;
     13     }
     14     
     15     tokens {
     16         VARDEF;
     17         FLOAT;
     18         EXPR;
     19         BLOCK;
     20         VARIABLE;
     21         FIELD;
     22         CALL;
     23         INDEX;
     24         FIELDACCESS;
     25     }
     26     
     27     @init {
     28       @flag = false
     29     }
     30     
     31     @members {
     32       attr_accessor :flag
     33       
     34       def report_error(e)
     35         # do nothing
     36       end
     37       
     38     }
     39     
     40     
     41     r1
     42         : INT ('+'^ INT)*
     43         ;
     44     
     45     r2
     46         : 'assert'^ x=expression (':'! y=expression)? ';'!
     47         ;
     48     
     49     r3
     50         : 'if'^ expression s1=statement ('else'! s2=statement)?
     51         ;
     52     
     53     r4
     54         : 'while'^ expression statement
     55         ;
     56     
     57     r5
     58         : 'return'^ expression? ';'!
     59         ;
     60     
     61     r6
     62         : (INT|ID)+
     63         ;
     64     
     65     r7
     66         : INT -> 
     67         ;
     68     
     69     r8
     70         : 'var' ID ':' type -> ^('var' type ID) 
     71         ;
     72     
     73     r9
     74         : type ID ';' -> ^(VARDEF type ID) 
     75         ;
     76     
     77     r10
     78         : INT -> { ANTLR3::AST::CommonTree.new(ANTLR3::CommonToken.create(:type => FLOAT, :text => ($INT.text + ".0")))}
     79         ;
     80     
     81     r11
     82         : expression -> ^(EXPR expression)
     83         | -> EXPR
     84         ;
     85     
     86     r12
     87         : ID (',' ID)* -> ID+
     88         ;
     89     
     90     r13
     91         : type ID (',' ID)* ';' -> ^(type ID+)
     92         ;
     93     
     94     r14
     95         :   expression? statement* type+
     96             -> ^(EXPR expression? statement* type+)
     97         ;
     98     
     99     r15
    100         : INT -> INT INT
    101         ;
    102     
    103     r16
    104         : 'int' ID (',' ID)* -> ^('int' ID)+
    105         ;
    106     
    107     r17
    108         : 'for' '(' start=statement ';' expression ';' next=statement ')' statement
    109             -> ^('for' $start expression $next statement)
    110         ;
    111     
    112     r18
    113         : t='for' -> ^(BLOCK)
    114         ;
    115     
    116     r19
    117         : t='for' -> ^(BLOCK[$t])
    118         ;
    119     
    120     r20
    121         : t='for' -> ^(BLOCK[$t,"FOR"])
    122         ;
    123     
    124     r21
    125         : t='for' -> BLOCK
    126         ;
    127     
    128     r22
    129         : t='for' -> BLOCK[$t]
    130         ;
    131     
    132     r23
    133         : t='for' -> BLOCK[$t,"FOR"]
    134         ;
    135     
    136     r24
    137         : r=statement expression -> ^($r expression)
    138         ;
    139     
    140     r25
    141         : r+=statement (',' r+=statement)+ expression -> ^($r expression)
    142         ;
    143     
    144     r26
    145         : r+=statement (',' r+=statement)+ -> ^(BLOCK $r+)
    146         ;
    147     
    148     r27
    149         : r=statement expression -> ^($r ^($r expression))
    150         ;
    151     
    152     r28
    153         : ('foo28a'|'foo28b') ->
    154         ;
    155     
    156     r29
    157         : (r+=statement)* -> ^(BLOCK $r+)
    158         ;
    159     
    160     r30
    161         : statement* -> ^(BLOCK statement?)
    162         ;
    163     
    164     r31
    165         : modifier type ID ('=' expression)? ';'
    166             -> {@flag == 0}? ^(VARDEF ID modifier* type expression?)
    167             -> {@flag == 1}? ^(VARIABLE ID modifier* type expression?)
    168             ->                   ^(FIELD ID modifier* type expression?)
    169         ;
    170     
    171     r32[which]
    172       : ID INT -> {which==1}? ID
    173                -> {which==2}? INT
    174                -> // yield nothing as else-clause
    175       ;
    176     
    177     r33
    178         :   modifiers! statement
    179         ;
    180     
    181     r34
    182         :   modifiers! r34a[$modifiers.tree]
    183         //|   modifiers! r33b[$modifiers.tree]
    184         ;
    185     
    186     r34a[mod]
    187         :   'class' ID ('extends' sup=type)?
    188             ( 'implements' i+=type (',' i+=type)*)?
    189             '{' statement* '}'
    190             -> ^('class' ID {$mod} ^('extends' $sup)? ^('implements' $i+)? statement* )
    191         ;
    192     
    193     r35
    194         : '{' 'extends' (sup=type)? '}'
    195             ->  ^('extends' $sup)?
    196         ;
    197     
    198     r36
    199         : 'if' '(' expression ')' s1=statement
    200             ( 'else' s2=statement -> ^('if' ^(EXPR expression) $s1 $s2)
    201             |                     -> ^('if' ^(EXPR expression) $s1)
    202             )
    203         ;
    204     
    205     r37
    206         : (INT -> INT) ('+' i=INT -> ^('+' $r37 $i) )* 
    207         ;
    208     
    209     r38
    210         : INT ('+'^ INT)*
    211         ;
    212     
    213     r39
    214         : (primary->primary) // set return tree to just primary
    215             ( '(' arg=expression ')'
    216                 -> ^(CALL $r39 $arg)
    217             | '[' ie=expression ']'
    218                 -> ^(INDEX $r39 $ie)
    219             | '.' p=primary
    220                 -> ^(FIELDACCESS $r39 $p)
    221             )*
    222         ;
    223     
    224     r40
    225         : (INT -> INT) ( ('+' i+=INT)* -> ^('+' $r40 $i*) ) ';'
    226         ;
    227     
    228     r41
    229         : (INT -> INT) ( ('+' i=INT) -> ^($i $r41) )* ';'
    230         ;
    231     
    232     r42
    233         : ids+=ID (','! ids+=ID)*
    234         ;
    235     
    236     r43 returns [res]
    237         : ids+=ID! (','! ids+=ID!)* {$res = $ids.map { |id| id.text }}
    238         ;
    239     
    240     r44
    241         : ids+=ID^ (','! ids+=ID^)*
    242         ;
    243     
    244     r45
    245         : primary^
    246         ;
    247     
    248     r46 returns [res]
    249         : ids+=primary! (','! ids+=primary!)* {$res = $ids.map { |id| id.text }}
    250         ;
    251     
    252     r47
    253         : ids+=primary (','! ids+=primary)*
    254         ;
    255     
    256     r48
    257         : ids+=. (','! ids+=.)*
    258         ;
    259     
    260     r49
    261         : .^ ID
    262         ;
    263     
    264     r50
    265         : ID 
    266             -> ^({ANTLR3::AST::CommonTree.new(ANTLR3::CommonToken.create(:type => FLOAT, :text => "1.0"))} ID)
    267         ;
    268     
    269     /** templates tested:
    270         tokenLabelPropertyRef_tree
    271     */
    272     r51 returns [res]
    273         : ID t=ID ID
    274             { $res = $t.tree }
    275         ;
    276     
    277     /** templates tested:
    278         rulePropertyRef_tree
    279     */
    280     r52 returns [res]
    281     @after {
    282         $res = $tree
    283     }
    284         : ID
    285         ;
    286     
    287     /** templates tested:
    288         ruleLabelPropertyRef_tree
    289     */
    290     r53 returns [res]
    291         : t=primary
    292             { $res = $t.tree }
    293         ;
    294     
    295     /** templates tested:
    296         ruleSetPropertyRef_tree
    297     */
    298     r54 returns [res]
    299     @after {
    300         $tree = $t.tree;
    301     }
    302         : ID t=expression ID
    303         ;
    304     
    305     /** backtracking */
    306     r55
    307     options { backtrack=true; k=1; }
    308         : (modifier+ INT)=> modifier+ expression
    309         | modifier+ statement
    310         ;
    311     
    312     
    313     /** templates tested:
    314         rewriteTokenRef with len(args)>0
    315     */
    316     r56
    317         : t=ID* -> ID[$t,'foo']
    318         ;
    319     
    320     /** templates tested:
    321         rewriteTokenRefRoot with len(args)>0
    322     */
    323     r57
    324         : t=ID* -> ^(ID[$t,'foo'])
    325         ;
    326     
    327     /** templates tested:
    328         ???
    329     */
    330     r58
    331         : ({CommonTree.new(CommonToken.create(:type => FLOAT, :text => "2.0"))})^
    332         ;
    333     
    334     /** templates tested:
    335         rewriteTokenListLabelRefRoot
    336     */
    337     r59
    338         : (t+=ID)+ statement -> ^($t statement)+
    339         ;
    340     
    341     primary
    342         : ID
    343         ;
    344     
    345     expression
    346         : r1
    347         ;
    348     
    349     statement
    350         : 'fooze'
    351         | 'fooze2'
    352         ;
    353     
    354     modifiers
    355         : modifier+
    356         ;
    357     
    358     modifier
    359         : 'public'
    360         | 'private'
    361         ;
    362     
    363     type
    364         : 'int'
    365         | 'bool'
    366         ;
    367     
    368     ID : 'a'..'z' + ;
    369     INT : '0'..'9' +;
    370     WS: (' ' | '\n' | '\t')+ {$channel = HIDDEN;};
    371   END
    372   
    373   def self.ast_test( opts, &special_test )
    374     input = opts[ :input ]
    375     rule  = opts[ :rule ]
    376     expected_tree = opts[ :ast ]
    377     flag = opts[ :flag ]
    378     args = opts[ :arguments ] || []
    379     message = opts[ :message ] || rule.to_s #"should parse %p with rule %s and make tree %s" % [input, rule, expected_tree]
    380     
    381     example( message ) do
    382       lexer = ASTBuilder::Lexer.new( input )
    383       parser = ASTBuilder::Parser.new( lexer )
    384       parser.flag = flag unless flag.nil?
    385       result = parser.send( rule, *args )
    386       if special_test then instance_exec( result, &special_test )
    387       elsif expected_tree then
    388         result.tree.inspect.should == expected_tree
    389       else result.tree.should be_nil
    390       end
    391     end
    392   end
    393   
    394   ast_test :input => "1 + 2", :rule => :r1, :ast => "(+ 1 2)"
    395   
    396   ast_test :input => "assert 2+3", :rule => :r2, :ast => "(assert (+ 2 3))"
    397   
    398   ast_test :input => "assert 2+3 : 5", :rule => :r2, :ast => "(assert (+ 2 3) 5)"
    399   
    400   ast_test :input => "if 1 fooze", :rule => :r3, :ast => "(if 1 fooze)"
    401   
    402   ast_test :input => "if 1 fooze else fooze", :rule => :r3, :ast => "(if 1 fooze fooze)"
    403   
    404   ast_test :input => "while 2 fooze", :rule => :r4, :ast => "(while 2 fooze)"
    405   
    406   ast_test :input => "return;", :rule => :r5, :ast => "return"
    407   
    408   ast_test :input => "return 2+3;", :rule => :r5, :ast => "(return (+ 2 3))"
    409   
    410   ast_test :input => "3", :rule => :r6, :ast => "3"
    411   
    412   ast_test :input => "3 a", :rule => :r6, :ast => "3 a"
    413   
    414   ast_test :input => "3", :rule => :r7, :ast => nil
    415   
    416   ast_test :input => "var foo:bool", :rule => :r8, :ast => "(var bool foo)"
    417   
    418   ast_test :input => "int foo;", :rule => :r9, :ast => "(VARDEF int foo)"
    419   
    420   ast_test :input => "10", :rule => :r10, :ast => "10.0"
    421   
    422   ast_test :input => "1+2", :rule => :r11, :ast => "(EXPR (+ 1 2))"
    423   
    424   ast_test :input => "", :rule => :r11, :ast => "EXPR"
    425   
    426   ast_test :input => "foo", :rule => :r12, :ast => "foo"
    427   
    428   ast_test :input => "foo, bar, gnurz", :rule => :r12, :ast => "foo bar gnurz"
    429   
    430   ast_test :input => "int foo;", :rule => :r13, :ast => "(int foo)"
    431   
    432   ast_test :input => "bool foo, bar, gnurz;", :rule => :r13, :ast => "(bool foo bar gnurz)"
    433   
    434   ast_test :input => "1+2 int", :rule => :r14, :ast => "(EXPR (+ 1 2) int)"
    435   
    436   ast_test :input => "1+2 int bool", :rule => :r14, :ast => "(EXPR (+ 1 2) int bool)"
    437   
    438   ast_test :input => "int bool", :rule => :r14, :ast => "(EXPR int bool)"
    439   
    440   ast_test :input => "fooze fooze int bool", :rule => :r14, :ast => "(EXPR fooze fooze int bool)"
    441   
    442   ast_test :input => "7+9 fooze fooze int bool", :rule => :r14, :ast => "(EXPR (+ 7 9) fooze fooze int bool)"
    443   
    444   ast_test :input => "7", :rule => :r15, :ast => "7 7"
    445   
    446   ast_test :input => "int foo", :rule => :r16, :ast => "(int foo)"
    447   
    448   ast_test :input => "int foo, bar, gnurz", :rule => :r16, :ast => "(int foo) (int bar) (int gnurz)"
    449   
    450   ast_test :input => "for ( fooze ; 1 + 2 ; fooze ) fooze", :rule => :r17, :ast => "(for fooze (+ 1 2) fooze fooze)"
    451   
    452   ast_test :input => "for", :rule => :r18, :ast => "BLOCK"
    453   
    454   ast_test :input => "for", :rule => :r19, :ast => "for"
    455   
    456   ast_test :input => "for", :rule => :r20, :ast => "FOR"
    457   
    458   ast_test :input => "for", :rule => :r21, :ast => "BLOCK"
    459   
    460   ast_test :input => "for", :rule => :r22, :ast => "for"
    461   
    462   ast_test :input => "for", :rule => :r23, :ast => "FOR"
    463   
    464   ast_test :input => "fooze 1 + 2", :rule => :r24, :ast => "(fooze (+ 1 2))"
    465   
    466   ast_test :input => "fooze, fooze2 1 + 2", :rule => :r25, :ast => "(fooze (+ 1 2))"
    467   
    468   ast_test :input => "fooze, fooze2", :rule => :r26, :ast => "(BLOCK fooze fooze2)"
    469   
    470   ast_test :input => "fooze 1 + 2", :rule => :r27, :ast => "(fooze (fooze (+ 1 2)))"
    471   
    472   ast_test :input => "foo28a", :rule => :r28, :ast => nil
    473   
    474   ast_test :input => "public int gnurz = 1 + 2;", :rule => :r31, :ast => "(VARDEF gnurz public int (+ 1 2))", :flag => 0
    475   
    476   ast_test :input => "public int gnurz = 1 + 2;", :rule => :r31, :ast => "(VARIABLE gnurz public int (+ 1 2))", :flag => 1
    477   
    478   ast_test :input => "public int gnurz = 1 + 2;", :rule => :r31, :ast => "(FIELD gnurz public int (+ 1 2))", :flag => 2
    479   
    480   ast_test :input => 'gnurz 32', :rule => :r32, :arguments => [ 1 ], :flag => 2, :ast => 'gnurz'
    481   
    482   ast_test :input => 'gnurz 32', :rule => :r32, :arguments => [ 2 ], :flag => 2, :ast => '32'
    483   
    484   ast_test :input => 'gnurz', :rule => :r32, :arguments => [ 3 ], :flag => 2, :ast => nil
    485   
    486   ast_test :input => "public private fooze", :rule => :r33, :ast => "fooze"
    487   
    488   ast_test :input => "public class gnurz { fooze fooze2 }", :rule => :r34, :ast => "(class gnurz public fooze fooze2)"
    489   
    490   ast_test :input => "public class gnurz extends bool implements int, bool { fooze fooze2 }", :rule => :r34, :ast => "(class gnurz public (extends bool) (implements int bool) fooze fooze2)"
    491   
    492   ast_test :input => "if ( 1 + 2 ) fooze", :rule => :r36, :ast => "(if (EXPR (+ 1 2)) fooze)"
    493   
    494   ast_test :input => "1 + 2 + 3", :rule => :r37, :ast => "(+ (+ 1 2) 3)"
    495   
    496   ast_test :input => "1 + 2 + 3", :rule => :r38, :ast => "(+ (+ 1 2) 3)"
    497   
    498   ast_test :input => "gnurz[1]", :rule => :r39, :ast => "(INDEX gnurz 1)"
    499   
    500   ast_test :input => "gnurz(2)", :rule => :r39, :ast => "(CALL gnurz 2)"
    501   
    502   ast_test :input => "gnurz.gnarz", :rule => :r39, :ast => "(FIELDACCESS gnurz gnarz)"
    503   
    504   ast_test :input => "gnurz.gnarz.gnorz", :rule => :r39, :ast => "(FIELDACCESS (FIELDACCESS gnurz gnarz) gnorz)"
    505   
    506   ast_test :input => "1 + 2 + 3;", :rule => :r40, :ast => "(+ 1 2 3)"
    507   
    508   ast_test :input => "1 + 2 + 3;", :rule => :r41, :ast => "(3 (2 1))"
    509   
    510   ast_test :input => "gnurz, gnarz, gnorz", :rule => :r42, :ast => "gnurz gnarz gnorz"
    511   
    512   ast_test :input => "gnurz, gnarz, gnorz", :rule => :r43 do |result|
    513     result.tree.should be_nil
    514     result.res.should == %w(gnurz gnarz gnorz)
    515   end
    516   
    517   ast_test :input => 'gnurz, gnarz, gnorz', :rule => :r44, :ast => '(gnorz (gnarz gnurz))'
    518   
    519   ast_test :input => 'gnurz', :rule => :r45, :ast => 'gnurz'
    520   
    521   ast_test :input => 'gnurz, gnarz, gnorz', :rule => :r46 do |result|
    522     result.tree.should be_nil
    523     result.res.should == %w(gnurz gnarz gnorz)
    524   end
    525   
    526   ast_test :input => 'gnurz, gnarz, gnorz', :rule => :r47, :ast => 'gnurz gnarz gnorz'
    527   
    528   ast_test :input => 'gnurz, gnarz, gnorz', :rule => :r48, :ast => 'gnurz gnarz gnorz'
    529   
    530   ast_test :input => 'gnurz gnorz', :rule => :r49, :ast => '(gnurz gnorz)'
    531   
    532   ast_test :input => 'gnurz', :rule => :r50, :ast => '(1.0 gnurz)'
    533   
    534   ast_test :input => 'gnurza gnurzb gnurzc', :rule => :r51 do |result|
    535     result.res.inspect.should == 'gnurzb'
    536   end
    537   
    538   ast_test :input => 'gnurz', :rule => :r52, :ast => 'gnurz'
    539   
    540   ast_test :input => 'gnurz', :rule => :r53, :ast => 'gnurz'
    541   
    542   ast_test :input => 'gnurza 1 + 2 gnurzb', :rule => :r54, :ast => '(+ 1 2)'
    543   
    544   ast_test :input => 'public private 1 + 2', :rule => :r55, :ast => 'public private (+ 1 2)'
    545   
    546   ast_test :input => 'public fooze', :rule => :r55, :ast => 'public fooze'
    547   
    548   ast_test :input => 'a b c d', :rule => :r56, :ast => 'foo'
    549   
    550   ast_test :input => 'a b c d', :rule => :r57, :ast => 'foo'
    551   
    552   ast_test :input => 'a b c fooze', :rule => :r59, :ast => '(a fooze) (b fooze) (c fooze)'
    553 
    554 end
    555