-
Notifications
You must be signed in to change notification settings - Fork 0
/
rbs.pest
209 lines (173 loc) · 6.89 KB
/
rbs.pest
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
capital_case = {ASCII_ALPHA_UPPER ~ (ASCII_ALPHANUMERIC|"_")*}
string_literal = {"\"" ~ ASCII_ALPHANUMERIC* ~ "\""|"'" ~ ASCII_ALPHANUMERIC* ~ "'"}
symbol_literal = {":" ~ ASCII_ALPHANUMERIC+}
w = _{WHITE_SPACE+}
wo = _{WHITE_SPACE*}
integer_literal = {ASCII_DIGIT+}
lower_case = _{ASCII_ALPHA_LOWER{1} ~ (ASCII_ALPHANUMERIC|"_")*}
namespace = {"::"? ~ capital_case ~ "::"*|"::"}
class_name = {"::"? ~ "_"? ~ (capital_case ~ "::")* ~ capital_case|"::"}
class_with_type = {"::"? ~ "_"? ~ (capital_case ~ "::")* ~ capital_case ~ "[" ~ wo ~ (ruby_types ~ ","? ~ wo)+ ~ wo ~ "]"}
interface_name = {"::"? ~ "_"? ~ capital_case ~ "::"*|"::"}
alias_name = {namespace? ~ lower_case}
type_variable = {"_"? ~ capital_case}
type_arguments = {"[" ~ wo ~ (ruby_types ~ ","? ~ wo)+ ~ wo ~ "]"}
literal = {string_literal|symbol_literal|integer_literal|"true"|"false"}
record_name = {lower_case}
ruby_type = {
"^(" ~ parameters ~ ")" ~ w ~ "->" ~ wo ~ ruby_type
| "self"
| "instance"
| "class"
| "bool"
| "untyped"
| "nil"
| "top"
| "bot"
| "void"
| class_with_type
| class_name
| interface_name ~ type_arguments
| "singleton(" ~ class_name ~ ")"
| literal
| "{" ~ wo ~ (record_name ~ ":" ~ wo ~ ruby_type ~ wo ~ ","? ~ wo)+ ~ wo ~ "}"
| "[" ~ wo ~ "]"
| "[" ~ wo ~ (ruby_types ~ ","? ~ wo)+ ~ wo ~ "]"
| type_variable
| alias_name ~ "?"? ~ w// why is this hear?
}
ruby_types = {
(ruby_type ~ wo ~ "|" ~ wo)+ ~ wo ~ ruby_type
| (ruby_type ~ wo ~ "&" ~ wo)+ ~ ruby_type
| ruby_type ~ "?"
| ruby_type
}
//method types
var_name = {"_"? ~ lower_case}
parameter_prime = {"?"? ~ "*"? ~ (ruby_types ~ w ~ var_name|ruby_types)}
parameter = {
"?"? ~ ("(" ~ parameter_prime ~ ")"|parameter_prime)
}
required_positionals = {(parameter ~ wo ~ "," ~ wo)* ~ wo ~ parameter}
keyword = {lower_case}
keywords = {
((keyword ~ ":" ~ w ~ parameter|"?" ~ keyword ~ ":" ~ w ~ parameter) ~ ","?)* ~ ("**" ~ parameter)*
}
parameters = {
wo ~ (((parameter|keywords) ~ wo ~ "," ~ wo)+ ~ wo ~ (parameter|keywords)|required_positionals|keywords) ~ wo ~ keywords ~ wo
}
// members
ivar_member = {ivar_name ~ ":" ~ ruby_type}
ivar_name = {"@" ~ lower_case}
method_name = {
"`"? ~ ("<=>"|"==="|"[]="|"!~"|"+@"|"-@"|"<<"|">>"|">="|"<="|"[]"|"=~"|"=="|"!="|"**"|"*"|"!"|"%"|"+"|"~"|"-"|"/"|"&"|"^"|"|"|"<"|">") ~ "`"?
| ("`" ~ (ASCII_ALPHA|"_") ~ (ASCII_ALPHANUMERIC|"_")* ~ ("!"|"?"|"=")? ~ "`")
| ((ASCII_ALPHA|"_") ~ (ASCII_ALPHANUMERIC|"_")* ~ ("!"|"?"|"=")?)
| "`"//last if it is a standalone def `:
}
arrow_type = {
wo ~ "->" ~ w ~ ("(" ~ wo ~ params* ~ wo ~ ")"|ruby_type ~ "?"?)
}
p = {((SPACE_SEPARATOR|SEPARATOR|MARK|SYMBOL|NUMBER|LETTER|":"|"_"|":"|"?"|"|"|","|"*"|"["|"]"|"#") ~ NEWLINE* ~ wo)+}
// https://github.com/pest-parser/pest/issues/463#issuecomment-677508586 adapted from here.
value = _{p}
call = {(value|arguments) ~ (arguments)*}
arguments = {"(" ~ (params ~ ("," ~ params)* ~ ","?)? ~ ")"}
params = {call ~ (call)*}
method_type = {
"(" ~ wo ~ ")" ~ arrow_type
| "(" ~ params? ~ ")" ~ wo ~ "?"? ~ "{" ~ wo ~ "(" ~ params? ~ ")" ~ w ~ "->" ~ w ~ "(" ~ wo ~ ruby_types ~ "?"? ~ wo ~ ")" ~ wo ~ "}" ~ arrow_type
| "(" ~ params? ~ ")" ~ wo ~ "?"? ~ "{" ~ wo ~ "(" ~ params? ~ ")" ~ w ~ "->" ~ w ~ ruby_types ~ "?"? ~ wo ~ "}" ~ arrow_type
| "(" ~ params ~ ")" ~ arrow_type
| arrow_type
}
method_types_prime = {
(type_parameters* ~ wo ~ method_type ~ wo ~ "|" ~ wo)* ~ type_parameters* ~ method_type ~ "?"?
}
method_types = {
"super"
| method_types_prime
| arrow_type
}
method_member = {
("incompatible" ~ w)? ~ ("def" ~ w ~ method_name ~ ":" ~ w ~ method_types|"def" ~ w ~ "self." ~ method_name ~ ":" ~ w ~ method_types|"def" ~ w ~ "self?." ~ method_name ~ ":" ~ w ~ method_types)
}
alias_member = {
"alias" ~ w ~ method_name ~ w ~ method_name
| "alias" ~ w ~ "self." ~ method_name ~ w ~ "self." ~ method_name
}
attribute_type = {"attr_reader"|"attr_writer"|"attr_accessor"}
include_member = {
"include" ~ w ~ class_name ~ type_arguments?
| "include" ~ w ~ interface_name ~ type_arguments?
}
extend_member = {
"extend" ~ w ~ class_name ~ type_arguments?
| "extend" ~ w ~ interface_name ~ type_arguments?
}
prepend_member = {
"prepend" ~ w ~ class_name ~ type_arguments?
}
type_parameters = {
wo ~ "[" ~ wo ~ (type_variable ~ wo ~ "," ~ wo)* ~ type_variable ~ wo ~ "]" ~ wo
}
attribute_member = {
attribute_type ~ w ~ method_name ~ ":" ~ w ~ ruby_type ~ "?"?
| attribute_type ~ w ~ method_name ~ wo ~ "(" ~ wo ~ ivar_name ~ wo ~ ")" ~ wo ~ ":" ~ w ~ ruby_type ~ "?"?
| attribute_type ~ w ~ method_name ~ wo ~ "()" ~ wo ~ ":" ~ w ~ ruby_type ~ "?"?
}
member = {
comments* ~ wo ~ (ivar_member|method_member|attribute_member|include_member|extend_member|prepend_member|alias_member|const_decl|class_decl|module_decl|interface_decl|type_alias_decl|"public"|"private")
}
variance = {
("unchecked" ~ w)? ~ ("out"|"in") ~ w
}
module_type_parameter = {
variance? ~ type_variable
}
module_type_parameters = {
"[" ~ (module_type_parameter ~ "," ~ wo)* ~ module_type_parameter ~ "]"
}
const_name = {
"::"? ~ (ASCII_ALPHA|"_"|"::")+
}
global_name = {"$" ~ ASCII_ALPHA}
global_decl = {global_name ~ ":" ~ w ~ ruby_type}
extension_decl = {
"extension" ~ w ~ class_name ~ type_parameters ~ "(" ~ capital_case ~ ")" ~ member+ ~ "end"
}
type_alias_decl = {
"type" ~ w ~ alias_name ~ wo ~ "=" ~ w ~ ruby_types
}
const_decl = {
const_name ~ ":" ~ w ~ ruby_type
}
decl = {
comments* ~ (class_decl|module_decl|interface_decl|extension_decl|type_alias_decl|const_decl|global_decl)
}
class_decl = {
"class" ~ w ~ class_name ~ module_type_parameters* ~ NEWLINE+ ~ (member ~ NEWLINE*)* ~ NEWLINE* ~ wo ~ "end"
| "class" ~ w ~ class_name ~ module_type_parameters* ~ w ~ "<" ~ w ~ class_name ~ type_arguments? ~ NEWLINE+ ~ (member ~ NEWLINE*)* ~ NEWLINE* ~ wo ~ "end"
}
module_name = {
"::"? ~ "_"? ~ (capital_case ~ "::")* ~ capital_case
| "::"
}
module_decl = {
"module" ~ w ~ module_name ~ module_type_parameters* ~ NEWLINE+ ~ (member ~ NEWLINE*)* ~ NEWLINE* ~ wo ~ "end"
| "module" ~ w ~ module_name ~ module_type_parameters* ~ wo ~ ":" ~ wo ~ module_self_types ~ NEWLINE+ ~ (member ~ NEWLINE*)* ~ NEWLINE* ~ wo ~ "end"
}
module_self_types = {
(class_with_type|class_name) ~ "," ~ module_self_types
| interface_name ~ type_arguments? ~ "," ~ module_self_types
| (class_with_type|class_name)
}
interface_decl = {
"interface" ~ w ~ interface_name ~ module_type_parameters* ~ NEWLINE+ ~ (wo ~ interface_members ~ NEWLINE*)* ~ NEWLINE* ~ wo ~ "end"
}
interface_members = {
comments* ~ wo ~ (method_member|include_member|alias_member)
}
no_newline = _{SPACE_SEPARATOR|MARK|SYMBOL|PUNCTUATION|NUMBER|LETTER}
comment = {wo ~ "#" ~ no_newline*}
comments = {(comment ~ NEWLINE)+}