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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
# -*- coding: utf-8 -*- #
# frozen_string_literal: true
module Rouge
module Lexers
class Hcl < RegexLexer
tag 'hcl'
filenames '*.hcl', '*.nomad'
title 'Hashicorp Configuration Language'
desc 'Hashicorp Configuration Language, used by Terraform and other Hashicorp tools'
state :multiline_comment do
rule %r([*]/), Comment::Multiline, :pop!
rule %r([^*/]+), Comment::Multiline
rule %r([*/]), Comment::Multiline
end
state :comments_and_whitespace do
rule %r/\s+/, Text
rule %r(//.*?$), Comment::Single
rule %r(#.*?$), Comment::Single
rule %r(/[*]), Comment::Multiline, :multiline_comment
end
state :primitives do
rule %r/[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?([kKmMgG]b?)?/, Num::Float
rule %r/[0-9]+([kKmMgG]b?)?/, Num::Integer
rule %r/[-+*\/!%&<>|=:?]/, Operator
rule %r/"/, Str::Double, :dq
rule %r/'/, Str::Single, :sq
rule %r/(<<-?)(\s*)(\'?)(\\?)(\w+)(\3)/ do |m|
groups Operator, Text, Str::Heredoc, Str::Heredoc, Name::Constant, Str::Heredoc
@heredocstr = Regexp.escape(m[5])
push :heredoc
end
end
def self.keywords
@keywords ||= Set.new %w()
end
def self.declarations
@declarations ||= Set.new %w()
end
def self.reserved
@reserved ||= Set.new %w()
end
def self.constants
@constants ||= Set.new %w(true false null)
end
def self.builtins
@builtins ||= %w()
end
id = /[$a-z_\-][a-z0-9_\-]*/io
state :root do
mixin :comments_and_whitespace
mixin :primitives
rule %r/\{/ do
token Punctuation
push :hash
end
rule %r/\[/ do
token Punctuation
push :array
end
rule id do |m|
if self.class.keywords.include? m[0]
token Keyword
push :composite
elsif self.class.declarations.include? m[0]
token Keyword::Declaration
push :composite
elsif self.class.reserved.include? m[0]
token Keyword::Reserved
elsif self.class.constants.include? m[0]
token Keyword::Constant
elsif self.class.builtins.include? m[0]
token Name::Builtin
else
token Name::Other
push :composite
end
end
end
state :composite do
mixin :comments_and_whitespace
rule %r/[{]/ do
token Punctuation
pop!
push :hash
end
rule %r/[\[]/ do
token Punctuation
pop!
push :array
end
mixin :root
rule %r//, Text, :pop!
end
state :hash do
mixin :comments_and_whitespace
rule %r/[.,()\\\/*]/, Punctuation
rule %r/\=/, Punctuation
rule %r/\}/, Punctuation, :pop!
mixin :root
end
state :array do
mixin :comments_and_whitespace
rule %r/[.,()\\\/*]/, Punctuation
rule %r/\]/, Punctuation, :pop!
mixin :root
end
state :dq do
rule %r/[^\\"]+/, Str::Double
rule %r/\\"/, Str::Escape
rule %r/"/, Str::Double, :pop!
end
state :sq do
rule %r/[^\\']+/, Str::Single
rule %r/\\'/, Str::Escape
rule %r/'/, Str::Single, :pop!
end
state :heredoc do
rule %r/\n/, Str::Heredoc, :heredoc_nl
rule %r/[^$\n]+/, Str::Heredoc
rule %r/[$]/, Str::Heredoc
end
state :heredoc_nl do
rule %r/\s*(\w+)\s*\n/ do |m|
if m[1] == @heredocstr
token Name::Constant
pop! 2
else
token Str::Heredoc
end
end
rule(//) { pop! }
end
end
end
end
|