summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parser/ast.rb
blob: ce5e8263e1f232b6ef07532cb89d238cab7bf1f6 (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
# the parent class for all of our syntactical objects

require 'puppet'
require 'puppet/util/autoload'

# 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::Util::Errors
    include Puppet::Util::MethodHelper
    attr_accessor :line, :file, :parent, :scope

    # Just used for 'tree', which is only used in debugging.
    @@pink = ""
    @@green = ""
    @@yellow = ""
    @@slate = ""
    @@reset = ""

    # Just used for 'tree', which is only used in debugging.
    @@indent = " " * 4
    @@indline = @@pink + ("-" * 4) + @@reset
    @@midline = @@slate + ("-" * 4) + @@reset

    @@settypes = {}

    # Just used for 'tree', which is only used in debugging.
    def AST.indention
        return @@indent * @@indention
    end

    # Just used for 'tree', which is only used in debugging.
    def AST.midline
        return @@midline
    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.  Basically just iterates across all
    # of the contained children and evaluates them in turn, returning a
    # list of all of the collected values, rejecting nil values
    def evaluate(args)
        #Puppet.debug("Evaluating ast %s" % @name)
        value = self.collect { |obj|
            obj.safeevaluate(args)
        }.reject { |obj|
            obj.nil?
        }
    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

    # Again, just used for printing out the parse tree.
    def typewrap(string)
        #return self.class.to_s.sub(/.+::/,'') +
            #"(" + @@green + string.to_s + @@reset + ")"
        return @@green + string.to_s + @@reset +
            "(" + self.class.to_s.sub(/.+::/,'') + ")"
    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)
        @file = nil
        @line = nil
        set_options(args)
    end
    #---------------------------------------------------------------
    # Now autoload everything.
    @autoloader = Puppet::Util::Autoload.new(self,
        "puppet/parser/ast"
    )
    @autoloader.loadall
end

require 'puppet/parser/ast/leaf'

# $Id$