public
Description: Code from my series on writing a Ruby compiler in Ruby
Homepage: http://www.hokstad.com/compiler
Clone URL: git://github.com/vidarh/writing-a-compiler-in-ruby.git
100644 61 lines (53 sloc) 1.501 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
module AST
 
  # Adds properties to AST nodes that simplify error
  # reporting, debugging etc.
  #
  # This will later also provide a location for
  # plugins to attach additional notation to the
  # nodes, such as inferred type information etc.
  module Node
    attr_accessor :position
  end
 
  # Inheriting from Array lets most code just work on the
  # expression as a raw set of data. And it avoids the hassle
  # of changing lots of code. At the same time, we can attach
  # extra data - we're sneaky like that.
  #
  # call-seq:
  # Expr[1,2,3]
  #
  # FIXME: When called with tokens from the scanner, it is the
  # intention that these tokens will *also* hav a position
  # and carry position information, and that Expr's constructor
  # will default to take the position information of the first
  # node it is passed that respond_to?(:position).
  #
  # Alternatively, if the first argument is_a?(Scanner::Position)
  # it will be stripped and used as the position.
  class Expr < Array
    include Node
 
    def update_position
      sub = find {|n| n.respond_to?(:position) }
      position = sub.position if sub
    end
 
    def self.[] *args
      if args.size > 0 && args.first.is_a?(Scanner::Position)
        pos = args.shift
      end
      e = super *args
      if pos
        position = pos
      else
        e.update_position
      end
      e
    end
 
    def concat other
      super(other)
      update_position
      self
    end
  end
 
  # For convience
  E = Expr
end