~ecs/hare.lua

ref: b1c56f3b86e9b24b73b7536062094d85c5b8c17d hare.lua/hare.lua -rw-r--r-- 2.3 KiB
b1c56f3bSebastian vaargs updates 9 months ago
                                                                                
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
-- ? LPeg lexer.

local l = require('lexer')
local token, word_match = l.token, l.word_match
local P, R, S = lpeg.P, lpeg.R, lpeg.S

local M = {_NAME = 'hare'}

local builtin = token(l.FUNCTION, word_match{
	'len', 'offset', 'free', 'alloc', 'assert', 'append', 'insert',
	'abort', 'delete', 'vastart', 'vaarg', 'vaend',
})

local comment = token(l.COMMENT, '//' * l.nonnewline_esc^0)

local constant = token(l.CONSTANT, word_match{
	'true', 'false',
})

local identifier = token(l.IDENTIFIER, l.word)

local keyword = token(l.KEYWORD, word_match{
	'let', 'const', 'fn', 'def', 'static', 'export', 'defer', 'for',
	'return', 'break', 'continue', 'if', 'else', 'match', 'switch',
	'type', 'yield', 'case',
})

local operator = token(l.OPERATOR, word_match{
	'is', 'as', "..", "...",
} + S('+-/*%<>~!=^&|?~:;,.()[]{}'))

local hex_digit = R("09") + R("af") + R("AF")
local integer_suffix = word_match{
	"i", "u", "z", "i8", "i16", "i32", "i64", "u8", "u16", "u32",
	"u64",
}
local integer_constant = (P("0x") * hex_digit^1
	+ P("0o") * R("07")^1
	+ P("0b") * R("01")^1
	+ R("09")^1) * integer_suffix^-1
local number = token(l.NUMBER, integer_constant)

local preproc = token(l.PREPROCESSOR,
	l.starts_line('use ') * l.nonnewline_esc^0 * lpeg.B(';')
	+ '@' * R("az")^1)

local named_escape = P('\\0') + '\\a' + '\\b' + '\\f' + '\\n' + '\\r' + '\\v' + '\\\\' + '\\\'' + '\\"'
local escape_sequence = named_escape
	+ '\\x' * hex_digit * hex_digit
	+ '\\u' * hex_digit * hex_digit * hex_digit * hex_digit
local rune = escape_sequence + l.nonnewline_esc-S("\\'")
local string_char = escape_sequence + l.nonnewline_esc-S('\\"')
local string = token(l.STRING, "'" * rune * "'" + '"' * string_char^0 * '"')

-- TODO: highlight size correctly both as keyword and type
local type = token(l.TYPE, word_match{
	'u8', 'u16', 'u32', 'u64', 'i8', 'i16', 'i32', 'i64', 'uint',
	'int', 'uintptr', 'size', 'f32', 'f64', 'bool', 'char', 'rune',
	'str', 'void', 'struct', 'union', 'enum', 'nullable', 'null',
	'valist',
})

local ws = token(l.WHITESPACE, l.space^1)

M._rules = {
	{'builtin', builtin},
	{'constant', constant},
	{'comment', comment},
	{'keyword', keyword},
	{'number', number},
	{'operator', operator},
	{'preproc', preproc},
	{'string', string},
	{'type', type},
	{'whitespace', ws},

	{'identifier', identifier},
}

return M