164 lines
3.7 KiB
Ruby
164 lines
3.7 KiB
Ruby
# -*- coding: utf-8 -*- #
|
|
# frozen_string_literal: true
|
|
|
|
module Rouge
|
|
module Lexers
|
|
class Hcl < RegexLexer
|
|
tag 'hcl'
|
|
|
|
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/"/, 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, :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
|