• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/ruby
2# encoding: utf-8
3
4=begin LICENSE
5
6[The "BSD licence"]
7Copyright (c) 2009-2010 Kyle Yetter
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions
12are met:
13
14 1. Redistributions of source code must retain the above copyright
15    notice, this list of conditions and the following disclaimer.
16 2. Redistributions in binary form must reproduce the above copyright
17    notice, this list of conditions and the following disclaimer in the
18    documentation and/or other materials provided with the distribution.
19 3. The name of the author may not be used to endorse or promote products
20    derived from this software without specific prior written permission.
21
22THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33=end
34
35require 'antlr3'
36
37module ANTLR3
38
39=begin rdoc ANTLR3::AST
40
41Name space containing all of the entities pertaining to tree construction and
42tree parsing.
43
44=end
45
46module AST
47
48autoload :Wizard, 'antlr3/tree/wizard'
49autoload :Visitor, 'antlr3/tree/visitor'
50
51####################################################################################################
52############################################ Tree Parser ###########################################
53####################################################################################################
54
55=begin rdoc ANTLR3::AST::TreeParser
56
57= TreeParser
58
59TreeParser is the default base class of ANTLR-generated tree parsers. The class
60tailors the functionality provided by Recognizer to the task of tree-pattern
61recognition.
62
63== About Tree Parsers
64
65ANTLR generates three basic types of recognizers:
66* lexers
67* parsers
68* tree parsers
69
70Furthermore, it is capable of generating several different flavors of parser,
71including parsers that take token input and use it to build Abstract Syntax
72Trees (ASTs), tree structures that reflect the high-level syntactic and semantic
73structures defined by the language.
74
75You can take the information encapsulated by the AST and process it directly in
76a program. However, ANTLR also provides a means to create a recognizer which is
77capable of walking through the AST, verifying its structure and performing
78custom actions along the way -- tree parsers.
79
80Tree parsers are created from tree grammars. ANTLR-generated tree parsers
81closely mirror the general structure of regular parsers and lexers.
82
83For more in-depth coverage of the topic, check out the ANTLR documentation
84(http://www.antlr.org).
85
86== The Tree Parser API
87
88Like Parser, the class does not stray too far from the Recognizer API.
89Mainly, it customizes a few methods specifically to deal with tree nodes
90(instead of basic tokens), and adds some helper methods for working with trees.
91
92Like all ANTLR recognizers, tree parsers contained a shared state structure and
93an input stream, which should be a TreeNodeStream. ANTLR intends to keep its
94tree features flexible and customizable, and thus it does not make any
95assumptions about the class of the actual nodes it processes. One consequence of
96this flexibility is that tree parsers also require an extra tree adaptor object,
97the purpose of which is to provide a homogeneous interface for handling tree
98construction and analysis of your tree nodes.
99
100See Tree and TreeAdaptor for more information.
101
102=end
103
104class TreeParser < Recognizer
105  def self.main( argv = ARGV, options = {} )
106    if ::Hash === argv then argv, options = ARGV, argv end
107    main = ANTLR3::Main::WalkerMain.new( self, options )
108    block_given? ? yield( main ) : main.execute( argv )
109  end
110
111  def initialize( input, options = {} )
112    super( options )
113    @input = input
114  end
115
116  alias tree_node_stream input
117  alias tree_node_stream= input=
118
119  def source_name
120    @input.source_name
121  end
122
123  def missing_symbol( error, expected_token_type, follow )
124    name = token_name( expected_token_type ).to_s
125    text = "<missing " << name << '>'
126    tk = create_token do |t|
127      t.text = text
128      t.type = expected_token_type
129    end
130    return( CommonTree.new( tk ) )
131  end
132
133  def match_any( ignore = nil )
134    @state.error_recovery = false
135
136    look, adaptor = @input.look, @input.tree_adaptor
137    if adaptor.child_count( look ) == 0
138      @input.consume
139      return
140    end
141
142    level = 0
143    while type = @input.peek and type != EOF
144      #token_type == EOF or ( token_type == UP && level == 0 )
145      @input.consume
146      case type
147      when DOWN then level += 1
148      when UP
149        level -= 1
150        level.zero? and break
151      end
152    end
153  end
154
155  def mismatch( input, type, follow = nil )
156    raise MismatchedTreeNode.new( type, input )
157  end
158
159  def error_header( e )
160    <<-END.strip!
161    #{ grammar_file_name }: node from #{
162      e.approximate_line_info? ? 'after ' : ''
163    } line #{ e.line }:#{ e.column }
164    END
165  end
166
167  def error_message( e )
168    adaptor = e.input.adaptor
169    e.token = adaptor.token( e.node )
170    e.token ||= create_token do | tok |
171      tok.type = adaptor.type_of( e.node )
172      tok.text = adaptor.text_of( e.node )
173    end
174    return super( e )
175  end
176
177  def trace_in( rule_name, rule_index )
178    super( rule_name, rule_index, @input.look )
179  end
180
181  def trace_out( rule_name, rule_index )
182    super( rule_name, rule_index, @input.look )
183  end
184end
185
186####################################################################################################
187############################################ Tree Nodes ############################################
188####################################################################################################
189
190=begin rdoc ANTLR3::AST::Tree
191
192= ANTLR Abstract Syntax Trees
193
194As ANTLR is concerned, an Abstract Syntax Tree (AST) node is an object that
195wraps a token, a list of child trees, and some information about the collective
196source text embodied within the tree and its children.
197
198The Tree module, like the Token and Stream modules, emulates an abstract base
199class for AST classes; it specifies the attributes that are expected of basic
200tree nodes as well as the methods trees need to implement.
201
202== Terminology
203
204While much of this terminology is probably familiar to most developers, the
205following brief glossary is intended to clarify terminology used in code
206throughout the AST library:
207
208[payload] either a token value contained within a node or +nil+
209[flat list (nil tree)] a tree node without a token payload, but with more
210                       than one children -- functions like an array of
211                       tree nodes
212[root] a top-level tree node, i.e. a node that does not have a parent
213[leaf] a node that does not have any children
214[siblings] all other nodes sharing the same parent as some node
215[ancestors] the list of successive parents from a tree node to the root node
216[error node] a special node used to represent an erroneous series of tokens
217             from an input stream
218
219=end
220
221module Tree
222
223  #attr_accessor :parent
224  attr_accessor :start_index
225  attr_accessor :stop_index
226  attr_accessor :child_index
227  attr_reader :type
228  attr_reader :text
229  attr_reader :line
230  attr_reader :column
231  #attr_reader :children
232  attr_reader :token
233
234
235  def root?
236    parent.nil?
237  end
238  alias detached? root?
239
240  def root
241    cursor = self
242    until cursor.root?
243      yield( parent_node = cursor.parent )
244      cursor = parent_node
245    end
246    return( cursor )
247  end
248
249  #
250  def leaf?
251    children.nil? or children.empty?
252  end
253
254  def has_child?( node )
255    children and children.include?( node )
256  end
257
258  def depth
259    root? ? 0 : parent.depth + 1
260  end
261
262  def siblings
263    root? and return []
264    parent.children.reject { | c | c.equal?( self ) }
265  end
266
267  def each_ancestor
268    block_given? or return( enum_for( :each_ancestor ) )
269    cursor = self
270    until cursor.root?
271      yield( parent_node = cursor.parent )
272      cursor = parent_node
273    end
274    return( self )
275  end
276
277  def ancestors
278    each_ancestor.to_a
279  end
280
281  def walk
282    block_given? or return( enum_for( :walk ) )
283    stack = []
284    cursor = self
285    while true
286      begin
287        yield( cursor )
288        stack.push( cursor.children.dup ) unless cursor.empty?
289      rescue StopIteration
290        # skips adding children to prune the node
291      ensure
292        break if stack.empty?
293        cursor = stack.last.shift
294        stack.pop if stack.last.empty?
295      end
296    end
297    return self
298  end
299
300end
301
302
303=begin rdoc ANTLR3::AST::BaseTree
304
305A base implementation of an Abstract Syntax Tree Node. It mainly defines the
306methods and attributes required to implement the parent-node-children
307relationship that characterize a tree; it does not provide any logic concerning
308a node's token <i>payload</i>.
309
310=end
311
312class BaseTree < ::Array
313  attr_accessor :parent
314  extend ClassMacros
315  include Tree
316
317  def initialize( node = nil )
318    super()
319    @parent = nil
320    @child_index = 0
321  end
322
323  def children() self end
324
325  alias child at
326  alias child_count length
327
328  def first_with_type( tree_type )
329    find { | child | child.type == tree_type }
330  end
331
332  def add_child( child_tree )
333    child_tree.nil? and return
334    if child_tree.flat_list?
335      self.equal?( child_tree.children ) and
336        raise ArgumentError, "attempt to add child list to itself"
337      child_tree.each_with_index do | child, index |
338        child.parent = self
339        child.child_index = length + index
340      end
341      concat( child_tree )
342    else
343      child_tree.child_index = length
344      child_tree.parent = self
345      self << child_tree
346    end
347    return( self )
348  end
349
350  def detach
351    @parent = nil
352    @child_index = -1
353    return( self )
354  end
355
356  alias add_children concat
357  alias each_child each
358
359  def set_child( index, tree )
360    return if tree.nil?
361    tree.flat_list? and raise ArgumentError, "Can't set single child to a list"
362    tree.parent = self
363    tree.child_index = index
364    self[ index ] = tree
365  end
366
367  def delete_child( index )
368    killed = delete_at( index ) and freshen( index )
369    return killed
370  end
371
372  def replace_children( start, stop, new_tree )
373    start >= length or stop >= length and
374      raise IndexError, ( <<-END ).gsub!( /^\s+\| /,'' )
375      | indices span beyond the number of children:
376      |  children.length = #{ length }
377      |  start = #{ start_index.inspect }
378      |  stop  = #{ stop_index.inspect }
379      END
380    new_children = new_tree.flat_list? ? new_tree : [ new_tree ]
381    self[ start .. stop ] = new_children
382    freshen( start_index )
383    return self
384  end
385
386  def flat_list?
387    false
388  end
389
390  def freshen( offset = 0 )
391    for i in offset ... length
392      node = self[ i ]
393      node.child_index = i
394      node.parent = self
395    end
396  end
397
398  def sanity_check( parent = nil, i = -1 )
399    parent == @parent or
400      raise TreeInconsistency.failed_parent_check!( parent, @parent )
401    i == @child_index or
402      raise TreeInconsistency.failed_index_check!( i, @child_index )
403    each_with_index do | child, index |
404      child.sanity_check( self, index )
405    end
406  end
407
408  def inspect
409    empty? and return to_s
410    buffer = ''
411    buffer << '(' << to_s << ' ' unless flat_list?
412    buffer << map { | c | c.inspect }.join( ' ' )
413    buffer << ')' unless flat_list?
414    return( buffer )
415  end
416
417  def walk
418    block_given? or return( enum_for( :walk ) )
419    stack = []
420    cursor = self
421    while true
422      begin
423        yield( cursor )
424        stack.push( Array[ *cursor ] ) unless cursor.empty?
425      rescue StopIteration
426        # skips adding children to prune the node
427      ensure
428        break if stack.empty?
429        cursor = stack.last.shift
430        stack.pop if stack.last.empty?
431      end
432    end
433    return self
434  end
435
436  def prune
437    raise StopIteration
438  end
439
440  abstract :to_s
441  #protected :sanity_check, :freshen
442
443  def root?() @parent.nil? end
444  alias leaf? empty?
445end
446
447
448=begin rdoc ANTLR3::AST::CommonTree
449
450The default Tree class implementation used by ANTLR tree-related code.
451
452A CommonTree object is a tree node that wraps a token <i>payload</i> (or a +nil+
453value) and contains zero or more child tree nodes. Additionally, it tracks
454information about the range of data collectively spanned by the tree node:
455
456* the token stream start and stop indexes of tokens contained throughout
457  the tree
458* that start and stop positions of the character input stream from which
459  the tokens were defined
460
461Tracking this information simplifies tasks like extracting a block of code or
462rewriting the input stream. However, depending on the purpose of the
463application, building trees with all of this extra information may be
464unnecessary. In such a case, a more bare-bones tree class could be written
465(optionally using the BaseTree class or the Token module). Define a customized
466TreeAdaptor class to handle tree construction and manipulation for the
467customized node class, and recognizers will be able to build, rewrite, and parse
468the customized lighter-weight trees.
469
470=end
471
472class CommonTree < BaseTree
473  def initialize( payload = nil )
474    super()
475    @start_index = -1
476    @stop_index = -1
477    @child_index = -1
478    case payload
479    when CommonTree then   # copy-constructor style init
480      @token       = payload.token
481      @start_index = payload.start_index
482      @stop_index  = payload.stop_index
483    when nil, Token then @token = payload
484    else raise ArgumentError,
485      "Invalid argument type: %s (%p)" % [ payload.class, payload ]
486    end
487  end
488
489  def initialize_copy( orig )
490    super
491    clear
492    @parent = nil
493  end
494
495  def copy_node
496    return self.class.new( @token )
497  end
498
499  def flat_list?
500    @token.nil?
501  end
502
503  def type
504    @token ? @token.type : 0
505  end
506
507  def text
508    @token.text rescue nil
509  end
510
511  def line
512    if @token.nil? or @token.line == 0
513      return ( empty? ? 0 : first.line )
514    end
515    return @token.line
516  end
517
518  def column
519    if @token.nil? or @token.column == -1
520      return( empty? ? 0 : first.column )
521    end
522    return @token.column
523  end
524
525  def start_index
526    @start_index == -1 and @token and return @token.index
527    return @start_index
528  end
529
530  def stop_index
531    @stop_index == -1 and @token and return @token.index
532    return @stop_index
533  end
534
535  alias token_start_index= start_index=
536  alias token_stop_index= stop_index=
537  alias token_start_index start_index
538  alias token_stop_index stop_index
539
540  def name
541    @token.name rescue 'INVALID'
542  end
543
544  def token_range
545    unknown_boundaries? and infer_boundaries
546    @start_index .. @stop_index
547  end
548
549  def source_range
550    unknown_boundaries? and infer_boundaries
551    tokens = map do | node |
552      tk = node.token and tk.index >= 0 ? tk : nil
553    end
554    tokens.compact!
555    first, last = tokens.minmax_by { |t| t.index }
556    first.start .. last.stop
557  end
558
559  def infer_boundaries
560    if empty? and @start_index < 0 || @stop_index < 0
561      @start_index = @stop_index = @token.index rescue -1
562      return
563    end
564    for child in self do child.infer_boundaries end
565    return if @start_index >= 0 and @stop_index >= 0
566
567    @start_index = first.start_index
568    @stop_index  = last.stop_index
569    return nil
570  end
571
572  def unknown_boundaries?
573    @start_index < 0 or @stop_index < 0
574  end
575
576  def to_s
577    flat_list? ? 'nil' : @token.text.to_s
578  end
579
580  def pretty_print( printer )
581    text = @token ? @token.text : 'nil'
582    text =~ /\s+/ and
583      text = text.dump
584
585    if empty?
586      printer.text( text )
587    else
588      endpoints = @token ? [ "(#{ text }", ')' ] : [ '', '' ]
589      printer.group( 1, *endpoints ) do
590        for child in self
591          printer.breakable
592          printer.pp( child )
593        end
594      end
595    end
596  end
597
598end
599
600=begin rdoc ANTLR3::AST::CommonErrorNode
601
602Represents a series of erroneous tokens from a token stream input
603
604=end
605
606class CommonErrorNode < CommonTree
607  include ANTLR3::Error
608  include ANTLR3::Constants
609
610  attr_accessor :input, :start, :stop, :error
611
612  def initialize( input, start, stop, error )
613    super( nil )
614    stop = start if stop.nil? or
615      ( stop.token_index < start.token_index and stop.type != EOF )
616    @input = input
617    @start = start
618    @stop = stop
619    @error = error
620  end
621
622  def flat_list?
623    return false
624  end
625
626  def type
627    INVALID_TOKEN_TYPE
628  end
629
630  def text
631    case @start
632    when Token
633      i = @start.token_index
634      j = ( @stop.type == EOF ) ? @input.size : @stop.token_index
635      @input.to_s( i, j )            # <- the bad text
636    when Tree
637      @input.to_s( @start, @stop )   # <- the bad text
638    else
639      "<unknown>"
640    end
641  end
642
643  def to_s
644    case @error
645    when MissingToken
646      "<missing type: #{ @error.missing_type }>"
647    when UnwantedToken
648      "<extraneous: #{ @error.token.inspect }, resync = #{ text }>"
649    when MismatchedToken
650      "<mismatched token: #{ @error.token.inspect }, resync = #{ text }>"
651    when NoViableAlternative
652      "<unexpected: #{ @error.token.inspect }, resync = #{ text }>"
653    else "<error: #{ text }>"
654    end
655  end
656
657end
658
659Constants::INVALID_NODE = CommonTree.new( ANTLR3::INVALID_TOKEN )
660
661####################################################################################################
662########################################### Tree Adaptors ##########################################
663####################################################################################################
664
665=begin rdoc ANTLR3::AST::TreeAdaptor
666
667Since a tree can be represented by a multitude of formats, ANTLR's tree-related
668code mandates the use of Tree Adaptor objects to build and manipulate any actual
669trees. Using an adaptor object permits a single recognizer to work with any
670number of different tree structures without adding rigid interface requirements
671on customized tree structures. For example, if you want to represent trees using
672simple arrays of arrays, you just need to design an appropriate tree adaptor and
673provide it to the parser.
674
675Tree adaptors are tasked with:
676
677* copying and creating tree nodes and tokens
678* defining parent-child relationships between nodes
679* cleaning up / normalizing a full tree structure after construction
680* reading and writing the attributes ANTLR expects of tree nodes
681* providing node access and iteration
682
683=end
684
685module TreeAdaptor
686  include TokenFactory
687  include Constants
688  include Error
689
690  def add_child( tree, child )
691    tree.add_child( child ) if tree and child
692  end
693
694  def child_count( tree )
695    tree.child_count
696  end
697
698  def child_index( tree )
699    tree.child_index rescue 0
700  end
701
702  def child_of( tree, index )
703    tree.nil? ? nil : tree.child( index )
704  end
705
706  def copy_node( tree_node )
707    tree_node and tree_node.dup
708  end
709
710  def copy_tree( tree, parent = nil )
711    tree or return nil
712    new_tree = copy_node( tree )
713    set_child_index( new_tree, child_index( tree ) )
714    set_parent( new_tree, parent )
715    each_child( tree ) do | child |
716      new_sub_tree = copy_tree( child, new_tree )
717      add_child( new_tree, new_sub_tree )
718    end
719    return new_tree
720  end
721
722  def delete_child( tree, index )
723    tree.delete_child( index )
724  end
725
726
727  def each_child( tree )
728    block_given? or return enum_for( :each_child, tree )
729    for i in 0 ... child_count( tree )
730      yield( child_of( tree, i ) )
731    end
732    return tree
733  end
734
735  def each_ancestor( tree, include_tree = true )
736    block_given? or return enum_for( :each_ancestor, tree, include_tree )
737    if include_tree
738      begin yield( tree ) end while tree = parent_of( tree )
739    else
740      while tree = parent_of( tree ) do yield( tree ) end
741    end
742  end
743
744  def flat_list?( tree )
745    tree.flat_list?
746  end
747
748  def empty?( tree )
749    child_count( tree ).zero?
750  end
751
752  def parent( tree )
753    tree.parent
754  end
755
756  def replace_children( parent, start, stop, replacement )
757    parent and parent.replace_children( start, stop, replacement )
758  end
759
760  def rule_post_processing( root )
761    if root and root.flat_list?
762      case root.child_count
763      when 0 then root = nil
764      when 1
765        root = root.child( 0 ).detach
766      end
767    end
768    return root
769  end
770
771  def set_child_index( tree, index )
772    tree.child_index = index
773  end
774
775  def set_parent( tree, parent )
776    tree.parent = parent
777  end
778
779  def set_token_boundaries( tree, start_token = nil, stop_token = nil )
780    return unless tree
781    start = stop = 0
782    start_token and start = start_token.index
783    stop_token  and stop  = stop_token.index
784    tree.start_index = start
785    tree.stop_index = stop
786    return tree
787  end
788
789  def text_of( tree )
790    tree.text rescue nil
791  end
792
793  def token( tree )
794    CommonTree === tree ? tree.token : nil
795  end
796
797  def token_start_index( tree )
798    tree ? tree.token_start_index : -1
799  end
800
801  def token_stop_index( tree )
802    tree ? tree.token_stop_index : -1
803  end
804
805  def type_name( tree )
806    tree.name rescue 'INVALID'
807  end
808
809  def type_of( tree )
810    tree.type rescue INVALID_TOKEN_TYPE
811  end
812
813  def unique_id( node )
814    node.hash
815  end
816
817end
818
819=begin rdoc ANTLR3::AST::CommonTreeAdaptor
820
821The default tree adaptor used by ANTLR-generated tree code. It, of course,
822builds and manipulates CommonTree nodes.
823
824=end
825
826class CommonTreeAdaptor
827  extend ClassMacros
828  include TreeAdaptor
829  include ANTLR3::Constants
830
831  def initialize( token_class = ANTLR3::CommonToken )
832    @token_class = token_class
833  end
834
835  def create_flat_list
836    return create_with_payload( nil )
837  end
838  alias create_flat_list! create_flat_list
839
840  def become_root( new_root, old_root )
841    new_root = create( new_root ) if new_root.is_a?( Token )
842    old_root or return( new_root )
843
844    new_root = create_with_payload( new_root ) unless CommonTree === new_root
845    if new_root.flat_list?
846      count = new_root.child_count
847      if count == 1
848        new_root = new_root.child( 0 )
849      elsif count > 1
850        raise TreeInconsistency.multiple_roots!
851      end
852    end
853
854    new_root.add_child( old_root )
855    return new_root
856  end
857
858  def create_from_token( token_type, from_token, text = nil )
859    from_token = from_token.dup
860    from_token.type = token_type
861    from_token.text = text.to_s if text
862    tree = create_with_payload( from_token )
863    return tree
864  end
865
866  def create_from_type( token_type, text )
867    from_token = create_token( token_type, DEFAULT_CHANNEL, text )
868    create_with_payload( from_token )
869  end
870
871  def create_error_node( input, start, stop, exc )
872    CommonErrorNode.new( input, start, stop, exc )
873  end
874
875  def create_with_payload( payload )
876    return CommonTree.new( payload )
877  end
878
879  def create( *args )
880    n = args.length
881    if n == 1 and args.first.is_a?( Token ) then create_with_payload( args[ 0 ] )
882    elsif n == 2 and Integer === args.first and String === args[ 1 ]
883      create_from_type( *args )
884    elsif n >= 2 and Integer === args.first
885      create_from_token( *args )
886    else
887      sig = args.map { |f| f.class }.join( ', ' )
888      raise TypeError, "No create method with this signature found: (#{ sig })"
889    end
890  end
891
892  creation_methods = %w(
893    create_from_token create_from_type
894    create_error_node create_with_payload
895    create
896  )
897
898  for method_name in creation_methods
899    bang_method = method_name + '!'
900    alias_method( bang_method, method_name )
901    deprecate( bang_method, "use method ##{ method_name } instead" )
902  end
903
904  def rule_post_processing( root )
905    if root and root.flat_list?
906      if root.empty? then root = nil
907      elsif root.child_count == 1 then root = root.first.detach
908      end
909    end
910    return root
911  end
912
913  def empty?( tree )
914    tree.empty?
915  end
916
917  def each_child( tree )
918    block_given? or return enum_for( :each_child, tree )
919    tree.each do | child |
920      yield( child )
921    end
922  end
923
924end
925
926
927####################################################################################################
928########################################### Tree Streams ###########################################
929####################################################################################################
930
931=begin rdoc ANTLR3::AST::TreeNodeStream
932
933TreeNodeStreams flatten two-dimensional tree structures into one-dimensional
934sequences. They preserve the two-dimensional structure of the tree by inserting
935special +UP+ and +DOWN+ nodes.
936
937Consider a hypothetical tree:
938
939  [A]
940   +--[B]
941   |   +--[C]
942   |   `--[D]
943   `--[E]
944       `--[F]
945
946A tree node stream would serialize the tree into the following sequence:
947
948  A DOWN B DOWN C D UP E DOWN F UP UP EOF
949
950Other than serializing a tree into a sequence of nodes, a tree node stream
951operates similarly to other streams. They are commonly used by tree parsers as
952the main form of input. #peek, like token streams, returns the type of the token
953of the next node. #look returns the next full tree node.
954
955=end
956
957module TreeNodeStream
958  extend ClassMacros
959  include Stream
960  include Constants
961
962  abstract :at
963  abstract :look
964  abstract :tree_source
965  abstract :token_stream
966  abstract :tree_adaptor
967  abstract :unique_navigation_nodes=
968  abstract :to_s
969  abstract :replace_children
970end
971
972=begin rdoc ANTLR3::AST::CommonTreeNodeStream
973
974An implementation of TreeNodeStream tailed for streams based on CommonTree
975objects. CommonTreeNodeStreams are the default input streams for tree parsers.
976
977=end
978
979class CommonTreeNodeStream
980  include TreeNodeStream
981
982  attr_accessor :token_stream
983  attr_reader :adaptor, :position
984
985  def initialize( *args )
986    options = args.last.is_a?( ::Hash ) ? args.pop : {}
987    case n = args.length
988    when 1
989      @root = args.first
990      @token_stream = @adaptor = @nodes = @down = @up = @eof = nil
991    when 2
992      @adaptor, @root = args
993      @token_stream = @nodes = @down = @up = @eof = nil
994    when 3
995      parent, start, stop = *args
996      @adaptor = parent.adaptor
997      @root = parent.root
998      @nodes = parent.nodes[ start ... stop ]
999      @down = parent.down
1000      @up = parent.up
1001      @eof = parent.eof
1002      @token_stream = parent.token_stream
1003    when 0
1004      raise ArgumentError, "wrong number of arguments (0 for 1)"
1005    else raise ArgumentError, "wrong number of arguments (#{ n } for 3)"
1006    end
1007    @adaptor ||= options.fetch( :adaptor ) { CommonTreeAdaptor.new }
1008    @token_stream ||= options[ :token_stream ]
1009    @down  ||= options.fetch( :down ) { @adaptor.create_from_type( DOWN, 'DOWN' ) }
1010    @up    ||= options.fetch( :up )   { @adaptor.create_from_type( UP, 'UP' ) }
1011    @eof   ||= options.fetch( :eof )  { @adaptor.create_from_type( EOF, 'EOF' ) }
1012    @nodes ||= []
1013
1014    @unique_navigation_nodes = options.fetch( :unique_navigation_nodes, false )
1015    @position = -1
1016    @last_marker = nil
1017    @calls = []
1018  end
1019
1020  def fill_buffer( tree = @root )
1021    @nodes << tree unless nil_tree = @adaptor.flat_list?( tree )
1022    unless @adaptor.empty?( tree )
1023      add_navigation_node( DOWN ) unless nil_tree
1024      @adaptor.each_child( tree ) { | c | fill_buffer( c ) }
1025      add_navigation_node( UP ) unless nil_tree
1026    end
1027    @position = 0 if tree == @root
1028    return( self )
1029  end
1030
1031  def node_index( node )
1032    @position == -1 and fill_buffer
1033    return @nodes.index( node )
1034  end
1035
1036  def add_navigation_node( type )
1037    navigation_node =
1038      case type
1039      when DOWN
1040        has_unique_navigation_nodes? ? @adaptor.create_from_type( DOWN, 'DOWN' ) : @down
1041      else
1042        has_unique_navigation_nodes? ? @adaptor.create_from_type( UP, 'UP' ) : @up
1043      end
1044    @nodes << navigation_node
1045  end
1046
1047  def at( index )
1048    @position == -1 and fill_buffer
1049    @nodes.at( index )
1050  end
1051
1052  def look( k = 1 )
1053    @position == -1 and fill_buffer
1054    k == 0 and return nil
1055    k < 0 and return self.look_behind( -k )
1056
1057    absolute = @position + k - 1
1058    @nodes.fetch( absolute, @eof )
1059  end
1060
1061  def current_symbol
1062    look
1063  end
1064
1065  def look_behind( k = 1 )
1066    k == 0 and return nil
1067    absolute = @position - k
1068    return( absolute < 0 ? nil : @nodes.fetch( absolute, @eof ) )
1069  end
1070
1071  def tree_source
1072    @root
1073  end
1074
1075  def source_name
1076    self.token_stream.source_name
1077  end
1078
1079  def tree_adaptor
1080    @adaptor
1081  end
1082
1083  def has_unique_navigation_nodes?
1084    return @unique_navigation_nodes
1085  end
1086  attr_writer :unique_navigation_nodes
1087
1088  def consume
1089    @position == -1 and fill_buffer
1090    node = @nodes.fetch( @position, @eof )
1091    @position += 1
1092    return( node )
1093  end
1094
1095  def peek( i = 1 )
1096    @adaptor.type_of look( i )
1097  end
1098
1099  alias >> peek
1100  def <<( k )
1101    self >> -k
1102  end
1103
1104  def mark
1105    @position == -1 and fill_buffer
1106    @last_marker = @position
1107    return @last_marker
1108  end
1109
1110  def release( marker = nil )
1111    # do nothing?
1112  end
1113
1114  alias index position
1115
1116  def rewind( marker = @last_marker, release = true )
1117    seek( marker )
1118  end
1119
1120  def seek( index )
1121    @position == -1 and fill_buffer
1122    @position = index
1123  end
1124
1125  def push( index )
1126    @calls << @position
1127    seek( index )
1128  end
1129
1130  def pop
1131    pos = @calls.pop and seek( pos )
1132    return pos
1133  end
1134
1135  def reset
1136    @position = 0
1137    @last_marker = 0
1138    @calls = []
1139  end
1140
1141  def replace_children( parent, start, stop, replacement )
1142    parent and @adaptor.replace_children( parent, start, stop, replacement )
1143  end
1144
1145  def size
1146    @position == -1 and fill_buffer
1147    return @nodes.length
1148  end
1149
1150  def inspect
1151    @position == -1 and fill_buffer
1152    @nodes.map { |nd| @adaptor.type_name( nd ) }.join( ' ' )
1153  end
1154
1155  def extract_text( start = nil, stop = nil )
1156    start.nil? || stop.nil? and return nil
1157    @position == -1 and fill_buffer
1158
1159    if @token_stream
1160      from = @adaptor.token_start_index( start )
1161      to =
1162        case @adaptor.type_of( stop )
1163        when UP then @adaptor.token_stop_index( start )
1164        when EOF then to = @nodes.length - 2
1165        else @adaptor.token_stop_index( stop )
1166        end
1167      return @token_stream.extract_text( from, to )
1168    end
1169
1170    buffer = ''
1171    for node in @nodes
1172      if node == start ... node == stop  # <-- hey look, it's the flip flop operator
1173        buffer << @adaptor.text_of( node ) #|| ' ' << @adaptor.type_of( node ).to_s )
1174      end
1175    end
1176    return( buffer )
1177  end
1178
1179  def each
1180    @position == -1 and fill_buffer
1181    block_given? or return enum_for( :each )
1182    for node in @nodes do yield( node ) end
1183    self
1184  end
1185
1186  include Enumerable
1187
1188  def to_a
1189    return @nodes.dup
1190  end
1191
1192  def extract_text( start = nil, stop = nil )
1193    @position == -1 and fill_buffer
1194    start ||= @nodes.first
1195    stop  ||= @nodes.last
1196
1197    if @token_stream
1198      case @adaptor.type_of( stop )
1199      when UP
1200        stop_index = @adaptor.token_stop_index( start )
1201      when EOF
1202        return extract_text( start, @nodes[ - 2 ] )
1203      else
1204        stop_index = @adaptor.token_stop_index( stop )
1205      end
1206
1207      start_index = @adaptor.token_start_index( start )
1208      return @token_stream.extract_text( start_index, stop_index )
1209    else
1210      start_index = @nodes.index( start ) || @nodes.length
1211      stop_index  = @nodes.index( stop )  || @nodes.length
1212      return(
1213        @nodes[ start_index .. stop_index ].map do | n |
1214          @adaptor.text_of( n ) or " " + @adaptor.type_of( n ).to_s
1215        end.join( '' )
1216      )
1217    end
1218  end
1219
1220  alias to_s extract_text
1221
1222#private
1223#
1224#  def linear_node_index( node )
1225#    @position == -1 and fill_buffer
1226#    @nodes.each_with_index do |n, i|
1227#      node == n and return(i)
1228#    end
1229#    return -1
1230#  end
1231end
1232
1233=begin rdoc ANTLR3::AST::RewriteRuleElementStream
1234
1235Special type of stream that is used internally by tree-building and tree-
1236rewriting parsers.
1237
1238=end
1239
1240class RewriteRuleElementStream # < Array
1241  extend ClassMacros
1242  include Error
1243
1244  def initialize( adaptor, element_description, elements = nil )
1245    @cursor = 0
1246    @single_element = nil
1247    @elements = nil
1248    @dirty = false
1249    @element_description = element_description
1250    @adaptor = adaptor
1251    if elements.instance_of?( Array )
1252      @elements = elements
1253    else
1254      add( elements )
1255    end
1256  end
1257
1258  def reset
1259    @cursor = 0
1260    @dirty = true
1261  end
1262
1263  def add( el )
1264    return( nil ) unless el
1265    case
1266    when ! el then return( nil )
1267    when @elements then @elements << el
1268    when @single_element.nil? then @single_element = el
1269    else
1270      @elements = [ @single_element, el ]
1271      @single_element = nil
1272      return( @elements )
1273    end
1274  end
1275
1276  def next_tree
1277    if @dirty or @cursor >= length && length == 1
1278      return dup( __next__ )
1279    end
1280    __next__
1281  end
1282
1283  abstract :dup
1284
1285  def to_tree( el )
1286    return el
1287  end
1288
1289  def has_next?
1290    return( @single_element && @cursor < 1 or
1291           @elements && @cursor < @elements.length )
1292  end
1293
1294  def size
1295    @single_element and return 1
1296    @elements and return @elements.length
1297    return 0
1298  end
1299
1300  alias length size
1301
1302private
1303
1304  def __next__
1305    l = length
1306    case
1307    when l.zero?
1308      raise Error::RewriteEmptyStream.new( @element_description )
1309    when @cursor >= l
1310      l == 1 and return to_tree( @single_element )
1311      raise RewriteCardinalityError.new( @element_description )
1312    when @single_element
1313      @cursor += 1
1314      return( to_tree( @single_element ) )
1315    else
1316      out = to_tree( @elements.at( @cursor ) )
1317      @cursor += 1
1318      return( out )
1319    end
1320  end
1321end
1322
1323
1324=begin rdoc ANTLR3::AST::RewriteRuleTokenStream
1325
1326Special type of stream that is used internally by tree-building and tree-
1327rewriting parsers.
1328
1329=end
1330class RewriteRuleTokenStream < RewriteRuleElementStream
1331  def next_node
1332    return @adaptor.create_with_payload( __next__ )
1333  end
1334
1335  alias :next :__next__
1336  public :next
1337
1338  def dup( el )
1339    raise TypeError, "dup can't be called for a token stream"
1340  end
1341end
1342
1343=begin rdoc ANTLR3::AST::RewriteRuleSubtreeStream
1344
1345Special type of stream that is used internally by tree-building and tree-
1346rewriting parsers.
1347
1348=end
1349
1350class RewriteRuleSubtreeStream < RewriteRuleElementStream
1351  def next_node
1352    if @dirty or @cursor >= length && length == 1
1353      return @adaptor.copy_node( __next__ )
1354    end
1355    return __next__
1356  end
1357
1358  def dup( el )
1359    @adaptor.copy_tree( el )
1360  end
1361end
1362
1363=begin rdoc ANTLR3::AST::RewriteRuleNodeStream
1364
1365Special type of stream that is used internally by tree-building and tree-
1366rewriting parsers.
1367
1368=end
1369
1370class RewriteRuleNodeStream < RewriteRuleElementStream
1371  alias next_node __next__
1372  public :next_node
1373  def to_tree( el )
1374    @adaptor.copy_node( el )
1375  end
1376
1377  def dup( el )
1378    raise TypeError, "dup can't be called for a node stream"
1379  end
1380end
1381end
1382
1383include AST
1384end
1385