1 -- Copyright 2006-2015 Mitchell mitchell.att.foicica.com. See LICENSE.
3 -- Heavily modified by Brian Schott (@Hackerpilot on Github).
5 local l
= require('lexer')
6 local token
, word_match
= l
.token
, l
.word_match
7 local P
, R
, S
= lpeg
.P
, lpeg
.R
, lpeg
.S
9 local M
= {_NAME
= 'dmd'}
12 local ws
= token(l
.WHITESPACE
, l
.space^
1)
15 local line_comment
= '//' * l
.nonnewline_esc^
0
16 local block_comment
= '/*' * (l
.any
- '*/')^
0 * P('*/')^
-1
17 local nested_comment
= l
.nested_pair('/+', '+/')
18 local comment
= token(l
.COMMENT
, line_comment
+ block_comment
+ nested_comment
)
21 local sq_str
= l
.delimited_range("'", true) * S('cwd')^
-1
22 local dq_str
= l
.delimited_range('"') * S('cwd')^
-1
23 local lit_str
= 'r' * l
.delimited_range('"', false, true) * S('cwd')^
-1
24 local bt_str
= l
.delimited_range('`', false, true) * S('cwd')^
-1
25 local hex_str
= 'x' * l
.delimited_range('"') * S('cwd')^
-1
26 local other_hex_str
= '\\x' * (l
.xdigit
* l
.xdigit
)^
1
27 local del_str
= l
.nested_pair('q"[', ']"') * S('cwd')^
-1 +
28 l
.nested_pair('q"(', ')"') * S('cwd')^
-1 +
29 l
.nested_pair('q"{', '}"') * S('cwd')^
-1 +
30 l
.nested_pair('q"<', '>"') * S('cwd')^
-1 +
31 P('q') * l
.nested_pair('{', '}') * S('cwd')^
-1
32 local string = token(l
.STRING
, del_str
+ sq_str
+ dq_str
+ lit_str
+ bt_str
+
33 hex_str
+ other_hex_str
)
36 local dec
= l
.digit^
1 * ('_' * l
.digit^
1)^
0
37 local hex_num
= l
.hex_num
* ('_' * l
.xdigit^
1)^
0
38 local bin_num
= '0' * S('bB') * S('01_')^
1
39 local oct_num
= '0' * S('01234567_')^
1
40 local integer
= S('+-')^
-1 * (hex_num
+ oct_num
+ bin_num
+ dec
)
41 local number = token(l
.NUMBER
, (l
.float
+ integer
) * S('uUlLdDfFi')^
-1)
44 local keyword
= token(l
.KEYWORD
, word_match
{
45 'abstract', 'align', 'asm', 'assert', 'auto', 'body', 'break', 'case', 'cast',
46 'catch', 'const', 'continue', 'debug', 'default', 'delete',
47 'deprecated', 'do', 'else', 'extern', 'export', 'false', 'final', 'finally',
48 'for', 'foreach', 'foreach_reverse', 'goto', 'if', 'import', 'immutable',
49 'in', 'inout', 'invariant', 'is', 'lazy', 'macro', 'mixin', 'new', 'nothrow',
50 'null', 'out', 'override', 'pragma', 'private', 'protected', 'public', 'pure',
51 'ref', 'return', 'scope', 'shared', 'static', 'super', 'switch',
52 'synchronized', 'this', 'throw','true', 'try', 'typeid', 'typeof', 'unittest',
53 'version', 'virtual', 'volatile', 'while', 'with', '__gshared', '__thread',
54 '__traits', '__vector', '__parameters'
58 local type = token(l
.TYPE
, word_match
{
59 'alias', 'bool', 'byte', 'cdouble', 'cent', 'cfloat', 'char', 'class',
60 'creal', 'dchar', 'delegate', 'double', 'enum', 'float', 'function',
61 'idouble', 'ifloat', 'int', 'interface', 'ireal', 'long', 'module', 'package',
62 'ptrdiff_t', 'real', 'short', 'size_t', 'struct', 'template', 'typedef',
63 'ubyte', 'ucent', 'uint', 'ulong', 'union', 'ushort', 'void', 'wchar',
64 'string', 'wstring', 'dstring', 'hash_t', 'equals_t'
68 local constant
= token(l
.CONSTANT
, word_match
{
69 '__FILE__', '__LINE__', '__DATE__', '__EOF__', '__TIME__', '__TIMESTAMP__',
70 '__VENDOR__', '__VERSION__', '__FUNCTION__', '__PRETTY_FUNCTION__',
74 local class_sequence
= token(l
.TYPE
, P('class') + P('struct')) * ws^
1 *
75 token(l
.CLASS
, l
.word
)
78 local identifier
= token(l
.IDENTIFIER
, l
.word
)
81 local operator
= token(l
.OPERATOR
, S('?=!<>+-*$/%&|^~.,;()[]{}'))
84 local properties
= (type + identifier
+ operator
) * token(l
.OPERATOR
, '.') *
85 token(l
.VARIABLE
, word_match
{
86 'alignof', 'dig', 'dup', 'epsilon', 'idup', 'im', 'init', 'infinity',
87 'keys', 'length', 'mangleof', 'mant_dig', 'max', 'max_10_exp', 'max_exp',
88 'min', 'min_normal', 'min_10_exp', 'min_exp', 'nan', 'offsetof', 'ptr',
89 're', 'rehash', 'reverse', 'sizeof', 'sort', 'stringof', 'tupleof',
94 local annotation
= token('annotation', '@' * l
.word^
1)
95 local preproc
= token(l
.PREPROCESSOR
, '#' * l
.nonnewline^
0)
98 local traits_list
= token('traits', word_match
{
99 'allMembers', 'classInstanceSize', 'compiles', 'derivedMembers',
100 'getAttributes', 'getMember', 'getOverloads', 'getProtection', 'getUnitTests',
101 'getVirtualFunctions', 'getVirtualIndex', 'getVirtualMethods', 'hasMember',
102 'identifier', 'isAbstractClass', 'isAbstractFunction', 'isArithmetic',
103 'isAssociativeArray', 'isFinalClass', 'isFinalFunction', 'isFloating',
104 'isIntegral', 'isLazy', 'isNested', 'isOut', 'isOverrideFunction', 'isPOD',
105 'isRef', 'isSame', 'isScalar', 'isStaticArray', 'isStaticFunction',
106 'isUnsigned', 'isVirtualFunction', 'isVirtualMethod', 'parent'
109 local scopes_list
= token('scopes', word_match
{'exit', 'success', 'failure'})
112 local versions_list
= token('versions', word_match
{
113 'AArch64', 'AIX', 'all', 'Alpha', 'Alpha_HardFloat', 'Alpha_SoftFloat',
114 'Android', 'ARM', 'ARM_HardFloat', 'ARM_SoftFloat', 'ARM_SoftFP', 'ARM_Thumb',
115 'assert', 'BigEndian', 'BSD', 'Cygwin', 'D_Coverage', 'D_Ddoc', 'D_HardFloat',
116 'DigitalMars', 'D_InlineAsm_X86', 'D_InlineAsm_X86_64', 'D_LP64',
117 'D_NoBoundsChecks', 'D_PIC', 'DragonFlyBSD', 'D_SIMD', 'D_SoftFloat',
118 'D_Version2', 'D_X32', 'FreeBSD', 'GNU', 'Haiku', 'HPPA', 'HPPA64', 'Hurd',
119 'IA64', 'LDC', 'linux', 'LittleEndian', 'MIPS32', 'MIPS64', 'MIPS_EABI',
120 'MIPS_HardFloat', 'MIPS_N32', 'MIPS_N64', 'MIPS_O32', 'MIPS_O64',
121 'MIPS_SoftFloat', 'NetBSD', 'none', 'OpenBSD', 'OSX', 'Posix', 'PPC', 'PPC64',
122 'PPC_HardFloat', 'PPC_SoftFloat', 'S390', 'S390X', 'SDC', 'SH', 'SH64',
123 'SkyOS', 'Solaris', 'SPARC', 'SPARC64', 'SPARC_HardFloat', 'SPARC_SoftFloat',
124 'SPARC_V8Plus', 'SysV3', 'SysV4', 'unittest', 'Win32', 'Win64', 'Windows',
128 local versions
= token(l
.KEYWORD
, 'version') * l
.space^
0 *
129 token(l
.OPERATOR
, '(') * l
.space^
0 * versions_list
131 local scopes
= token(l
.KEYWORD
, 'scope') * l
.space^
0 *
132 token(l
.OPERATOR
, '(') * l
.space^
0 * scopes_list
134 local traits
= token(l
.KEYWORD
, '__traits') * l
.space^
0 *
135 token(l
.OPERATOR
, '(') * l
.space^
0 * traits_list
137 local func
= token(l
.FUNCTION
, l
.word
) *
138 #(l
.space^
0 * (P('!') * l
.word^
-1 * l
.space^
-1)^
-1 * P('('))
142 {'class', class_sequence
},
144 {'versions', versions
},
146 {'keyword', keyword
},
147 {'variable', properties
},
150 {'constant', constant
},
152 {'identifier', identifier
},
153 {'comment', comment
},
155 {'preproc', preproc
},
156 {'operator', operator
},
157 {'annotation', annotation
},
161 annotation
= l
.STYLE_PREPROCESSOR
,
162 traits
= l
.STYLE_CLASS
,
163 versions
= l
.STYLE_CONSTANT
,
164 scopes
= l
.STYLE_CONSTANT
168 _patterns
= {'[{}]', '/[*+]', '[*+]/', '//'},
169 [l
.OPERATOR
] = {['{'] = 1, ['}'] = -1},
171 ['/*'] = 1, ['*/'] = -1, ['/+'] = 1, ['+/'] = -1,
172 ['//'] = l
.fold_line_comments('//')