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
|
-- KDL LPeg lexer for vis.
-- Covers: // and /* */ comments, slashdash /-, quoted and raw strings,
-- type annotations (type), keywords, numbers, node/property identifiers.
local lexer = lexer
local P, S = lpeg.P, lpeg.S
local lex = lexer.new(..., {fold_by_indentation = true})
-- Comments.
local line_comment = lexer.to_eol('//')
local block_comment = lexer.range('/*', '*/', false, false, true)
lex:add_rule('comment', lex:tag(lexer.COMMENT, line_comment + block_comment))
-- Slashdash node suppression.
lex:add_rule('slashdash', lex:tag(lexer.OPERATOR, P('/-')))
-- Keywords.
lex:add_rule('keyword', lex:tag(lexer.KEYWORD, lexer.word_match({'true', 'false', 'null'})))
-- Strings: raw #"..."# first so the hash prefixes are not split off,
-- then regular "..." strings.
local raw_str = lexer.range(P('#')^1 * '"', '"' * P('#')^1)
local dq_str = lexer.range('"')
lex:add_rule('string', lex:tag(lexer.STRING, raw_str + dq_str))
-- Type annotations like (path)file or (const).
local type_ann = P('(') * lexer.word * P(')')
lex:add_rule('type', lex:tag(lexer.TYPE, type_ann))
-- Numbers (int/float/hex/oct/bin; underscores are tolerated inside).
local num_pattern =
(lexer.number *
(S('_')^0 * lexer.number)^0) +
'0x' * (lpeg.R('09') + lpeg.R('af') + lpeg.R('AF') + '_')^1 +
'0o' * lpeg.R('07')^1 +
'0b' * lpeg.R('01')^1
lex:add_rule('number', lex:tag(lexer.NUMBER, num_pattern))
-- Identifiers (node names, property keys).
lex:add_rule('identifier', lex:tag(lexer.IDENTIFIER, lexer.word))
-- Operators / punctuation.
lex:add_rule('operator', lex:tag(lexer.OPERATOR, S('{}()=;,/+\\')))
lexer.property['scintillua.comment'] = '//'
return lex
|