1 -- Copyright 2017 Murray Calavera. See LICENSE.
4 local l
= require('lexer')
6 local P
, S
= lpeg
.P
, lpeg
.S
8 local function pword(words
)
9 return l
.word_match(words
, "'")
12 local ws
= token(l
.WHITESPACE
, l
.space^
1)
14 local comment_line
= '//' * l
.nonnewline^
0
15 local comment_block
= l
.nested_pair('/*', '*/')
16 local comment
= token(l
.COMMENT
, comment_line
+ comment_block
)
18 local annotation
= token(l
.PREPROCESSOR
, l
.delimited_range('\\', false, true))
20 local lit_bool
= token(l
.CONSTANT
, pword
{'true', 'false'})
22 local lit_str
= token(l
.STRING
,
23 l
.delimited_range('"') -- this covers triple quoted strings
24 + l
.delimited_range("'")
27 local function num(digit
)
28 return digit
* (digit^
0 * P
'_')^
0 * digit^
1 + digit
31 local int
= num(l
.digit
)
32 local frac
= P('.') * int
33 local exp = S('eE') * (P('-') + P('+'))^
-1 * int
35 local lit_num
= token(l
.NUMBER
,
36 P('0x') * num(l
.xdigit
)
37 + P('0b') * num(S('01'))
38 + int
* frac^
-1 * exp^
-1
41 local keyword
= token(l
.KEYWORD
, pword
{
42 'actor', 'as', 'be', 'break', 'class', 'compile_error', 'compile_intrinsic',
43 'continue', 'consume', 'do', 'else', 'elseif', 'embed', 'end', 'error',
44 'for', 'fun', 'if', 'ifdef', 'iftype', 'in', 'interface', 'is', 'isnt',
45 'lambda', 'let', 'match', 'new', 'object', 'primitive', 'recover', 'repeat',
46 'return', 'struct', 'then', 'this', 'trait', 'try', 'type', 'until', 'use',
47 'var', 'where', 'while', 'with'})
48 local capability
= token(l
.LABEL
, pword
{
49 'box', 'iso', 'ref', 'tag', 'trn', 'val'})
50 local qualifier
= token(l
.LABEL
,
51 P
'#' * pword
{'read', 'send', 'share', 'any', 'alias'})
53 local operator
= token(l
.OPERATOR
,
54 pword
{'and', 'or', 'xor', 'not', 'addressof', 'digestof'}
55 + lpeg
.Cmt(S('+-*/%<>=!~')^
1, function(input
, index
, op
)
57 ['+'] = true, ['-'] = true, ['*'] = true, ['/'] = true, ['%'] = true,
58 ['+~'] = true, ['-~'] = true, ['*~'] = true, ['/~'] = true,
59 ['%~'] = true, ['<<'] = true, ['>>'] = true, ['<<~'] = true,
60 ['>>~'] = true, ['=='] = true, ['!='] = true, ['<'] = true,
61 ['<='] = true, ['>='] = true, ['>'] = true, ['==~'] = true,
62 ['!=~'] = true, ['<~'] = true, ['<=~'] = true, ['>=~'] = true,
65 return ops
[op
] and index
or nil
69 -- there is no suitable token name for this, change this if ever one is added
70 local punctuation
= token(l
.OPERATOR
,
71 P
'=>' + P
'.>' + P
'<:' + P
'->'
72 + S('=.,:;()[]{}!?~^&|_@'))
74 -- highlight functions with syntax sugar at declaration
76 = token(l
.KEYWORD
, pword
{'fun', 'new', 'be'}) * ws^
-1
77 * annotation^
-1 * ws^
-1
78 * capability^
-1 * ws^
-1
79 * token(l
.FUNCTION
, pword
{
80 'create', 'dispose', '_final', 'apply', 'update',
81 'add', 'sub', 'mul', 'div', 'mod', 'add_unsafe', 'sub_unsafe',
82 'mul_unsafe', 'div_unsafe', 'mod_unsafe', 'shl', 'shr', 'shl_unsafe',
83 'shr_unsafe', 'op_and', 'op_or', 'op_xor', 'eq', 'ne', 'lt', 'le', 'ge',
84 'gt', 'eq_unsafe', 'ne_unsafe', 'lt_unsafe', 'le_unsafe', 'ge_unsafe',
85 'gt_unsafe', 'neg', 'neg_unsafe', 'op_not',
87 '_serialise_space', '_serialise', '_deserialise'})
89 local id_suffix
= (l
.alnum
+ P("'") + P('_'))^
0
90 local type = token(l
.TYPE
, P('_')^
-1 * l
.upper
* id_suffix
)
91 local identifier
= token(l
.IDENTIFIER
, P('_')^
-1 * l
.lower
* id_suffix
)
92 local tuple_lookup
= token(l
.IDENTIFIER
, P('_') * l
.digit^
1)
94 local M
= {_NAME
= 'pony'}
99 {'annotation', annotation
},
100 {'boolean', lit_bool
},
104 {'keyword', keyword
},
105 {'capability', capability
},
106 {'qualifier', qualifier
},
107 {'operator', operator
},
109 {'identifier', identifier
},
110 {'lookup', tuple_lookup
},
111 {'punctuation', punctuation
}