1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#!/usr/bin/ruby
2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver# encoding: utf-8
3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverrequire 'antlr3/test/functional'
5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass TestTemplateOutput < ANTLR3::Test::Functional
7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def parse( grammar, input, options = nil )
9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @grammar = inline_grammar( grammar )
10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    compile_and_load( @grammar )
11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    grammar_module = self.class.const_get( @grammar.name )
12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    parser_options = {}
14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if options
15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      rule = options.fetch( :rule ) { grammar_module::Parser.default_rule }
16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      group = options[ :templates ] and parser_options[ :templates ] = group
17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    else
18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      rule = grammar_module::Parser.default_rule
19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @lexer  = grammar_module::Lexer.new( input )
22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @parser = grammar_module::Parser.new( @lexer, parser_options )
23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    out = @parser.send( rule ).template
25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return( out ? out.to_s : out )
26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def parse_templates( source )
29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    ANTLR3::Template::Group.parse( source.fixed_indent( 0 ) )
30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  example 'inline templates' do
34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text = parse( <<-'END', "abc 34" )
35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      grammar InlineTemplates;
36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      options {
37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        language = Ruby;
38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        output = template;
39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      }
40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      a : ID INT
42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        -> template(id={$ID.text}, int={$INT.text})
43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver           "id=<%= @id %>, int=<%= @int %>"
44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ;
45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ID : 'a'..'z'+;
47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      INT : '0'..'9'+;
48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      WS : (' '|'\n') {$channel=HIDDEN;} ;
49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text.should == "id=abc, int=34"
52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  example 'external template' do
55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    templates = ANTLR3::Template::Group.new do
56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      define_template( :expr, <<-'END'.strip )
57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        [<%= @args.join( @op.to_s ) %>]
58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      END
59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text = parse( <<-'END', 'a + b', :templates => templates )
62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      grammar ExternalTemplate;
63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      options {
64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        language = Ruby;
65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        output = template;
66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      }
67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      a : r+=arg OP r+=arg
69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        -> expr( op={$OP.text}, args={$r} )
70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ;
71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      arg: ID -> template(t={$ID.text}) "<%= @t %>";
72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ID : 'a'..'z'+;
74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      OP: '+';
75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      WS : (' '|'\n') {$channel=HIDDEN;} ;
76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text.should == '[a+b]'
79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  example "empty template" do
82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text = parse( <<-'END', 'abc 34' )
83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      grammar EmptyTemplate;
84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      options {
85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        language=Ruby;
86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        output=template;
87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      }
88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      a : ID INT
89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        -> 
90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ;
91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ID : 'a'..'z'+;
93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      INT : '0'..'9'+;
94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      WS : (' '|'\n') {$channel=HIDDEN;} ;
95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text.should be_nil
98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  example "list" do
101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text = parse( <<-'END', "abc def ghi" )
102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      grammar List;
103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      options {
104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        language=Ruby;
105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        output=template;
106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      }
107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      a: (r+=b)* EOF
108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        -> template(r={$r}) "<%= @r.join(',') %>"
109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ;
110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      b: ID
112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        -> template(t={$ID.text}) "<%= @t %>"
113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ;
114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ID : 'a'..'z'+;
116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      WS : (' '|'\n') {$channel=HIDDEN;} ;
117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text.should == 'abc,def,ghi'
119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  example 'action' do
122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text = parse( <<-'END', "abc" )
123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      grammar Action;
124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      options {
125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        language=Ruby;
126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        output=template;
127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      }
128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      a: ID
129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        -> { create_template( "hello" ) }
130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ;
131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ID : 'a'..'z'+;
133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      WS : (' '|'\n') {$channel=HIDDEN;} ;
134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text.should == 'hello'
137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  example "template expression in action" do
140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text = parse( <<-'END', 'abc' )
141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      grammar TemplateExpressionInAction;
142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      options {
143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        language=Ruby;
144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        output=template;
145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      }
146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      a: ID
147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        { $st = %{"hello"} }
148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ;
149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ID : 'a'..'z'+;
151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      WS : (' '|'\n') {$channel=HIDDEN;} ;
152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text.should == 'hello'
154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #example "template expression in action2" do
157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #  text = parse( <<-'END', 'abc' )
158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #    grammar TemplateExpressionInAction2;
159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #    options {
160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #      language=Ruby;
161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #      output=template;
162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #    }
163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #    a: ID
164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #      {
165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #        res = %{"hello <%= @foo %>"}
166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #        %res.foo = "world";
167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #      }
168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #      -> { res }
169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #    ;
170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #    
171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #    ID : 'a'..'z'+;
172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #    WS : (' '|'\n') {$channel=HIDDEN;} ;
173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #  END
174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #  
175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #  text.should == 'hello world'
176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  #end
177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  example "indirect template constructor" do
179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    templates = ANTLR3::Template::Group.new do
180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      define_template( :expr, <<-'END'.strip )
181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        [<%= @args.join( @op.to_s ) %>]
182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      END
183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text = parse( <<-'END', 'abc', :templates => templates )
186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      grammar IndirectTemplateConstructor;
187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      options {
188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        language=Ruby;
189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        output=template;
190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      }
191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      a: ID
193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        {
194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          $st = %({"expr"})(args={[1, 2, 3]}, op={"+"})
195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ;
197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ID : 'a'..'z'+;
199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      WS : (' '|'\n') {$channel=HIDDEN;} ;
200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text.should == '[1+2+3]'
203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  example "predicates" do
206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text = parse( <<-'END', 'b 34' )
207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      grammar Predicates;
208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      options {
209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        language=Ruby;
210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        output=template;
211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      }
212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      a : ID INT
213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        -> {$ID.text=='a'}? template(int={$INT.text})
214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                            "A: <%= @int %>"
215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        -> {$ID.text=='b'}? template(int={$INT.text})
216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                            "B: <%= @int %>"
217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        ->                  template(int={$INT.text})
218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                            "C: <%= @int %>"
219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ;
220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ID : 'a'..'z'+;
222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      INT : '0'..'9'+;
223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      WS : (' '|'\n') {$channel=HIDDEN;} ;
224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text.should == 'B: 34'
227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  example "backtracking mode" do
230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text = parse( <<-'END', 'abc 34' )
231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      grammar BacktrackingMode;
232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      options {
233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        language=Ruby;
234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        output=template;
235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        backtrack=true;
236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      }
237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      a : (ID INT)=> ID INT
238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        -> template(id={$ID.text}, int={$INT.text})
239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver           "id=<%= @id %>, int=<%= @int %>"
240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ;
241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ID : 'a'..'z'+;
243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      INT : '0'..'9'+;
244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      WS : (' '|'\n') {$channel=HIDDEN;} ;
245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    text.should == "id=abc, int=34"
248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  example "rewrite" do
251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    input = <<-'END'.here_indent!
252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | if ( foo ) {
253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    |   b = /* bla */ 2;
254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    |   return 1 /* foo */;
255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | }
256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | 
257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | /* gnurz */
258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | return 12;
259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    expected = <<-'END'.here_indent!
261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | if ( foo ) {
262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    |   b = /* bla */ 2;
263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    |   return boom(1) /* foo */;
264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | }
265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | 
266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | /* gnurz */
267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | return boom(12);
268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    parse( <<-'END', input )
271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      grammar Rewrite;
272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      options {
273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        language=Ruby;
274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        output=template;
275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        rewrite=true;
276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      }
277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      prog: stat+;
279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      stat
281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          : 'if' '(' expr ')' stat
282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          | 'return' return_expr ';'
283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          | '{' stat* '}'
284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          | ID '=' expr ';'
285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          ;
286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      return_expr
288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          : expr
289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            -> template(t={$text}) <<boom(<%= @t %>)>>
290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          ;
291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          
292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      expr
293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          : ID
294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          | INT
295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          ;
296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          
297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ID:  'a'..'z'+;
298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      INT: '0'..'9'+;
299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      WS: (' '|'\n')+ {$channel=HIDDEN;} ;
300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      COMMENT: '/*' (options {greedy=false;} : .)* '*/' {$channel = HIDDEN;} ;
301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @parser.input.render.should == expected
304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  example "tree rewrite" do
307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    input = <<-'END'.here_indent!
308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | if ( foo ) {
309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    |   b = /* bla */ 2;
310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    |   return 1 /* foo */;
311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | }
312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | 
313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | /* gnurz */
314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | return 12;
315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    expected = <<-'END'.here_indent!
317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | if ( foo ) {
318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    |   b = /* bla */ 2;
319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    |   return boom(1) /* foo */;
320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | }
321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | 
322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | /* gnurz */
323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    | return boom(12);
324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    compile_and_load( inline_grammar( <<-'END' ) )
327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      grammar TreeRewrite;
328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      options {
329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        language=Ruby;
330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        output=AST;
331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      }
332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      tokens {
334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        BLOCK;
335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        ASSIGN;
336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      }
337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      prog: stat+;
339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      stat
341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          : IF '(' e=expr ')' s=stat
342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            -> ^(IF $e $s)
343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          | RETURN expr ';'
344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            -> ^(RETURN expr)
345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          | '{' stat* '}'
346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            -> ^(BLOCK stat*)
347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          | ID '=' expr ';'
348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            -> ^(ASSIGN ID expr)
349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          ;
350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          
351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      expr
352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          : ID
353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          | INT
354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          ;
355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
356324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      IF: 'if';
357324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      RETURN: 'return';
358324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ID:  'a'..'z'+;
359324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      INT: '0'..'9'+;
360324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      WS: (' '|'\n')+ {$channel=HIDDEN;} ;
361324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      COMMENT: '/*' (options {greedy=false;} : .)* '*/' {$channel = HIDDEN;} ;
362324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
363324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
364324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    compile_and_load( inline_grammar( <<-'END' ) )
365324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      tree grammar TreeRewriteTG;
366324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      options {
367324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        language=Ruby;
368324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        tokenVocab=TreeRewrite;
369324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        ASTLabelType=CommonTree;
370324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        output=template;
371324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        rewrite=true;
372324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      }
373324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
374324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      prog: stat+;
375324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
376324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      stat
377324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          : ^(IF expr stat)
378324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          | ^(RETURN return_expr)                
379324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          | ^(BLOCK stat*)                
380324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          | ^(ASSIGN ID expr)
381324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          ;
382324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
383324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      return_expr
384324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          : expr
385324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            -> template(t={$text}) <<boom(<%= @t %>)>>
386324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          ;
387324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
388324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      expr
389324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          : ID
390324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          | INT
391324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          ;
392324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    END
393324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
394324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    lexer = TreeRewrite::Lexer.new( input )
395324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    tokens = ANTLR3::TokenRewriteStream.new( lexer )
396324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    parser = TreeRewrite::Parser.new( tokens )
397324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    tree = parser.prog.tree
398324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    nodes = ANTLR3::AST::CommonTreeNodeStream.new( tree )
399324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    nodes.token_stream = tokens
400324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    tree_parser = TreeRewriteTG::TreeParser.new( nodes )
401324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    tree_parser.prog
402324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    tokens.render.should == expected
403324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
404324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
405