module Rouge module Lexers class Bicep < Rouge::RegexLexer tag 'bicep' filenames '*.bicep' title "Bicep" desc 'Bicep is a domain-specific language (DSL) that uses declarative syntax to deploy Azure resources.' def self.keywords @keywords ||= Set.new %w( as assert existing extends extension false for from func if import in metadata module none null output param provider resource targetScope test true type using var void with ) end def self.datatypes @datatypes ||= Set.new %w(array bool int object string) end def self.functions @functions ||= Set.new %w( array base64 base64ToJson base64ToString bool cidrHost cidrSubnet concat contains dataUri dataUriToString dateTimeAdd dateTimeFromEpoch dateTimeToEpoch deployer deployment empty endsWith environment extensionResourceId fail filter first flatten format getSecret groupBy guid indexOf int intersection items join json last lastIndexOf length list* listAccountSas listKeys listSecrets loadFileAsBase64 loadJsonContent loadTextContent loadYamlContent managementGroup managementGroupResourceId map mapValue max min newGuid objectKeys padLeft parseCidr pickZones range readEnvironmentVariable reduce reference replace resourceGroup resourceId shallowMerge skip sort split startsWith string subscription subscriptionResourceId substring take tenant tenantResourceId toLogicalZone toLower toObject toPhysicalZone toUpper trim union uniqueString uri uriComponent uriComponentToString utcNow ) end operators = %w(+ - * / % < <= > >= == != =~ !~ && || ! ?? ... .?) punctuations = %w(( ) { } [ ] , : ; = .) state :root do mixin :comments # Match strings rule %r/'/, Str::Single, :string # Match numbers rule %r/\b\d+\b/, Num # Rules for sets of reserved keywords rule %r/\b\w+\b/ do |m| if self.class.keywords.include? m[0] token Keyword elsif self.class.datatypes.include? m[0] token Keyword::Type elsif self.class.functions.include? m[0] token Name::Function else token Name end end # Match operators rule %r/#{operators.map { |o| Regexp.escape(o) }.join('|')}/, Operator # Enter a state when encountering an opening curly bracket rule %r/{/, Punctuation::Indicator, :block # Match punctuation rule %r/#{punctuations.map { |p| Regexp.escape(p) }.join('|')}/, Punctuation # Match identifiers rule %r/[a-zA-Z_]\w*/, Name # Match decorators rule %r/@[a-zA-Z_]\w*/, Name::Decorator # Ignore whitespace rule %r/\s+/, Text end state :comments do rule %r(//[^\n\r]+), Comment::Single rule %r(/\*.*?\*/)m, Comment::Multiline end state :string do rule %r/[^'$}]+/, Str::Single rule %r/\$(?!\{)/, Str::Single rule %r/\$[\{]/, Str::Interpol, :interp rule %r/\'/, Str::Single, :pop! rule %r/\$+/, Str::Single end state :interp do rule %r/\}/, Str::Interpol, :pop! mixin :root end # State for matching code blocks between curly brackets state :block do # Match property names rule %r/\b([a-zA-Z_]\w*)\b(?=\s*:)/, Name::Property # Match closing curly brackets rule %r/}/, Punctuation::Indicator, :pop! # Include the root state for nested tokens mixin :root end end end end