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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
--[[!
LPEG grammar for LuaCATS
Currently only partially supports:
- @param
- @return
]]
local lpeg = vim.lpeg
local P, R, S = lpeg.P, lpeg.R, lpeg.S
local Ct, Cg = lpeg.Ct, lpeg.Cg
--- @param x vim.lpeg.Pattern
local function rep(x)
return x ^ 0
end
--- @param x vim.lpeg.Pattern
local function rep1(x)
return x ^ 1
end
--- @param x vim.lpeg.Pattern
local function opt(x)
return x ^ -1
end
local nl = P('\r\n') + P('\n')
local ws = rep1(S(' \t') + nl)
local fill = opt(ws)
local any = P(1) -- (consume one character)
local letter = R('az', 'AZ') + S('_$')
local num = R('09')
local ident = letter * rep(letter + num + S '-.')
local string_single = P "'" * rep(any - P "'") * P "'"
local string_double = P '"' * rep(any - P '"') * P '"'
local literal = (string_single + string_double + (opt(P '-') * num) + P 'false' + P 'true')
local lname = (ident + P '...') * opt(P '?')
--- @param x string
local function Pf(x)
return fill * P(x) * fill
end
--- @param x string
local function Sf(x)
return fill * S(x) * fill
end
--- @param x vim.lpeg.Pattern
local function comma(x)
return x * rep(Pf ',' * x)
end
--- @param x vim.lpeg.Pattern
local function parenOpt(x)
return (Pf('(') * x ^ -1 * fill * P(')')) + x ^ -1
end
--- @type table<string,vim.lpeg.Pattern>
local v = setmetatable({}, {
__index = function(_, k)
return lpeg.V(k)
end,
})
local desc_delim = Sf '#:' + ws
--- @class luacats.Param
--- @field kind 'param'
--- @field name string
--- @field type string
--- @field desc? string
--- @class luacats.Return
--- @field kind 'return'
--- @field [integer] { type: string, name?: string}
--- @field desc? string
--- @class luacats.Generic
--- @field kind 'generic'
--- @field name string
--- @field type? string
--- @alias luacats.grammar.result
--- | luacats.Param
--- | luacats.Return
--- | luacats.Generic
--- @class luacats.grammar
--- @field match fun(self, input: string): luacats.grammar.result?
local grammar = P {
rep1(P('@') * v.ats),
ats = (v.at_param + v.at_return + v.at_generic),
at_param = Ct(
Cg(P('param'), 'kind')
* ws
* Cg(lname, 'name')
* ws
* Cg(v.ltype, 'type')
* opt(desc_delim * Cg(rep(any), 'desc'))
),
at_return = Ct(
Cg(P('return'), 'kind')
* ws
* parenOpt(comma(Ct(Cg(v.ltype, 'type') * opt(ws * Cg(ident, 'name')))))
* opt(desc_delim * Cg(rep(any), 'desc'))
),
at_generic = Ct(
Cg(P('generic'), 'kind') * ws * Cg(ident, 'name') * opt(Pf ':' * Cg(v.ltype, 'type'))
),
ltype = v.ty_union + Pf '(' * v.ty_union * fill * P ')',
ty_union = v.ty_opt * rep(Pf '|' * v.ty_opt),
ty = v.ty_fun + ident + v.ty_table + literal,
ty_param = Pf '<' * comma(v.ltype) * fill * P '>',
ty_opt = v.ty * opt(v.ty_param) * opt(P '[]') * opt(P '?'),
table_key = (Pf '[' * literal * Pf ']') + lname,
table_elem = v.table_key * Pf ':' * v.ltype,
ty_table = Pf '{' * comma(v.table_elem) * Pf '}',
fun_param = lname * opt(Pf ':' * v.ltype),
ty_fun = Pf 'fun(' * rep(comma(v.fun_param)) * fill * P ')' * opt(Pf ':' * v.ltype),
}
return grammar --[[@as luacats.grammar]]
|