summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parser/ast.rb
blob: 54e034acbdbd2eba97d7d5531a08c12f10b199fb (plain)
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# the parent class for all of our syntactical objects

require 'puppet'
require 'puppet/util/autoload'
require 'puppet/file_collection/lookup'

# The base class for all of the objects that make up the parse trees.
# Handles things like file name, line #, and also does the initialization
# for all of the parameters of all of the child objects.
class Puppet::Parser::AST
  # Do this so I don't have to type the full path in all of the subclasses
  AST = Puppet::Parser::AST

  include Puppet::FileCollection::Lookup

  include Puppet::Util::Errors
  include Puppet::Util::MethodHelper
  include Puppet::Util::Docs

  attr_accessor :parent, :scope

  # don't fetch lexer comment by default
  def use_docs
    self.class.use_docs
  end

  # allow our subclass to specify they want documentation
  class << self
    attr_accessor :use_docs
    def associates_doc
    self.use_docs = true
    end
  end

  # Does this ast object set something?  If so, it gets evaluated first.
  def self.settor?
    if defined?(@settor)
      @settor
    else
      false
    end
  end

  # Evaluate the current object.  Just a stub method, since the subclass
  # should override this method.
  # of the contained children and evaluates them in turn, returning a
  # list of all of the collected values, rejecting nil values
  def evaluate(*options)
    raise Puppet::DevError, "Did not override #evaluate in #{self.class}"
  end

  # Throw a parse error.
  def parsefail(message)
    self.fail(Puppet::ParseError, message)
  end

  # Wrap a statemp in a reusable way so we always throw a parse error.
  def parsewrap
    exceptwrap :type => Puppet::ParseError do
      yield
    end
  end

  # The version of the evaluate method that should be called, because it
  # correctly handles errors.  It is critical to use this method because
  # it can enable you to catch the error where it happens, rather than
  # much higher up the stack.
  def safeevaluate(*options)
    # We duplicate code here, rather than using exceptwrap, because this
    # is called so many times during parsing.
    begin
      return self.evaluate(*options)
    rescue Puppet::Error => detail
      raise adderrorcontext(detail)
    rescue => detail
      error = Puppet::Error.new(detail.to_s)
      # We can't use self.fail here because it always expects strings,
      # not exceptions.
      raise adderrorcontext(error, detail)
    end
  end

  # Initialize the object.  Requires a hash as the argument, and
  # takes each of the parameters of the hash and calls the settor
  # method for them.  This is probably pretty inefficient and should
  # likely be changed at some point.
  def initialize(args)
    set_options(args)
  end

  # evaluate ourselves, and match
  def evaluate_match(value, scope)
    obj = self.safeevaluate(scope)

    obj   = obj.downcase   if obj.respond_to?(:downcase)
    value = value.downcase if value.respond_to?(:downcase)

    obj   = Puppet::Parser::Scope.number?(obj)   || obj
    value = Puppet::Parser::Scope.number?(value) || value

    # "" == undef for case/selector/if
    obj == value or (obj == "" and value == :undef)
  end
end

# And include all of the AST subclasses.
require 'puppet/parser/ast/arithmetic_operator'
require 'puppet/parser/ast/astarray'
require 'puppet/parser/ast/asthash'
require 'puppet/parser/ast/branch'
require 'puppet/parser/ast/boolean_operator'
require 'puppet/parser/ast/caseopt'
require 'puppet/parser/ast/casestatement'
require 'puppet/parser/ast/collection'
require 'puppet/parser/ast/collexpr'
require 'puppet/parser/ast/comparison_operator'
require 'puppet/parser/ast/else'
require 'puppet/parser/ast/function'
require 'puppet/parser/ast/ifstatement'
require 'puppet/parser/ast/in_operator'
require 'puppet/parser/ast/leaf'
require 'puppet/parser/ast/match_operator'
require 'puppet/parser/ast/minus'
require 'puppet/parser/ast/nop'
require 'puppet/parser/ast/not'
require 'puppet/parser/ast/resource'
require 'puppet/parser/ast/resource_defaults'
require 'puppet/parser/ast/resource_override'
require 'puppet/parser/ast/resource_reference'
require 'puppet/parser/ast/resourceparam'
require 'puppet/parser/ast/selector'
require 'puppet/parser/ast/tag'
require 'puppet/parser/ast/vardef'
require 'puppet/parser/ast/relationship'