# module Rouge # module Lexers # class D < RegexLexer # desc 'The D Programming language (http://dlang.org)' # tag 'd' # aliases 'dlang' # filenames '*.d' # # def self.keywords # @keywords ||= %w( # abstract alias align asm assert auto body bool break byte # case cast catch cdouble cent cfloat char class const continue # creal dchar debug default delegate delete deprecated do double # else enum export extern false final finally float for foreach # foreach_reverse function goto idouble if ifloat immutable # import in inout int interface invariant ireal is lazy long # macro mixin module new nothrow null out override package pragma # private protected public pure real ref return scope shared # short static struct super switch synchronized template this # throw true try typedef typeid typeof ubyte ucent uint ulong # union unittest ushort version void volatile wchar while with # __FILE__ __MODULE__ __LINE__ __FUNCTION__ __PRETTY_FUNCTION__ # __gshared __traits __vector __parameters # ) # end # # def self.builtins # @builtins ||= %w( # string wstring dstring size_t ptrdiff_t # __DATE__ __TIME__ __TIMESTAMP__ __VENDOR__ __VERSION__ # ) # end # # id = /[[:alpha:]_]\w*/ # symmetric = { # '[' => ']', # '<' => '>', # '(' => ')', # '{' => '}' # } # # escapes = [ # /\\['"?\\abfnrtv]/, # /\\[0-7]{1,3}/, # /\\x[0-9a-fA-F]{2}/, # /\\u[0-9a-fA-F]{4}/, # /\\U[0-9a-fA-F]{8}/, # /\\&\w+;/, # ] # # symmetric_open = Regexp.new "[#{Regexp.escape(symmetric.keys.join)}]" # # state :basic do # rule /\s+/m, 'Text' # rule %r(//.*$), 'Comment.Single' # rule %r(/[*].*?[*]/), 'Comment.Multiline' # rule %r(/[+]), 'Comment.Multiline', :nested_comment # end # # state :final_quote do # rule /"/, 'Literal.String', :pop! # rule /./, 'Error', :pop! # end # # state :nested_comment do # rule %r([+]/), :pop! # rule %r(/[+]), :nested_comment # rule %r([/+]|[^/+]+), 'Comment.Multiline' # end # # state :root do # rule /r".*?"/, 'Literal.String' # rule /`.*?`/, 'Literal.String' # rule /q"(#{id})\n.*?\n\1"/, 'Literal.String.Heredoc' # rule /q"(#{symmetric_open})/ do |m| # token 'Literal.String' # open = Regexp.escape(m[1]) # close = Regexp.escape(symmetric[m[1]]) # push :final_quote # push do # mixin :escapes # rule /\\[#{open}#{close}]/, 'Literal.String.Escape' # rule(/#{open}/) { token 'Literal.String'; push } # rule(/#{close}/) { token 'Literal.String'; pop! } # rule /[^\\#{open}#{close}]+/, 'Literal.String' # end # end # rule /q"(\S).*?\1"/, 'Literal.String' # # Token strings are going to be lexed like D, because # # they're frigging impossible otherwise. I'll highlight # # the q as a string, though. # rule /q(?=[{])/, 'Literal.String' # rule /x"/, 'Literal.String.Other', :hex_string # rule /"/, 'Literal.String', :dq # rule /'/ do # token 'Literal.String.Char' # push :char_end; push :char # end # # # numbers # rule /0b[01_]+/, 'Literal.Number.Binary' # rule /0x[0-9a-f_]+/i, # rule /\d+[ul]+/i, 'Literal.Number.Integer' # # rule /#{keywords.join('|')}/, 'Keyword' # end # # state :escapes do # escapes.each do |re| # rule re, 'Literal.String.Escape' # end # end # # state :char do # escapes.each do |re| # rule re, 'Literal.String.Char', :pop! # end # # rule /./, 'Literal.String.Char', :pop! # end # # state :hex_string do # rule /[0-9a-f]+/i, 'Literal.Number.Hex' # rule /\s+/m, 'Literal.String.Other' # rule /"/, 'Literal.String.Other', :pop! # end # # state :char_end do # rule /'[cwd]+/, 'Literal.String.Char', :pop! # rule /./, 'Error', :pop! # end # # state :dq do # mixin :escapes # rule /[^\\"]+/, 'Literal.String.Double' # rule /"/ do # token 'Literal.String.Double' # pop!; push :post_string # end # end # # state :post_string do # rule /[cwd]+/, 'Literal.String' # rule(//) { pop! } # end # end # end # end