hcl-checker 1.4.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +32 -0
- data/Gemfile +3 -4
- data/Gemfile.lock +21 -22
- data/README.md +3 -3
- data/Rakefile +7 -8
- data/assets/lexer.rex +24 -19
- data/assets/parse.y +33 -14
- data/bin/console +3 -3
- data/hcl-checker.gemspec +9 -25
- data/lib/hcl/{lexer.rb → checker/lexer.rb} +23 -16
- data/lib/hcl/checker/parser.rb +496 -0
- data/lib/hcl/checker/version.rb +1 -1
- data/lib/hcl/checker.rb +27 -14
- metadata +34 -54
- data/lib/hcl/parser.rb +0 -456
- data/lib/hcl1/checker/version.rb +0 -5
- data/lib/hcl1/checker.rb +0 -21
- data/lib/hcl1/lexer.rb +0 -175
- data/lib/hcl1/parser.rb +0 -456
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e385b2693e62154b496432fb0baf5022d64fdc0827b5703d33be6a05dbfb50c6
|
4
|
+
data.tar.gz: 931d2e6fe0348c24164bfc17d6686ebd6b64ac41e2acb9884af1d51c189764c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c23f7d1562b29c3523de8be84d57a7690ff5c1f7680a368df049b7c21dd4b3246f2417a79df09f797ad00bd2743ec218effe67ffd020132174a79c5dd2ccaf4a
|
7
|
+
data.tar.gz: 8874919303dad9cbb0285fa69a042ddb4a444df7c71d76c41d8cb39639e333fddcdec13768cedb4fffcde4fdabcc3f9c70e805b89c5744cf643b0e267dd7b449
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
AllCops:
|
2
|
+
NewCops: enable
|
3
|
+
Exclude:
|
4
|
+
- lib/hcl/lexer.rb
|
5
|
+
- lib/hcl/parser.rb
|
6
|
+
|
7
|
+
Layout/LineLength:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
Metrics/AbcSize:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Metrics/BlockLength:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Metrics/ClassLength:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Metrics/CyclomaticComplexity:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Metrics/MethodLength:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Metrics/PerceivedComplexity:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
Style/Documentation:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Style/FrozenStringLiteralComment:
|
32
|
+
EnforcedStyle: never
|
data/Gemfile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
3
|
# This is needed due https://nvd.nist.gov/vuln/detail/CVE-2018-14404
|
4
4
|
# A NULL pointer dereference vulnerability exists in the xpath.c:xmlXPathCompOpEval()
|
@@ -7,10 +7,9 @@ source "https://rubygems.org"
|
|
7
7
|
# with the use of the libxml2 library may be vulnerable to a denial of service attack due
|
8
8
|
# to a crash of the application.
|
9
9
|
# Nokogiri >= 1.8.5 solves this problem
|
10
|
-
gem
|
10
|
+
gem 'nokogiri', '>= 1.11.4'
|
11
11
|
|
12
|
-
|
13
|
-
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
12
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
14
13
|
|
15
14
|
# Specify your gem's dependencies in hcl-checker.gemspec
|
16
15
|
gemspec
|
data/Gemfile.lock
CHANGED
@@ -1,20 +1,19 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
hcl-checker (1.
|
4
|
+
hcl-checker (1.6.1)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
diff-lcs (1.
|
9
|
+
diff-lcs (1.5.0)
|
10
10
|
filesize (0.2.0)
|
11
11
|
jsobfu (0.4.2)
|
12
12
|
rkelly-remix
|
13
|
-
json (2.
|
14
|
-
metasm (1.0.
|
15
|
-
|
16
|
-
|
17
|
-
mini_portile2 (~> 2.4.0)
|
13
|
+
json (2.6.1)
|
14
|
+
metasm (1.0.5)
|
15
|
+
nokogiri (1.13.6-arm64-darwin)
|
16
|
+
racc (~> 1.4)
|
18
17
|
racc (1.5.0)
|
19
18
|
rake (12.3.3)
|
20
19
|
rb-readline (0.5.5)
|
@@ -27,27 +26,27 @@ GEM
|
|
27
26
|
rb-readline (~> 0)
|
28
27
|
rexical (1.0.7)
|
29
28
|
rkelly-remix (0.0.7)
|
30
|
-
rspec (3.
|
31
|
-
rspec-core (~> 3.
|
32
|
-
rspec-expectations (~> 3.
|
33
|
-
rspec-mocks (~> 3.
|
34
|
-
rspec-core (3.
|
35
|
-
rspec-support (~> 3.
|
36
|
-
rspec-expectations (3.
|
29
|
+
rspec (3.11.0)
|
30
|
+
rspec-core (~> 3.11.0)
|
31
|
+
rspec-expectations (~> 3.11.0)
|
32
|
+
rspec-mocks (~> 3.11.0)
|
33
|
+
rspec-core (3.11.0)
|
34
|
+
rspec-support (~> 3.11.0)
|
35
|
+
rspec-expectations (3.11.0)
|
37
36
|
diff-lcs (>= 1.2.0, < 2.0)
|
38
|
-
rspec-support (~> 3.
|
39
|
-
rspec-mocks (3.
|
37
|
+
rspec-support (~> 3.11.0)
|
38
|
+
rspec-mocks (3.11.1)
|
40
39
|
diff-lcs (>= 1.2.0, < 2.0)
|
41
|
-
rspec-support (~> 3.
|
42
|
-
rspec-support (3.
|
40
|
+
rspec-support (~> 3.11.0)
|
41
|
+
rspec-support (3.11.0)
|
43
42
|
|
44
43
|
PLATFORMS
|
45
|
-
|
44
|
+
arm64-darwin-21
|
46
45
|
|
47
46
|
DEPENDENCIES
|
48
|
-
bundler (~> 2.
|
47
|
+
bundler (~> 2.3.13)
|
49
48
|
hcl-checker!
|
50
|
-
nokogiri (>= 1.
|
49
|
+
nokogiri (>= 1.11.4)
|
51
50
|
racc (= 1.5.0)
|
52
51
|
rake (~> 12.3.3)
|
53
52
|
rex (= 2.0.12)
|
@@ -55,4 +54,4 @@ DEPENDENCIES
|
|
55
54
|
rspec (~> 3.0)
|
56
55
|
|
57
56
|
BUNDLED WITH
|
58
|
-
2.
|
57
|
+
2.3.13
|
data/README.md
CHANGED
@@ -47,21 +47,21 @@ You can validate the `hcl_string` contents with `valid?` method. This will
|
|
47
47
|
return `true` if is a valid HCL or `false` if not.
|
48
48
|
|
49
49
|
```
|
50
|
-
2.3.2 :014 >
|
50
|
+
2.3.2 :014 > HCL::Checker.valid? hcl_string
|
51
51
|
=> true
|
52
52
|
```
|
53
53
|
|
54
54
|
You can parse the `hcl_string` into a `Hash` with `parse` method.
|
55
55
|
|
56
56
|
```
|
57
|
-
2.3.2 :015 >
|
57
|
+
2.3.2 :015 > HCL::Checker.parse(hcl_string)
|
58
58
|
=> {"provider"=>{"aws"=>{"region"=>"${var.aws_region}", "access_key"=>"${var.aws_access_key}", "secret_key"=>"${var.aws_secret_key}"}}, "resource"=>{"aws_vpc"=>{"default"=>{"cidr_block"=>"10.0.0.0/16", "enable_dns_hostnames"=>true, "tags"=>{"Name"=>"Event Store VPC"}}}}}
|
59
59
|
```
|
60
60
|
|
61
61
|
If after a `parse` you got `false` you can check `last_error` with:
|
62
62
|
|
63
63
|
```
|
64
|
-
2.4.2 :063 >
|
64
|
+
2.4.2 :063 > HCL::Checker.last_error
|
65
65
|
=> "Parse error at \"eec8b16c-ee89-4ea0-bdcc-d094300a42e8\" , (invalid token: ,)"
|
66
66
|
```
|
67
67
|
|
data/Rakefile
CHANGED
@@ -1,19 +1,18 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
3
|
|
4
4
|
RSpec::Core::RakeTask.new do |c|
|
5
|
-
options = [
|
6
|
-
options += [
|
5
|
+
options = ['--color']
|
6
|
+
options += ['--format', 'documentation']
|
7
7
|
c.rspec_opts = options
|
8
8
|
end
|
9
9
|
|
10
|
-
desc
|
10
|
+
desc 'Generate Grammar files for HCL'
|
11
11
|
task :build_grammar do
|
12
12
|
print 'Building Lexer'
|
13
|
-
`rex
|
13
|
+
`rex ./assets/lexer.rex -o ./lib/hcl/checker/lexer.rb`
|
14
14
|
print "....done\n"
|
15
15
|
print 'Building Parser'
|
16
|
-
`racc ./assets/parse.y -o ./lib/hcl/parser.rb`
|
16
|
+
`racc ./assets/parse.y -o ./lib/hcl/checker/parser.rb`
|
17
17
|
print "....done\n\n"
|
18
18
|
end
|
19
|
-
|
data/assets/lexer.rex
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
-
|
2
|
-
class HCLLexer
|
1
|
+
class HCL::Checker::Lexer
|
3
2
|
option
|
4
3
|
independent
|
5
|
-
|
4
|
+
|
6
5
|
macro
|
7
6
|
NEWLINE \n|\r
|
8
7
|
BLANK \s+
|
@@ -20,6 +19,8 @@ macro
|
|
20
19
|
RIGHTBRACE \}
|
21
20
|
LEFTBRACKET \[
|
22
21
|
RIGHTBRACKET \]
|
22
|
+
LEFTPARENTHESES \(
|
23
|
+
RIGHTPARENTHESES \)
|
23
24
|
HEREDOCUMENT \<<\-?
|
24
25
|
|
25
26
|
rule
|
@@ -36,37 +37,39 @@ rule
|
|
36
37
|
{QUOTE} { [:STRING, consume_string(text)] }
|
37
38
|
{HEREDOCUMENT} { [:STRING, consume_heredoc] }
|
38
39
|
#-------------------------------------------------------------------------------
|
39
|
-
{LEFTBRACE} { [:LEFTBRACE,
|
40
|
-
{RIGHTBRACE} { [:RIGHTBRACE,
|
41
|
-
{LEFTBRACKET} { [:LEFTBRACKET,
|
42
|
-
{RIGHTBRACKET} { [:RIGHTBRACKET,
|
40
|
+
{LEFTBRACE} { [:LEFTBRACE, text]}
|
41
|
+
{RIGHTBRACE} { [:RIGHTBRACE, text]}
|
42
|
+
{LEFTBRACKET} { [:LEFTBRACKET, text]}
|
43
|
+
{RIGHTBRACKET} { [:RIGHTBRACKET, text]}
|
44
|
+
{LEFTPARENTHESES} { [:LEFTPARENTHESES, text]}
|
45
|
+
{RIGHTPARENTHESES} { [:RIGHTPARENTHESES, text]}
|
43
46
|
#-------------------------------------------------------------------------------
|
44
47
|
{COMMA} { [:COMMA, text]}
|
45
48
|
{IDENTIFIER} { [:IDENTIFIER, text]}
|
46
49
|
{EQUAL} { [:EQUAL, text]}
|
47
50
|
{MINUS} { [:MINUS, text]}
|
48
51
|
|
49
|
-
|
50
52
|
inner
|
51
|
-
|
52
53
|
def lex(input)
|
53
54
|
scan_setup(input)
|
54
55
|
tokens = []
|
55
56
|
while token = next_token
|
56
57
|
tokens << token
|
57
58
|
end
|
59
|
+
|
58
60
|
tokens
|
59
61
|
end
|
60
62
|
|
61
63
|
|
62
64
|
def to_boolean(input)
|
63
|
-
input
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
65
|
+
case input
|
66
|
+
when /true/
|
67
|
+
true
|
68
|
+
when /false/
|
69
|
+
false
|
70
|
+
else
|
71
|
+
raise "Invalid value for `to_boolean`, expected true/false got #{input}"
|
72
|
+
end
|
70
73
|
end
|
71
74
|
|
72
75
|
|
@@ -90,19 +93,21 @@ inner
|
|
90
93
|
result = ''
|
91
94
|
nested = 0
|
92
95
|
|
93
|
-
|
96
|
+
loop do
|
94
97
|
case(text = @ss.scan_until(%r{\"|\$\{|\}|\\}))
|
95
98
|
when %r{\$\{\z}
|
96
99
|
nested += 1
|
97
100
|
when %r{\}\z}
|
98
|
-
nested -= 1 if nested
|
101
|
+
nested -= 1 if nested.positive?
|
99
102
|
when %r{\\\z}
|
100
103
|
result += text.chop + @ss.getch
|
101
104
|
next
|
102
105
|
end
|
103
106
|
|
104
107
|
result += text.to_s
|
105
|
-
|
108
|
+
|
109
|
+
break if nested.zero? && text =~ %r{\"\z}
|
110
|
+
end
|
106
111
|
|
107
112
|
result.chop
|
108
113
|
end
|
data/assets/parse.y
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
class
|
1
|
+
class HCL::Checker::Parser
|
2
2
|
token BOOL
|
3
3
|
FLOAT
|
4
4
|
NUMBER
|
@@ -12,6 +12,8 @@ token BOOL
|
|
12
12
|
RIGHTBRACE
|
13
13
|
LEFTBRACKET
|
14
14
|
RIGHTBRACKET
|
15
|
+
LEFTPARENTHESES
|
16
|
+
RIGHTPARENTHESES
|
15
17
|
PERIOD
|
16
18
|
EPLUS
|
17
19
|
EMINUS
|
@@ -24,7 +26,6 @@ rule
|
|
24
26
|
| objectlist
|
25
27
|
;
|
26
28
|
|
27
|
-
|
28
29
|
objectlist:
|
29
30
|
objectitem COMMA
|
30
31
|
{ result = [val[0]] }
|
@@ -40,7 +41,7 @@ rule
|
|
40
41
|
LEFTBRACE objectlist RIGHTBRACE
|
41
42
|
{ result = flatten_objectlist(val[1]) }
|
42
43
|
| LEFTBRACE RIGHTBRACE
|
43
|
-
{ return }
|
44
|
+
{ return {} }
|
44
45
|
;
|
45
46
|
|
46
47
|
objectkey:
|
@@ -61,6 +62,10 @@ rule
|
|
61
62
|
{ result = val[0], val[2] }
|
62
63
|
| objectkey EQUAL list
|
63
64
|
{ result = val[0], val[2] }
|
65
|
+
| objectkey EQUAL IDENTIFIER LEFTPARENTHESES IDENTIFIER RIGHTPARENTHESES
|
66
|
+
{ result = val[0], "#{val[2]}(#{val[4]})" }
|
67
|
+
| objectkey EQUAL IDENTIFIER
|
68
|
+
{ result = val[0], val[2] }
|
64
69
|
| block
|
65
70
|
{ result = val[0] }
|
66
71
|
;
|
@@ -83,7 +88,7 @@ rule
|
|
83
88
|
LEFTBRACKET listitems RIGHTBRACKET
|
84
89
|
{ result = val[1] }
|
85
90
|
| LEFTBRACKET RIGHTBRACKET
|
86
|
-
{ return }
|
91
|
+
{ return [] }
|
87
92
|
;
|
88
93
|
|
89
94
|
listitems:
|
@@ -117,7 +122,7 @@ rule
|
|
117
122
|
end
|
118
123
|
|
119
124
|
---- header
|
120
|
-
require_relative '
|
125
|
+
require_relative 'lexer'
|
121
126
|
|
122
127
|
---- inner
|
123
128
|
#//
|
@@ -125,19 +130,31 @@ require_relative './lexer'
|
|
125
130
|
#// keys are encountered.
|
126
131
|
#//
|
127
132
|
#// from decoder.go: if we're at the root or we're directly within
|
128
|
-
#// a list, decode
|
133
|
+
#// a list, decode to hashes, otherwise lists
|
129
134
|
#//
|
130
135
|
#// from object.go: there is a flattened list structure
|
131
136
|
#//
|
137
|
+
#// if @duplicate_mode is set:
|
138
|
+
#// - :array then duplicates will be appended to an array
|
139
|
+
#// - :merge then duplicates will be deep merged into a hash
|
140
|
+
#//
|
132
141
|
def flatten_objectlist(list)
|
133
142
|
(list || {}).each_with_object({}) do |a, h|
|
134
|
-
h
|
135
|
-
case
|
136
|
-
when
|
143
|
+
if h.keys.include?(a.first)
|
144
|
+
case @duplicate_mode
|
145
|
+
when :array
|
146
|
+
if h[a.first].is_a?(Array)
|
147
|
+
h[a.first].push(a.last)
|
148
|
+
else
|
149
|
+
h[a.first] = [ h[a.first], a.last ]
|
150
|
+
end
|
151
|
+
when :merge
|
137
152
|
deep_merge(h[a.first] || {}, a.last)
|
138
|
-
else
|
139
|
-
h[a.first] = a.last
|
153
|
+
else raise ArgumentError
|
140
154
|
end
|
155
|
+
else
|
156
|
+
h[a.first] = a.last
|
157
|
+
end
|
141
158
|
end
|
142
159
|
end
|
143
160
|
|
@@ -149,10 +166,12 @@ require_relative './lexer'
|
|
149
166
|
end
|
150
167
|
|
151
168
|
|
152
|
-
def parse(input)
|
153
|
-
@
|
169
|
+
def parse(input, duplicate_mode = :array)
|
170
|
+
@duplicate_mode = duplicate_mode
|
171
|
+
@lexer = HCL::Checker::Lexer.new.lex(input)
|
154
172
|
do_parse
|
155
|
-
|
173
|
+
|
174
|
+
@result
|
156
175
|
end
|
157
176
|
|
158
177
|
|
data/bin/console
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'hcl/checker'
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +10,5 @@ require "hcl/checker"
|
|
10
10
|
# require "pry"
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
-
require
|
13
|
+
require 'irb'
|
14
14
|
IRB.start(__FILE__)
|
data/hcl-checker.gemspec
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
lib = File.expand_path('
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
3
|
require 'hcl/checker/version'
|
4
4
|
|
@@ -17,36 +17,20 @@ Gem::Specification.new do |spec|
|
|
17
17
|
f.match(%r{^(test|spec|features)/})
|
18
18
|
end
|
19
19
|
spec.require_paths = ['lib']
|
20
|
+
spec.required_ruby_version = '>= 2.5.0'
|
20
21
|
|
21
|
-
spec.add_development_dependency 'bundler', '~> 2.
|
22
|
-
spec.add_development_dependency 'rake', '~> 12.3.3'
|
23
|
-
spec.add_development_dependency 'rspec', '~> 3.0'
|
22
|
+
spec.add_development_dependency 'bundler', '~> 2.3.13'
|
24
23
|
spec.add_development_dependency 'racc', '1.5.0'
|
24
|
+
spec.add_development_dependency 'rake', '~> 12.3.3'
|
25
25
|
spec.add_development_dependency 'rex', '2.0.12'
|
26
26
|
spec.add_development_dependency 'rexical', '>= 1.0.7'
|
27
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
27
28
|
|
28
|
-
spec.post_install_message =
|
29
|
-
Hello,
|
30
|
-
|
31
|
-
In the meantime, it is important that you know that there will be a
|
32
|
-
compatibility break with the current version, for Gem to support both
|
33
|
-
versions.
|
34
|
-
|
35
|
-
Therefore, instead of using just HCL::Checker you must tell which
|
36
|
-
version you are using, like this:
|
37
|
-
|
38
|
-
HCL1::Checker
|
39
|
-
|
40
|
-
Or
|
41
|
-
|
42
|
-
HCL2::Checker
|
43
|
-
|
44
|
-
At the moment both HCL::Checker and HCL1::Checker will work, but with
|
45
|
-
the release of support for version 2 the HCL::Checker syntax will no
|
46
|
-
longer work.
|
29
|
+
spec.post_install_message = '
|
30
|
+
Hello, me again. This version fixes:
|
47
31
|
|
48
|
-
|
32
|
+
- Update dependencies due security issues
|
49
33
|
|
50
34
|
Thank you :)
|
51
|
-
|
35
|
+
'
|
52
36
|
end
|
@@ -4,8 +4,7 @@
|
|
4
4
|
# from lexical definition file "./assets/lexer.rex".
|
5
5
|
#++
|
6
6
|
|
7
|
-
|
8
|
-
class HCLLexer
|
7
|
+
class HCL::Checker::Lexer
|
9
8
|
require 'strscan'
|
10
9
|
|
11
10
|
class ScanError < StandardError ; end
|
@@ -85,16 +84,22 @@ class HCLLexer
|
|
85
84
|
action { [:STRING, consume_heredoc] }
|
86
85
|
|
87
86
|
when (text = @ss.scan(/\{/))
|
88
|
-
action { [:LEFTBRACE,
|
87
|
+
action { [:LEFTBRACE, text]}
|
89
88
|
|
90
89
|
when (text = @ss.scan(/\}/))
|
91
|
-
action { [:RIGHTBRACE,
|
90
|
+
action { [:RIGHTBRACE, text]}
|
92
91
|
|
93
92
|
when (text = @ss.scan(/\[/))
|
94
|
-
action { [:LEFTBRACKET,
|
93
|
+
action { [:LEFTBRACKET, text]}
|
95
94
|
|
96
95
|
when (text = @ss.scan(/\]/))
|
97
|
-
action { [:RIGHTBRACKET,
|
96
|
+
action { [:RIGHTBRACKET, text]}
|
97
|
+
|
98
|
+
when (text = @ss.scan(/\(/))
|
99
|
+
action { [:LEFTPARENTHESES, text]}
|
100
|
+
|
101
|
+
when (text = @ss.scan(/\)/))
|
102
|
+
action { [:RIGHTPARENTHESES, text]}
|
98
103
|
|
99
104
|
when (text = @ss.scan(/\,/))
|
100
105
|
action { [:COMMA, text]}
|
@@ -129,13 +134,14 @@ class HCLLexer
|
|
129
134
|
tokens
|
130
135
|
end
|
131
136
|
def to_boolean(input)
|
132
|
-
input
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
137
|
+
case input
|
138
|
+
when /true/
|
139
|
+
true
|
140
|
+
when /false/
|
141
|
+
false
|
142
|
+
else
|
143
|
+
raise "Invalid value for `to_boolean`, expected true/false got #{input}"
|
144
|
+
end
|
139
145
|
end
|
140
146
|
def consume_comment(input)
|
141
147
|
nested = 1
|
@@ -153,18 +159,19 @@ class HCLLexer
|
|
153
159
|
def consume_string(input)
|
154
160
|
result = ''
|
155
161
|
nested = 0
|
156
|
-
|
162
|
+
loop do
|
157
163
|
case(text = @ss.scan_until(%r{\"|\$\{|\}|\\}))
|
158
164
|
when %r{\$\{\z}
|
159
165
|
nested += 1
|
160
166
|
when %r{\}\z}
|
161
|
-
nested -= 1 if nested
|
167
|
+
nested -= 1 if nested.positive?
|
162
168
|
when %r{\\\z}
|
163
169
|
result += text.chop + @ss.getch
|
164
170
|
next
|
165
171
|
end
|
166
172
|
result += text.to_s
|
167
|
-
|
173
|
+
break if nested.zero? && text =~ %r{\"\z}
|
174
|
+
end
|
168
175
|
result.chop
|
169
176
|
end
|
170
177
|
def consume_heredoc
|