1#!/usr/bin/ruby
2# encoding: utf-8
3
4require 'antlr3/test/functional'
5
6class TestActions1 < ANTLR3::Test::Functional
7  inline_grammar( <<-'END' )
8    grammar ParserActions;
9    options { language = Ruby; }
10    
11    declaration returns [name]
12        :   functionHeader ';'
13            { $name = $functionHeader.name }
14        ;
15    
16    functionHeader returns [name]
17        : type id=ID
18          { $name = $id.text }
19        ;
20    
21    type
22        :   'int'
23        |   'char'
24        |   'void'
25        ;
26    
27    ID  :   ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
28        ;
29    
30    WS  :   (   ' '
31            |   '\t'
32            |   '\r'
33            |   '\n'
34            )+
35            {$channel=HIDDEN}
36        ;    
37  END
38  
39  example "parser action execution" do
40    lexer = ParserActions::Lexer.new "int foo;"
41    parser = ParserActions::Parser.new lexer
42    
43    parser.declaration.should == 'foo'
44  end
45  
46end
47
48
49class TestActions2 < ANTLR3::Test::Functional
50
51  inline_grammar( <<-'END' )
52    grammar AllKindsOfActions;
53    options { language = Ruby; }
54    
55    @parser::members {
56      include ANTLR3::Test::CaptureOutput
57    }
58    
59    @lexer::members {
60      include ANTLR3::Test::CaptureOutput
61    }
62    @lexer::init { @foobar = 'attribute' }
63    
64    prog
65    @init  { say('init')  }
66    @after { say('after') }
67      :   IDENTIFIER EOF
68      ;
69      catch [ RecognitionError => exc ] {
70        say('catch')
71        raise
72      }
73      finally { say('finally') }
74    
75    
76    IDENTIFIER
77        : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
78          {
79            # a comment
80            say('action')
81            say('\%p \%p \%p \%p \%p \%p \%p \%p' \% [$text, $type, $line, $pos, $index, $channel, $start, $stop])
82            say(@foobar)
83          }
84        ;
85    
86    WS: (' ' | '\n')+;
87  END
88
89
90  example "execution of special named actions" do
91    lexer = AllKindsOfActions::Lexer.new( "foobar _Ab98 \n A12sdf" )
92    parser = AllKindsOfActions::Parser.new lexer
93    parser.prog
94    
95    parser.output.should == <<-END.fixed_indent( 0 )
96      init
97      after
98      finally
99    END
100    
101    lexer.output.should == <<-END.fixed_indent( 0 )
102      action
103      "foobar" 4 1 0 -1 :default 0 5
104      attribute
105      action
106      "_Ab98" 4 1 7 -1 :default 7 11
107      attribute
108      action
109      "A12sdf" 4 2 1 -1 :default 15 20
110      attribute
111    END
112  end
113end
114
115class TestFinally < ANTLR3::Test::Functional
116
117  inline_grammar( <<-'END' )
118    grammar Finally;
119    
120    options {
121        language = Ruby;
122    }
123    
124    prog returns [events]
125    @init {events = []}
126    @after {events << 'after'}
127        :   ID {raise RuntimeError}
128        ;
129        catch [RuntimeError] {events << 'catch'}
130        finally { events << 'finally'}
131    
132    ID  :   ('a'..'z')+
133        ;
134    
135    WS  :   (' '|'\n'|'\r')+ {$channel=HIDDEN}
136        ;
137  END
138
139  
140  example "order of catch and ensure clauses" do
141    lexer = Finally::Lexer.new( 'foobar' )
142    parser = Finally::Parser.new lexer
143    parser.prog.should == %w(catch finally)
144  end
145
146end
147
148
149class TestActionScopes < ANTLR3::Test::Functional
150
151  inline_grammar( <<-'END' )
152    grammar SpecialActionScopes;
153    options { language=Ruby; }
154    
155    @all::header {
156      \$all_header_files ||= []
157      \$all_header_files << File.basename( __FILE__ )
158    }
159    
160    @all::footer {
161      \$all_footer_files ||= []
162      \$all_footer_files << File.basename( __FILE__ )
163    }
164    
165    @header {
166      \$header_location = __LINE__
167      \$header_context = self
168    }
169    
170    @footer {
171      \$footer_location = __LINE__
172      \$footer_context = self
173    }
174    
175    @module::head {
176      \$module_head_location = __LINE__
177      \$module_head_context = self
178      
179      class << self
180        attr_accessor :head_var
181      end
182    }
183    
184    @module::foot {
185      \$module_foot_location = __LINE__
186      \$module_foot_context  = self
187      
188      FOOT_CONST = 1
189    }
190    
191    @token::scheme {
192      \$token_scheme_location = __LINE__
193      \$token_scheme_context = self
194      
195      SCHEME_CONST = 1
196    }
197    
198    @token::members {
199      \$token_members_location = __LINE__
200      \$token_members_context  = self
201      
202      def value
203        text.to_i
204      end
205    }
206    
207    @members {
208      \$members_location = __LINE__
209    }
210    
211    nums returns [ds]: digs+=DIGIT+
212                       { $ds = $digs.map { |t| t.value } };
213    
214    DIGIT: ('0'..'9')+;
215    WS: (' ' | '\t' | '\n' | '\r' | '\f')+ { $channel=HIDDEN; };
216  END
217  
218  example 'verifying action scope behavior' do
219    lexer = SpecialActionScopes::Lexer.new( "10 20 30 40 50" )
220    parser = SpecialActionScopes::Parser.new lexer
221    parser.nums.should == [ 10, 20, 30, 40, 50 ]
222  end
223  
224  example 'special action scope locations' do
225    $all_header_files.should include "SpecialActionScopesLexer.rb"
226    $all_header_files.should include "SpecialActionScopesParser.rb"
227    $all_footer_files.should include "SpecialActionScopesLexer.rb"
228    $all_footer_files.should include "SpecialActionScopesParser.rb"
229    
230    $header_location.should be < $module_head_location
231    $module_head_location.should be < $token_scheme_location
232    $token_scheme_location.should be < $token_members_location
233    $token_members_location.should be < $members_location
234    $members_location.should be < $module_foot_location
235    $module_foot_location.should be < $footer_location
236  end
237
238end
239