puppet 0.24.1 → 0.24.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/CHANGELOG +94 -0
- data/Rakefile +0 -4
- data/bin/puppet +18 -10
- data/bin/puppetd +1 -1
- data/bin/puppetdoc +14 -4
- data/bin/puppetmasterd +1 -1
- data/bin/puppetrun +3 -8
- data/bin/ralsh +12 -11
- data/conf/freebsd/puppetd +1 -1
- data/conf/freebsd/puppetmasterd +1 -1
- data/conf/gentoo/puppet/puppet.conf +29 -0
- data/conf/namespaceauth.conf +20 -0
- data/conf/redhat/puppet.spec +4 -1
- data/conf/solaris/smf/puppetd.xml +1 -1
- data/conf/solaris/smf/puppetmasterd.xml +1 -1
- data/conf/suse/puppet.spec +10 -8
- data/examples/root/etc/puppet/{puppetmasterd.conf → puppet.conf} +6 -3
- data/ext/logcheck/puppet +7 -0
- data/ext/puppet-test +28 -5
- data/lib/puppet.rb +2 -1
- data/lib/puppet/defaults.rb +12 -5
- data/lib/puppet/dsl.rb +43 -45
- data/lib/puppet/external/{gratr/rdot.rb → dot.rb} +0 -0
- data/lib/puppet/external/nagios.rb +50 -0
- data/lib/puppet/external/nagios/base.rb +421 -0
- data/lib/puppet/external/nagios/parser.rb +816 -0
- data/lib/puppet/file_serving/file_base.rb +16 -3
- data/lib/puppet/file_serving/metadata.rb +29 -11
- data/lib/puppet/indirector/terminus.rb +1 -0
- data/lib/puppet/metatype/closure.rb +4 -0
- data/lib/puppet/metatype/evaluation.rb +2 -17
- data/lib/puppet/metatype/metaparams.rb +1 -1
- data/lib/puppet/network.rb +3 -0
- data/lib/puppet/network/client.rb +4 -5
- data/lib/puppet/network/client/master.rb +10 -7
- data/lib/puppet/network/handler/fileserver.rb +22 -45
- data/lib/puppet/network/http_pool.rb +3 -0
- data/lib/puppet/network/http_server/mongrel.rb +7 -1
- data/lib/puppet/network/http_server/webrick.rb +4 -3
- data/lib/puppet/network/xmlrpc/client.rb +12 -1
- data/lib/puppet/node/catalog.rb +51 -40
- data/lib/puppet/parser/ast.rb +27 -49
- data/lib/puppet/parser/ast/astarray.rb +5 -24
- data/lib/puppet/parser/ast/caseopt.rb +4 -4
- data/lib/puppet/parser/ast/casestatement.rb +4 -5
- data/lib/puppet/parser/ast/collection.rb +3 -5
- data/lib/puppet/parser/ast/collexpr.rb +3 -5
- data/lib/puppet/parser/ast/definition.rb +148 -159
- data/lib/puppet/parser/ast/else.rb +2 -3
- data/lib/puppet/parser/ast/function.rb +3 -10
- data/lib/puppet/parser/ast/hostclass.rb +66 -59
- data/lib/puppet/parser/ast/ifstatement.rb +4 -5
- data/lib/puppet/parser/ast/leaf.rb +6 -6
- data/lib/puppet/parser/ast/node.rb +26 -58
- data/lib/puppet/parser/ast/resource.rb +5 -7
- data/lib/puppet/parser/ast/resource_defaults.rb +2 -4
- data/lib/puppet/parser/ast/resource_override.rb +4 -6
- data/lib/puppet/parser/ast/resource_reference.rb +2 -4
- data/lib/puppet/parser/ast/resourceparam.rb +2 -4
- data/lib/puppet/parser/ast/selector.rb +5 -6
- data/lib/puppet/parser/ast/tag.rb +2 -4
- data/lib/puppet/parser/ast/vardef.rb +3 -4
- data/lib/puppet/parser/collector.rb +5 -5
- data/lib/puppet/parser/{compile.rb → compiler.rb} +69 -107
- data/lib/puppet/parser/functions.rb +3 -3
- data/lib/puppet/parser/interpreter.rb +32 -23
- data/lib/puppet/parser/lexer.rb +391 -282
- data/lib/puppet/parser/parser.rb +5 -4
- data/lib/puppet/parser/parser_support.rb +3 -6
- data/lib/puppet/parser/resource.rb +24 -36
- data/lib/puppet/parser/resource/param.rb +1 -1
- data/lib/puppet/parser/resource/reference.rb +7 -3
- data/lib/puppet/parser/scope.rb +12 -7
- data/lib/puppet/parser/templatewrapper.rb +1 -1
- data/lib/puppet/pgraph.rb +9 -98
- data/lib/puppet/provider/interface/redhat.rb +65 -65
- data/lib/puppet/provider/mount/parsed.rb +1 -1
- data/lib/puppet/provider/naginator.rb +55 -0
- data/lib/puppet/provider/nameservice/directoryservice.rb +6 -7
- data/lib/puppet/provider/package/fink.rb +0 -2
- data/lib/puppet/provider/package/gem.rb +9 -5
- data/lib/puppet/provider/package/openbsd.rb +1 -1
- data/lib/puppet/provider/package/pkgdmg.rb +3 -8
- data/lib/puppet/provider/package/portage.rb +4 -4
- data/lib/puppet/provider/package/yumhelper.py +8 -6
- data/lib/puppet/provider/parsedfile.rb +7 -1
- data/lib/puppet/provider/service/debian.rb +2 -0
- data/lib/puppet/provider/service/gentoo.rb +4 -0
- data/lib/puppet/provider/service/init.rb +1 -1
- data/lib/puppet/provider/sshkey/parsed.rb +2 -0
- data/lib/puppet/provider/user/useradd.rb +1 -1
- data/lib/puppet/rails.rb +4 -0
- data/lib/puppet/rails/database/001_add_created_at_to_all_tables.rb +17 -0
- data/lib/puppet/rails/fact_value.rb +4 -0
- data/lib/puppet/rails/host.rb +1 -2
- data/lib/puppet/rails/param_value.rb +4 -0
- data/lib/puppet/rails/resource_tag.rb +4 -0
- data/lib/puppet/rails/source_file.rb +4 -1
- data/lib/puppet/relationship.rb +5 -1
- data/lib/puppet/reports/tagmail.rb +12 -1
- data/lib/puppet/resource_reference.rb +1 -1
- data/lib/puppet/simple_graph.rb +78 -11
- data/lib/puppet/sslcertificates.rb +1 -1
- data/lib/puppet/sslcertificates/ca.rb +3 -3
- data/lib/puppet/transaction.rb +7 -4
- data/lib/puppet/transportable.rb +1 -1
- data/lib/puppet/type.rb +3 -10
- data/lib/puppet/type/cron.rb +18 -0
- data/lib/puppet/type/exec.rb +18 -12
- data/lib/puppet/type/{pfile.rb → file.rb} +66 -84
- data/lib/puppet/type/file/checksum.rb +271 -0
- data/lib/puppet/type/{pfile → file}/content.rb +10 -15
- data/lib/puppet/type/{pfile → file}/ensure.rb +15 -8
- data/lib/puppet/type/{pfile → file}/group.rb +0 -0
- data/lib/puppet/type/{pfile → file}/mode.rb +0 -0
- data/lib/puppet/type/{pfile → file}/owner.rb +0 -0
- data/lib/puppet/type/{pfile → file}/source.rb +34 -48
- data/lib/puppet/type/{pfile → file}/target.rb +0 -0
- data/lib/puppet/type/{pfile → file}/type.rb +0 -0
- data/lib/puppet/type/{pfilebucket.rb → filebucket.rb} +0 -0
- data/lib/puppet/type/host.rb +13 -0
- data/lib/puppet/type/mailalias.rb +1 -1
- data/lib/puppet/type/nagios_command.rb +3 -0
- data/lib/puppet/type/nagios_contact.rb +3 -0
- data/lib/puppet/type/nagios_contactgroup.rb +3 -0
- data/lib/puppet/type/nagios_host.rb +3 -0
- data/lib/puppet/type/nagios_hostextinfo.rb +3 -0
- data/lib/puppet/type/nagios_hostgroup.rb +3 -0
- data/lib/puppet/type/nagios_hostgroupescalation.rb +3 -0
- data/lib/puppet/type/nagios_service.rb +3 -0
- data/lib/puppet/type/nagios_servicedependency.rb +3 -0
- data/lib/puppet/type/nagios_serviceescalation.rb +3 -0
- data/lib/puppet/type/nagios_serviceextinfo.rb +3 -0
- data/lib/puppet/type/nagios_timeperiod.rb +3 -0
- data/lib/puppet/type/package.rb +4 -12
- data/lib/puppet/type/service.rb +9 -0
- data/lib/puppet/type/sshkey.rb +3 -3
- data/lib/puppet/util/autoload.rb +5 -5
- data/lib/puppet/util/checksums.rb +51 -13
- data/lib/puppet/util/constant_inflector.rb +14 -0
- data/lib/puppet/util/filetype.rb +1 -1
- data/lib/puppet/util/graph.rb +3 -9
- data/lib/puppet/util/nagios_maker.rb +57 -0
- data/lib/puppet/util/settings.rb +19 -16
- data/lib/puppet/util/tagging.rb +39 -0
- data/test/executables/puppetbin.rb +17 -0
- data/test/language/ast.rb +8 -58
- data/test/language/ast/casestatement.rb +3 -3
- data/test/language/ast/resource.rb +6 -7
- data/test/language/ast/resource_reference.rb +12 -12
- data/test/language/ast/selector.rb +2 -2
- data/test/language/ast/variable.rb +2 -2
- data/test/language/functions.rb +24 -24
- data/test/language/parser.rb +20 -8
- data/test/language/resource.rb +5 -42
- data/test/language/scope.rb +21 -37
- data/test/language/snippets.rb +7 -0
- data/test/lib/puppettest.rb +28 -14
- data/test/lib/puppettest/parsertesting.rb +10 -10
- data/test/lib/puppettest/support/resources.rb +1 -1
- data/test/network/client/master.rb +10 -0
- data/test/network/handler/fileserver.rb +51 -49
- data/test/network/server/webrick.rb +1 -1
- data/test/other/dsl.rb +3 -4
- data/test/other/transactions.rb +6 -4
- data/test/rails/ast.rb +2 -2
- data/test/rails/configuration.rb +1 -1
- data/test/rails/railsparameter.rb +2 -0
- data/test/rails/railsresource.rb +1 -0
- data/test/ral/manager/type.rb +4 -4
- data/test/ral/providers/cron/crontab.rb +3 -1
- data/test/ral/providers/package.rb +1 -1
- data/test/ral/{types → type}/basic.rb +2 -2
- data/test/ral/{types → type}/cron.rb +0 -0
- data/test/ral/{types → type}/exec.rb +42 -2
- data/test/ral/{types → type}/file.rb +34 -79
- data/test/ral/{types → type}/file/target.rb +0 -0
- data/test/ral/{types → type}/filebucket.rb +0 -0
- data/test/ral/{types → type}/fileignoresource.rb +0 -0
- data/test/ral/{types → type}/filesources.rb +8 -27
- data/test/ral/{types → type}/group.rb +0 -0
- data/test/ral/{types → type}/host.rb +16 -0
- data/test/ral/{types → type}/mailalias.rb +0 -0
- data/test/ral/{types → type}/parameter.rb +0 -0
- data/test/ral/{types → type}/port.rb +0 -0
- data/test/ral/{types → type}/property.rb +0 -0
- data/test/ral/{types → type}/resources.rb +0 -0
- data/test/ral/{types → type}/service.rb +0 -0
- data/test/ral/{types → type}/sshkey.rb +0 -0
- data/test/ral/{types → type}/tidy.rb +1 -0
- data/test/ral/{types → type}/user.rb +0 -0
- data/test/ral/{types → type}/yumrepo.rb +0 -0
- data/test/ral/{types → type}/zone.rb +0 -0
- data/test/util/autoload.rb +24 -5
- metadata +60 -107
- data/conf/gentoo/puppet/puppetca.conf +0 -29
- data/conf/gentoo/puppet/puppetd.conf +0 -29
- data/conf/gentoo/puppet/puppetmasterd.conf +0 -29
- data/examples/root/etc/puppet/puppetd.conf +0 -4
- data/lib/puppet/external/gratr.rb +0 -33
- data/lib/puppet/external/gratr/adjacency_graph.rb +0 -257
- data/lib/puppet/external/gratr/base.rb +0 -34
- data/lib/puppet/external/gratr/biconnected.rb +0 -116
- data/lib/puppet/external/gratr/chinese_postman.rb +0 -123
- data/lib/puppet/external/gratr/common.rb +0 -73
- data/lib/puppet/external/gratr/comparability.rb +0 -92
- data/lib/puppet/external/gratr/digraph.rb +0 -116
- data/lib/puppet/external/gratr/digraph_distance.rb +0 -185
- data/lib/puppet/external/gratr/dot.rb +0 -90
- data/lib/puppet/external/gratr/edge.rb +0 -145
- data/lib/puppet/external/gratr/graph.rb +0 -303
- data/lib/puppet/external/gratr/graph_api.rb +0 -83
- data/lib/puppet/external/gratr/import.rb +0 -44
- data/lib/puppet/external/gratr/labels.rb +0 -90
- data/lib/puppet/external/gratr/maximum_flow.rb +0 -64
- data/lib/puppet/external/gratr/search.rb +0 -409
- data/lib/puppet/external/gratr/strong_components.rb +0 -127
- data/lib/puppet/external/gratr/undirected_graph.rb +0 -153
- data/lib/puppet/rails/external/tagging/acts_as_taggable.rb +0 -62
- data/lib/puppet/rails/external/tagging/init.rb +0 -5
- data/lib/puppet/rails/external/tagging/tag.rb +0 -50
- data/lib/puppet/rails/external/tagging/tagging.rb +0 -12
- data/lib/puppet/rails/puppet_class.rb +0 -6
- data/lib/puppet/reference/node_source.rb +0 -9
- data/lib/puppet/reference/report.rb +0 -21
- data/lib/puppet/type/pfile/checksum.rb +0 -326
- data/test/language/ast/definition.rb +0 -166
- data/test/language/ast/hostclass.rb +0 -184
- data/test/language/compile.rb +0 -569
- data/test/language/lexer.rb +0 -276
- data/test/lib/mocha.rb +0 -19
- data/test/lib/mocha/any_instance_method.rb +0 -35
- data/test/lib/mocha/auto_verify.rb +0 -113
- data/test/lib/mocha/central.rb +0 -35
- data/test/lib/mocha/class_method.rb +0 -62
- data/test/lib/mocha/deprecation.rb +0 -22
- data/test/lib/mocha/exception_raiser.rb +0 -17
- data/test/lib/mocha/expectation.rb +0 -378
- data/test/lib/mocha/expectation_error.rb +0 -6
- data/test/lib/mocha/infinite_range.rb +0 -25
- data/test/lib/mocha/inspect.rb +0 -39
- data/test/lib/mocha/instance_method.rb +0 -8
- data/test/lib/mocha/is_a.rb +0 -9
- data/test/lib/mocha/metaclass.rb +0 -7
- data/test/lib/mocha/missing_expectation.rb +0 -27
- data/test/lib/mocha/mock.rb +0 -207
- data/test/lib/mocha/multiple_yields.rb +0 -20
- data/test/lib/mocha/no_yields.rb +0 -11
- data/test/lib/mocha/object.rb +0 -110
- data/test/lib/mocha/parameter_matchers.rb +0 -9
- data/test/lib/mocha/parameter_matchers/all_of.rb +0 -39
- data/test/lib/mocha/parameter_matchers/any_of.rb +0 -44
- data/test/lib/mocha/parameter_matchers/anything.rb +0 -30
- data/test/lib/mocha/parameter_matchers/has_entry.rb +0 -39
- data/test/lib/mocha/parameter_matchers/has_key.rb +0 -39
- data/test/lib/mocha/parameter_matchers/has_value.rb +0 -39
- data/test/lib/mocha/parameter_matchers/includes.rb +0 -37
- data/test/lib/mocha/pretty_parameters.rb +0 -28
- data/test/lib/mocha/return_values.rb +0 -31
- data/test/lib/mocha/setup_and_teardown.rb +0 -23
- data/test/lib/mocha/single_return_value.rb +0 -24
- data/test/lib/mocha/single_yield.rb +0 -18
- data/test/lib/mocha/standalone.rb +0 -32
- data/test/lib/mocha/stub.rb +0 -18
- data/test/lib/mocha/test_case_adapter.rb +0 -49
- data/test/lib/mocha/yield_parameters.rb +0 -31
data/lib/puppet/parser/lexer.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
# the scanner/lexer
|
3
2
|
|
4
3
|
require 'strscan'
|
@@ -7,326 +6,436 @@ require 'puppet'
|
|
7
6
|
|
8
7
|
module Puppet
|
9
8
|
class LexError < RuntimeError; end
|
10
|
-
|
11
|
-
#---------------------------------------------------------------
|
12
|
-
class Lexer
|
13
|
-
attr_reader :line, :last, :file
|
14
|
-
|
15
|
-
attr_accessor :indefine
|
16
|
-
|
17
|
-
#%r{\w+} => :WORD,
|
18
|
-
@@tokens = {
|
19
|
-
%r{#.*} => :COMMENT,
|
20
|
-
%r{\[} => :LBRACK,
|
21
|
-
%r{\]} => :RBRACK,
|
22
|
-
%r{\{} => :LBRACE,
|
23
|
-
%r{\}} => :RBRACE,
|
24
|
-
%r{\(} => :LPAREN,
|
25
|
-
%r{\)} => :RPAREN,
|
26
|
-
%r{\"} => :DQUOTE,
|
27
|
-
%r{\n} => :RETURN,
|
28
|
-
%r{\'} => :SQUOTE,
|
29
|
-
%r{=} => :EQUALS,
|
30
|
-
%r{==} => :ISEQUAL,
|
31
|
-
%r{>=} => :GREATEREQUAL,
|
32
|
-
%r{>} => :GREATERTHAN,
|
33
|
-
%r{<} => :LESSTHAN,
|
34
|
-
%r{<=} => :LESSEQUAL,
|
35
|
-
%r{!=} => :NOTEQUAL,
|
36
|
-
%r{!} => :NOT,
|
37
|
-
%r{,} => :COMMA,
|
38
|
-
%r{\.} => :DOT,
|
39
|
-
%r{:} => :COLON,
|
40
|
-
%r{@} => :AT,
|
41
|
-
%r{<<\|} => :LLCOLLECT,
|
42
|
-
%r{\|>>} => :RRCOLLECT,
|
43
|
-
%r{<\|} => :LCOLLECT,
|
44
|
-
%r{\|>} => :RCOLLECT,
|
45
|
-
%r{;} => :SEMIC,
|
46
|
-
%r{\?} => :QMARK,
|
47
|
-
%r{\\} => :BACKSLASH,
|
48
|
-
%r{=>} => :FARROW,
|
49
|
-
%r{\+>} => :PARROW,
|
50
|
-
%r{[a-z][-\w]*} => :NAME,
|
51
|
-
%r{([a-z][-\w]*::)+[a-z][-\w]*} => :CLASSNAME,
|
52
|
-
%r{((::){0,1}[A-Z][-\w]*)+} => :CLASSREF,
|
53
|
-
%r{[0-9]+} => :NUMBER,
|
54
|
-
%r{\$(\w*::)*\w+} => :VARIABLE
|
55
|
-
}
|
56
|
-
|
57
|
-
@@pairs = {
|
58
|
-
"{" => "}",
|
59
|
-
"(" => ")",
|
60
|
-
"[" => "]",
|
61
|
-
"<|" => "|>",
|
62
|
-
"<<|" => "|>>"
|
63
|
-
}
|
64
|
-
|
65
|
-
@@reverse_pairs = @@pairs.inject({}) { |hash, pair| hash[pair[1]] = pair[0]; hash }
|
66
|
-
|
67
|
-
@@keywords = {
|
68
|
-
"case" => :CASE,
|
69
|
-
"class" => :CLASS,
|
70
|
-
"default" => :DEFAULT,
|
71
|
-
"define" => :DEFINE,
|
72
|
-
"false" => :BOOLEAN,
|
73
|
-
"import" => :IMPORT,
|
74
|
-
"if" => :IF,
|
75
|
-
"elsif" => :ELSIF,
|
76
|
-
"else" => :ELSE,
|
77
|
-
"inherits" => :INHERITS,
|
78
|
-
"node" => :NODE,
|
79
|
-
"true" => :BOOLEAN,
|
80
|
-
"and" => :AND,
|
81
|
-
"or" => :OR,
|
82
|
-
"undef" => :UNDEF
|
83
|
-
}
|
84
|
-
|
85
|
-
def clear
|
86
|
-
initvars
|
87
|
-
end
|
9
|
+
end
|
88
10
|
|
89
|
-
|
90
|
-
if @expected.empty?
|
91
|
-
nil
|
92
|
-
else
|
93
|
-
token = @expected[-1]
|
94
|
-
@@tokens.each do |value, name|
|
95
|
-
if token == name
|
96
|
-
return value
|
97
|
-
end
|
98
|
-
end
|
99
|
-
return token
|
100
|
-
end
|
101
|
-
end
|
11
|
+
module Puppet::Parser; end
|
102
12
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
return array
|
13
|
+
class Puppet::Parser::Lexer
|
14
|
+
attr_reader :last, :file
|
15
|
+
|
16
|
+
attr_accessor :line, :indefine
|
17
|
+
|
18
|
+
# Our base token class.
|
19
|
+
class Token
|
20
|
+
attr_accessor :regex, :name, :string, :skip, :incr_line, :skip_text
|
21
|
+
|
22
|
+
def initialize(regex, name)
|
23
|
+
if regex.is_a?(String)
|
24
|
+
@name, @string = name, regex
|
25
|
+
@regex = Regexp.new(Regexp.escape(@string))
|
26
|
+
else
|
27
|
+
@name, @regex = name, regex
|
119
28
|
end
|
29
|
+
end
|
120
30
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
}
|
31
|
+
def skip?
|
32
|
+
self.skip
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
if self.string
|
37
|
+
@string
|
38
|
+
else
|
39
|
+
@name.to_s
|
131
40
|
end
|
41
|
+
end
|
42
|
+
end
|
132
43
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
44
|
+
# Maintain a list of tokens.
|
45
|
+
class TokenList
|
46
|
+
attr_reader :regex_tokens, :string_tokens
|
47
|
+
|
48
|
+
def [](name)
|
49
|
+
@tokens[name]
|
50
|
+
end
|
51
|
+
|
52
|
+
# Create a new token.
|
53
|
+
def add_token(name, regex, options = {}, &block)
|
54
|
+
token = Token.new(regex, name)
|
55
|
+
raise(ArgumentError, "Token %s already exists" % name) if @tokens.include?(name)
|
56
|
+
@tokens[token.name] = token
|
57
|
+
if token.string
|
58
|
+
@string_tokens << token
|
59
|
+
@tokens_by_string[token.string] = token
|
60
|
+
else
|
61
|
+
@regex_tokens << token
|
139
62
|
end
|
140
63
|
|
141
|
-
|
142
|
-
|
64
|
+
options.each do |name, option|
|
65
|
+
token.send(name.to_s + "=", option)
|
143
66
|
end
|
144
67
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
@scanner = nil
|
150
|
-
@file = nil
|
151
|
-
# AAARRGGGG! okay, regexes in ruby are bloody annoying
|
152
|
-
# no one else has "\n" =~ /\s/
|
153
|
-
@skip = %r{[ \t]+}
|
68
|
+
token.meta_def(:convert, &block) if block_given?
|
69
|
+
|
70
|
+
token
|
71
|
+
end
|
154
72
|
|
155
|
-
|
156
|
-
|
73
|
+
def initialize
|
74
|
+
@tokens = {}
|
75
|
+
@regex_tokens = []
|
76
|
+
@string_tokens = []
|
77
|
+
@tokens_by_string = {}
|
78
|
+
end
|
157
79
|
|
158
|
-
|
159
|
-
|
80
|
+
# Look up a token by its value, rather than name.
|
81
|
+
def lookup(string)
|
82
|
+
@tokens_by_string[string]
|
83
|
+
end
|
160
84
|
|
161
|
-
|
162
|
-
|
163
|
-
|
85
|
+
# Define more tokens.
|
86
|
+
def add_tokens(hash)
|
87
|
+
hash.each do |regex, name|
|
88
|
+
add_token(name, regex)
|
164
89
|
end
|
90
|
+
end
|
165
91
|
|
166
|
-
|
167
|
-
|
168
|
-
|
92
|
+
# Sort our tokens by length, so we know once we match, we're done.
|
93
|
+
# This helps us avoid the O(n^2) nature of token matching.
|
94
|
+
def sort_tokens
|
95
|
+
@string_tokens.sort! { |a, b| b.string.length <=> a.string.length }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
TOKENS = TokenList.new
|
100
|
+
TOKENS.add_tokens(
|
101
|
+
'[' => :LBRACK,
|
102
|
+
']' => :RBRACK,
|
103
|
+
'{' => :LBRACE,
|
104
|
+
'}' => :RBRACE,
|
105
|
+
'(' => :LPAREN,
|
106
|
+
')' => :RPAREN,
|
107
|
+
'=' => :EQUALS,
|
108
|
+
'==' => :ISEQUAL,
|
109
|
+
'>=' => :GREATEREQUAL,
|
110
|
+
'>' => :GREATERTHAN,
|
111
|
+
'<' => :LESSTHAN,
|
112
|
+
'<=' => :LESSEQUAL,
|
113
|
+
'!=' => :NOTEQUAL,
|
114
|
+
'!' => :NOT,
|
115
|
+
',' => :COMMA,
|
116
|
+
'.' => :DOT,
|
117
|
+
':' => :COLON,
|
118
|
+
'@' => :AT,
|
119
|
+
'<<|' => :LLCOLLECT,
|
120
|
+
'|>>' => :RRCOLLECT,
|
121
|
+
'<|' => :LCOLLECT,
|
122
|
+
'|>' => :RCOLLECT,
|
123
|
+
';' => :SEMIC,
|
124
|
+
'?' => :QMARK,
|
125
|
+
'\\' => :BACKSLASH,
|
126
|
+
'=>' => :FARROW,
|
127
|
+
'+>' => :PARROW,
|
128
|
+
%r{([a-z][-\w]*::)+[a-z][-\w]*} => :CLASSNAME,
|
129
|
+
%r{((::){0,1}[A-Z][-\w]*)+} => :CLASSREF
|
130
|
+
)
|
131
|
+
|
132
|
+
TOKENS.add_tokens "Whatever" => :DQTEXT, "Nomatter" => :SQTEXT, "alsonomatter" => :BOOLEAN
|
133
|
+
|
134
|
+
TOKENS.add_token :NAME, %r{[a-z][-\w]*} do |lexer, value|
|
135
|
+
string_token = self
|
136
|
+
# we're looking for keywords here
|
137
|
+
if tmp = KEYWORDS.lookup(value)
|
138
|
+
string_token = tmp
|
139
|
+
if [:TRUE, :FALSE].include?(string_token.name)
|
140
|
+
value = eval(value)
|
141
|
+
string_token = TOKENS[:BOOLEAN]
|
169
142
|
end
|
143
|
+
end
|
144
|
+
[string_token, value]
|
145
|
+
end
|
146
|
+
|
147
|
+
TOKENS.add_token :NUMBER, %r{[0-9]+} do |lexer, value|
|
148
|
+
[TOKENS[:NAME], value]
|
149
|
+
end
|
150
|
+
|
151
|
+
TOKENS.add_token :COMMENT, %r{#.*}, :skip => true
|
152
|
+
|
153
|
+
TOKENS.add_token :RETURN, "\n", :skip => true, :incr_line => true, :skip_text => true
|
154
|
+
|
155
|
+
TOKENS.add_token :SQUOTE, "'" do |lexer, value|
|
156
|
+
value = lexer.slurpstring(value)
|
157
|
+
[TOKENS[:SQTEXT], value]
|
158
|
+
end
|
159
|
+
|
160
|
+
TOKENS.add_token :DQUOTE, '"' do |lexer, value|
|
161
|
+
value = lexer.slurpstring(value)
|
162
|
+
[TOKENS[:DQTEXT], value]
|
163
|
+
end
|
164
|
+
|
165
|
+
TOKENS.add_token :VARIABLE, %r{\$(\w*::)*\w+} do |lexer, value|
|
166
|
+
value = value.sub(/^\$/, '')
|
167
|
+
[self, value]
|
168
|
+
end
|
169
|
+
|
170
|
+
TOKENS.sort_tokens
|
171
|
+
|
172
|
+
@@pairs = {
|
173
|
+
"{" => "}",
|
174
|
+
"(" => ")",
|
175
|
+
"[" => "]",
|
176
|
+
"<|" => "|>",
|
177
|
+
"<<|" => "|>>"
|
178
|
+
}
|
179
|
+
|
180
|
+
KEYWORDS = TokenList.new
|
181
|
+
|
182
|
+
KEYWORDS.add_tokens(
|
183
|
+
"case" => :CASE,
|
184
|
+
"class" => :CLASS,
|
185
|
+
"default" => :DEFAULT,
|
186
|
+
"define" => :DEFINE,
|
187
|
+
"import" => :IMPORT,
|
188
|
+
"if" => :IF,
|
189
|
+
"elsif" => :ELSIF,
|
190
|
+
"else" => :ELSE,
|
191
|
+
"inherits" => :INHERITS,
|
192
|
+
"node" => :NODE,
|
193
|
+
"and" => :AND,
|
194
|
+
"or" => :OR,
|
195
|
+
"undef" => :UNDEF,
|
196
|
+
"false" => :FALSE,
|
197
|
+
"true" => :TRUE
|
198
|
+
)
|
199
|
+
|
200
|
+
def clear
|
201
|
+
initvars
|
202
|
+
end
|
203
|
+
|
204
|
+
def expected
|
205
|
+
return nil if @expected.empty?
|
206
|
+
name = @expected[-1]
|
207
|
+
raise "Could not find expected token %s" % name unless token = TOKENS.lookup(name)
|
208
|
+
|
209
|
+
return token
|
210
|
+
end
|
211
|
+
|
212
|
+
# scan the whole file
|
213
|
+
# basically just used for testing
|
214
|
+
def fullscan
|
215
|
+
array = []
|
216
|
+
|
217
|
+
self.scan { |token, str|
|
218
|
+
# Ignore any definition nesting problems
|
219
|
+
@indefine = false
|
220
|
+
array.push([token,str])
|
221
|
+
}
|
222
|
+
return array
|
223
|
+
end
|
224
|
+
|
225
|
+
# this is probably pretty damned inefficient...
|
226
|
+
# it'd be nice not to have to load the whole file first...
|
227
|
+
def file=(file)
|
228
|
+
@file = file
|
229
|
+
@line = 1
|
230
|
+
File.open(file) { |of|
|
231
|
+
str = ""
|
232
|
+
of.each { |line| str += line }
|
233
|
+
@scanner = StringScanner.new(str)
|
234
|
+
}
|
235
|
+
end
|
170
236
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
237
|
+
def find_string_token
|
238
|
+
matched_token = value = nil
|
239
|
+
|
240
|
+
# We know our longest string token is three chars, so try each size in turn
|
241
|
+
# until we either match or run out of chars. This way our worst-case is three
|
242
|
+
# tries, where it is otherwise the number of string chars we have. Also,
|
243
|
+
# the lookups are optimized hash lookups, instead of regex scans.
|
244
|
+
[3, 2, 1].each do |i|
|
245
|
+
str = @scanner.peek(i)
|
246
|
+
if matched_token = TOKENS.lookup(str)
|
247
|
+
value = @scanner.scan(matched_token.regex)
|
248
|
+
break
|
176
249
|
end
|
250
|
+
end
|
251
|
+
|
252
|
+
return matched_token, value
|
253
|
+
end
|
177
254
|
|
178
|
-
|
179
|
-
|
255
|
+
# Find the next token that matches a regex. We look for these first.
|
256
|
+
def find_regex_token
|
257
|
+
@regex += 1
|
258
|
+
matched_token = nil
|
259
|
+
value = ""
|
260
|
+
length = 0
|
261
|
+
|
262
|
+
# I tried optimizing based on the first char, but it had
|
263
|
+
# a slightly negative affect and was a good bit more complicated.
|
264
|
+
TOKENS.regex_tokens.each do |token|
|
265
|
+
next unless match_length = @scanner.match?(token.regex)
|
266
|
+
|
267
|
+
# We've found a longer match
|
268
|
+
if match_length > length
|
269
|
+
value = @scanner.scan(token.regex)
|
270
|
+
length = value.length
|
271
|
+
matched_token = token
|
180
272
|
end
|
273
|
+
end
|
181
274
|
|
182
|
-
|
183
|
-
|
184
|
-
#Puppet.debug("entering scan")
|
185
|
-
if @scanner.nil?
|
186
|
-
raise TypeError.new("Invalid or empty string")
|
187
|
-
end
|
275
|
+
return matched_token, value
|
276
|
+
end
|
188
277
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
stoken = nil
|
194
|
-
sregex = nil
|
195
|
-
value = ""
|
196
|
-
|
197
|
-
# first find out which type of token we've got
|
198
|
-
@@tokens.each { |regex,token|
|
199
|
-
# we're just checking, which doesn't advance the scan
|
200
|
-
# pointer
|
201
|
-
tmp = @scanner.check(regex)
|
202
|
-
if tmp.nil?
|
203
|
-
#puppet.debug("did not match %s to '%s'" %
|
204
|
-
# [regex,@scanner.rest])
|
205
|
-
next
|
206
|
-
end
|
207
|
-
|
208
|
-
# find the longest match
|
209
|
-
if tmp.length > value.length
|
210
|
-
value = tmp
|
211
|
-
stoken = token
|
212
|
-
sregex = regex
|
213
|
-
else
|
214
|
-
# we've already got a longer match
|
215
|
-
next
|
216
|
-
end
|
217
|
-
}
|
218
|
-
|
219
|
-
# error out if we didn't match anything at all
|
220
|
-
if stoken.nil?
|
221
|
-
nword = nil
|
222
|
-
if @scanner.rest =~ /^(\S+)/
|
223
|
-
nword = $1
|
224
|
-
elsif@scanner.rest =~ /^(\s+)/
|
225
|
-
nword = $1
|
226
|
-
else
|
227
|
-
nword = @scanner.rest
|
228
|
-
end
|
229
|
-
raise "Could not match '%s'" % nword
|
230
|
-
end
|
278
|
+
# Find the next token, returning the string and the token.
|
279
|
+
def find_token
|
280
|
+
@find += 1
|
281
|
+
matched_token, value = find_regex_token
|
231
282
|
|
232
|
-
|
283
|
+
unless matched_token
|
284
|
+
matched_token, value = find_string_token
|
285
|
+
end
|
233
286
|
|
234
|
-
|
235
|
-
|
236
|
-
end
|
287
|
+
return matched_token, value
|
288
|
+
end
|
237
289
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
wtoken = stoken
|
246
|
-
# we're looking for keywords here
|
247
|
-
if @@keywords.include?(value)
|
248
|
-
wtoken = @@keywords[value]
|
249
|
-
#Puppet.debug("token '%s'" % wtoken)
|
250
|
-
if wtoken == :BOOLEAN
|
251
|
-
value = eval(value)
|
252
|
-
end
|
253
|
-
end
|
254
|
-
ptoken = wtoken
|
255
|
-
when :NUMBER then
|
256
|
-
ptoken = :NAME
|
257
|
-
when :COMMENT then
|
258
|
-
# just throw comments away
|
259
|
-
next
|
260
|
-
when :RETURN then
|
261
|
-
@line += 1
|
262
|
-
@scanner.skip(@skip)
|
263
|
-
next
|
264
|
-
when :SQUOTE then
|
265
|
-
#Puppet.debug("searching '%s' after '%s'" % [self.rest,value])
|
266
|
-
value = self.slurpstring(value)
|
267
|
-
ptoken = :SQTEXT
|
268
|
-
#Puppet.debug("got string '%s' => '%s'" % [:DQTEXT,value])
|
269
|
-
when :DQUOTE then
|
270
|
-
value = self.slurpstring(value)
|
271
|
-
ptoken = :DQTEXT
|
272
|
-
when :VARIABLE then
|
273
|
-
value = value.sub(/^\$/, '')
|
274
|
-
end
|
290
|
+
def indefine?
|
291
|
+
if defined? @indefine
|
292
|
+
@indefine
|
293
|
+
else
|
294
|
+
false
|
295
|
+
end
|
296
|
+
end
|
275
297
|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
298
|
+
def initialize
|
299
|
+
@find = 0
|
300
|
+
@regex = 0
|
301
|
+
initvars()
|
302
|
+
end
|
281
303
|
|
282
|
-
|
304
|
+
def initvars
|
305
|
+
@line = 1
|
306
|
+
@previous_token = nil
|
307
|
+
@scanner = nil
|
308
|
+
@file = nil
|
309
|
+
# AAARRGGGG! okay, regexes in ruby are bloody annoying
|
310
|
+
# no one else has "\n" =~ /\s/
|
311
|
+
@skip = %r{[ \t]+}
|
312
|
+
|
313
|
+
@namestack = []
|
314
|
+
@indefine = false
|
315
|
+
@expected = []
|
316
|
+
end
|
283
317
|
|
284
|
-
|
285
|
-
|
286
|
-
|
318
|
+
# Make any necessary changes to the token and/or value.
|
319
|
+
def munge_token(token, value)
|
320
|
+
@line += 1 if token.incr_line
|
287
321
|
|
288
|
-
|
289
|
-
if indefine?
|
290
|
-
msg = "Cannot nest definition %s inside %s" % [value, @indefine]
|
291
|
-
self.indefine = false
|
292
|
-
raise Puppet::ParseError, msg
|
293
|
-
end
|
322
|
+
skip() if token.skip_text
|
294
323
|
|
295
|
-
|
296
|
-
end
|
324
|
+
return if token.skip
|
297
325
|
|
298
|
-
|
299
|
-
@lasttoken = ptoken
|
326
|
+
token, value = token.convert(self, value) if token.respond_to?(:convert)
|
300
327
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
328
|
+
return unless token
|
329
|
+
|
330
|
+
return token, value
|
331
|
+
end
|
332
|
+
|
333
|
+
# Go up one in the namespace.
|
334
|
+
def namepop
|
335
|
+
@namestack.pop
|
336
|
+
end
|
306
337
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
338
|
+
# Collect the current namespace.
|
339
|
+
def namespace
|
340
|
+
@namestack.join("::")
|
341
|
+
end
|
342
|
+
|
343
|
+
# This value might have :: in it, but we don't care -- it'll be
|
344
|
+
# handled normally when joining, and when popping we want to pop
|
345
|
+
# this full value, however long the namespace is.
|
346
|
+
def namestack(value)
|
347
|
+
@namestack << value
|
348
|
+
end
|
349
|
+
|
350
|
+
def rest
|
351
|
+
@scanner.rest
|
352
|
+
end
|
353
|
+
|
354
|
+
# this is the heart of the lexer
|
355
|
+
def scan
|
356
|
+
#Puppet.debug("entering scan")
|
357
|
+
raise Puppet::LexError.new("Invalid or empty string") unless @scanner
|
358
|
+
|
359
|
+
# Skip any initial whitespace.
|
360
|
+
skip()
|
361
|
+
|
362
|
+
until @scanner.eos? do
|
363
|
+
yielded = false
|
364
|
+
matched_token, value = find_token
|
365
|
+
|
366
|
+
# error out if we didn't match anything at all
|
367
|
+
if matched_token.nil?
|
368
|
+
nword = nil
|
369
|
+
# Try to pull a 'word' out of the remaining string.
|
370
|
+
if @scanner.rest =~ /^(\S+)/
|
371
|
+
nword = $1
|
372
|
+
elsif @scanner.rest =~ /^(\s+)/
|
373
|
+
nword = $1
|
316
374
|
else
|
317
|
-
|
318
|
-
str.gsub!(/\\#{quote}/,quote)
|
375
|
+
nword = @scanner.rest
|
319
376
|
end
|
377
|
+
raise "Could not match '%s'" % nword
|
378
|
+
end
|
320
379
|
|
321
|
-
|
380
|
+
final_token, value = munge_token(matched_token, value)
|
381
|
+
|
382
|
+
next unless final_token
|
383
|
+
|
384
|
+
if match = @@pairs[value] and final_token.name != :DQUOTE and final_token.name != :SQUOTE
|
385
|
+
@expected << match
|
386
|
+
elsif exp = @expected[-1] and exp == value and final_token.name != :DQUOTE and final_token.name != :SQUOTE
|
387
|
+
@expected.pop
|
322
388
|
end
|
323
389
|
|
324
|
-
|
325
|
-
|
326
|
-
|
390
|
+
yield [final_token.name, value]
|
391
|
+
|
392
|
+
if @previous_token
|
393
|
+
namestack(value) if @previous_token.name == :CLASS
|
394
|
+
|
395
|
+
if @previous_token.name == :DEFINE
|
396
|
+
if indefine?
|
397
|
+
msg = "Cannot nest definition %s inside %s" % [value, @indefine]
|
398
|
+
self.indefine = false
|
399
|
+
raise Puppet::ParseError, msg
|
400
|
+
end
|
401
|
+
|
402
|
+
@indefine = value
|
403
|
+
end
|
327
404
|
end
|
405
|
+
|
406
|
+
@previous_token = final_token
|
407
|
+
skip()
|
328
408
|
end
|
329
|
-
|
409
|
+
@scanner = nil
|
410
|
+
|
411
|
+
# This indicates that we're done parsing.
|
412
|
+
yield [false,false]
|
413
|
+
end
|
414
|
+
|
415
|
+
# Skip any skipchars in our remaining string.
|
416
|
+
def skip
|
417
|
+
@scanner.skip(@skip)
|
330
418
|
end
|
331
|
-
end
|
332
419
|
|
420
|
+
# we've encountered an opening quote...
|
421
|
+
# slurp in the rest of the string and return it
|
422
|
+
def slurpstring(quote)
|
423
|
+
# we search for the next quote that isn't preceded by a
|
424
|
+
# backslash; the caret is there to match empty strings
|
425
|
+
str = @scanner.scan_until(/([^\\]|^)#{quote}/)
|
426
|
+
if str.nil?
|
427
|
+
raise Puppet::LexError.new("Unclosed quote after '%s' in '%s'" %
|
428
|
+
[self.last,self.rest])
|
429
|
+
else
|
430
|
+
str.sub!(/#{quote}\Z/,"")
|
431
|
+
str.gsub!(/\\#{quote}/,quote)
|
432
|
+
end
|
433
|
+
|
434
|
+
return str
|
435
|
+
end
|
436
|
+
|
437
|
+
# just parse a string, not a whole file
|
438
|
+
def string=(string)
|
439
|
+
@scanner = StringScanner.new(string)
|
440
|
+
end
|
441
|
+
end
|