1pub mod element_type;
5
6use crate::{
7 language::JasmLanguage,
8 lexer::{JasmLexer, token_type::JasmTokenType},
9 parser::element_type::JasmElementType,
10};
11use oak_core::{
12 parser::{ParseCache, ParseOutput, Parser, ParserState, parse_with_lexer},
13 source::{Source, TextEdit},
14};
15
16pub(crate) type State<'a, S> = ParserState<'a, JasmLanguage, S>;
17
18pub struct JasmParser<'config> {
20 pub config: &'config JasmLanguage,
22}
23
24impl<'config> JasmParser<'config> {
25 pub fn new(config: &'config JasmLanguage) -> Self {
27 Self { config }
28 }
29
30 fn skip_trivia<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
31 while state.not_at_end() && (state.at(JasmTokenType::Whitespace) || state.at(JasmTokenType::Newline) || state.at(JasmTokenType::Comment)) {
32 state.bump();
33 }
34 }
35
36 fn parse_class<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
37 let cp = state.checkpoint();
38
39 while state.not_at_end()
41 && matches!(
42 state.current().map(|t| t.kind),
43 Some(JasmTokenType::Public)
44 | Some(JasmTokenType::Private)
45 | Some(JasmTokenType::Protected)
46 | Some(JasmTokenType::Static)
47 | Some(JasmTokenType::Final)
48 | Some(JasmTokenType::Abstract)
49 | Some(JasmTokenType::Synthetic)
50 | Some(JasmTokenType::Deprecated)
51 )
52 {
53 state.bump();
54 self.skip_trivia(state);
55 }
56
57 if !state.at(JasmTokenType::ClassKw) {
59 while state.not_at_end() && !state.at(JasmTokenType::ClassKw) {
60 state.advance();
61 }
62 }
63
64 state.expect(JasmTokenType::ClassKw).ok();
65 self.skip_trivia(state);
66
67 if state.at(JasmTokenType::Identifier) {
69 state.bump();
70 }
71 else {
72 while state.not_at_end() && !state.at(JasmTokenType::Identifier) && !state.at(JasmTokenType::ExtendsKw) && !state.at(JasmTokenType::ImplementsKw) && !state.at(JasmTokenType::LeftBrace) {
74 state.advance();
75 }
76 }
77 self.skip_trivia(state);
78
79 if state.at(JasmTokenType::ExtendsKw) {
81 state.bump();
82 self.skip_trivia(state);
83 if state.at(JasmTokenType::Identifier) {
84 state.bump();
85 }
86 else {
87 while state.not_at_end() && !state.at(JasmTokenType::Identifier) && !state.at(JasmTokenType::ImplementsKw) && !state.at(JasmTokenType::LeftBrace) {
89 state.advance();
90 }
91 }
92 self.skip_trivia(state);
93 }
94
95 if state.at(JasmTokenType::ImplementsKw) {
97 state.bump();
98 self.skip_trivia(state);
99 while state.not_at_end() && !state.at(JasmTokenType::LeftBrace) {
101 if state.at(JasmTokenType::Identifier) {
102 state.bump();
103 self.skip_trivia(state);
104 if state.at(JasmTokenType::Comma) {
105 state.bump();
106 self.skip_trivia(state);
107 }
108 else {
109 break;
110 }
111 }
112 else {
113 while state.not_at_end() && !state.at(JasmTokenType::Identifier) && !state.at(JasmTokenType::LeftBrace) {
115 state.advance();
116 }
117 }
118 }
119 }
120
121 if state.eat(JasmTokenType::LeftBrace) {
122 while state.not_at_end() && !state.at(JasmTokenType::RightBrace) {
123 self.skip_trivia(state);
124 if state.not_at_end() && !state.at(JasmTokenType::RightBrace) {
125 if state.at(JasmTokenType::MethodKw)
126 || matches!(
127 state.current().map(|t| t.kind),
128 Some(JasmTokenType::Public)
129 | Some(JasmTokenType::Private)
130 | Some(JasmTokenType::Protected)
131 | Some(JasmTokenType::Static)
132 | Some(JasmTokenType::Final)
133 | Some(JasmTokenType::Abstract)
134 | Some(JasmTokenType::Synthetic)
135 | Some(JasmTokenType::Deprecated)
136 )
137 {
138 let mut lookahead = 0;
143 let mut is_method = false;
144 while let Some(t) = state.peek_at(lookahead) {
145 if t.kind == JasmTokenType::MethodKw {
146 is_method = true;
147 break;
148 }
149 if t.kind == JasmTokenType::Newline || t.kind == JasmTokenType::Semicolon || t.kind == JasmTokenType::LeftBrace {
150 break;
151 }
152 lookahead += 1;
153 }
154
155 if is_method {
156 self.parse_method(state);
157 }
158 else {
159 self.parse_field(state);
160 }
161 }
162 else if state.at(JasmTokenType::FieldKw) {
163 self.parse_field(state);
164 }
165 else if state.at(JasmTokenType::MethodKw) {
166 self.parse_method(state);
167 }
168 else {
169 state.advance();
171 }
172 }
173 self.skip_trivia(state);
174 }
175 state.eat(JasmTokenType::RightBrace);
176 }
177
178 state.finish_at(cp, JasmElementType::Class);
179 }
180
181 fn parse_field<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
182 let cp = state.checkpoint();
183
184 while state.not_at_end()
186 && matches!(
187 state.current().map(|t| t.kind),
188 Some(JasmTokenType::Public) | Some(JasmTokenType::Private) | Some(JasmTokenType::Protected) | Some(JasmTokenType::Static) | Some(JasmTokenType::Final) | Some(JasmTokenType::Synthetic) | Some(JasmTokenType::Deprecated)
189 )
190 {
191 state.bump();
192 self.skip_trivia(state);
193 }
194
195 if !state.at(JasmTokenType::FieldKw) {
197 while state.not_at_end() && !state.at(JasmTokenType::FieldKw) && !state.at(JasmTokenType::MethodKw) && !state.at(JasmTokenType::RightBrace) {
198 state.advance();
199 }
200 }
201
202 state.expect(JasmTokenType::FieldKw).ok();
203 self.skip_trivia(state);
204
205 if state.at(JasmTokenType::Identifier) {
207 state.bump();
208 }
209 else {
210 while state.not_at_end() && !state.at(JasmTokenType::Identifier) && !state.at(JasmTokenType::String) && !state.at(JasmTokenType::Newline) && !state.at(JasmTokenType::Semicolon) {
212 state.advance();
213 }
214 }
215 self.skip_trivia(state);
216
217 if state.at(JasmTokenType::Identifier) || state.at(JasmTokenType::String) {
219 state.bump();
220 }
221
222 while state.not_at_end() && !state.at(JasmTokenType::Newline) && !state.at(JasmTokenType::Semicolon) {
224 state.bump();
225 }
226 state.eat(JasmTokenType::Semicolon);
227 state.finish_at(cp, JasmElementType::Field);
228 }
229
230 fn parse_method<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
231 let cp = state.checkpoint();
232
233 while state.not_at_end()
235 && matches!(
236 state.current().map(|t| t.kind),
237 Some(JasmTokenType::Public)
238 | Some(JasmTokenType::Private)
239 | Some(JasmTokenType::Protected)
240 | Some(JasmTokenType::Static)
241 | Some(JasmTokenType::Final)
242 | Some(JasmTokenType::Abstract)
243 | Some(JasmTokenType::Native)
244 | Some(JasmTokenType::Synchronized)
245 | Some(JasmTokenType::Synthetic)
246 | Some(JasmTokenType::Deprecated)
247 | Some(JasmTokenType::Varargs)
248 )
249 {
250 state.bump();
251 self.skip_trivia(state);
252 }
253
254 if !state.at(JasmTokenType::MethodKw) {
256 while state.not_at_end() && !state.at(JasmTokenType::MethodKw) && !state.at(JasmTokenType::FieldKw) && !state.at(JasmTokenType::RightBrace) {
257 state.advance();
258 }
259 }
260
261 state.expect(JasmTokenType::MethodKw).ok();
262 self.skip_trivia(state);
263
264 if state.at(JasmTokenType::Identifier) {
266 state.bump();
267 }
268 else {
269 while state.not_at_end() && !state.at(JasmTokenType::Identifier) && !state.at(JasmTokenType::String) && !state.at(JasmTokenType::LeftBrace) {
271 state.advance();
272 }
273 }
274 self.skip_trivia(state);
275
276 if state.at(JasmTokenType::Identifier) || state.at(JasmTokenType::String) {
278 state.bump();
279 }
280 self.skip_trivia(state);
281
282 if state.eat(JasmTokenType::LeftBrace) {
283 while state.not_at_end() && !state.at(JasmTokenType::RightBrace) {
284 self.skip_trivia(state);
285 if !state.not_at_end() || state.at(JasmTokenType::RightBrace) {
286 break;
287 }
288
289 if state.at(JasmTokenType::StackKw) || state.at(JasmTokenType::LocalsKw) {
290 state.bump();
291 self.skip_trivia(state);
292 if state.at(JasmTokenType::Number) {
293 state.bump();
294 }
295 continue;
296 }
297
298 let inst_cp = state.checkpoint();
299
300 while state.not_at_end() && !state.at(JasmTokenType::Newline) && !state.at(JasmTokenType::RightBrace) {
302 state.bump();
303 }
304
305 state.finish_at(inst_cp, JasmElementType::Instruction);
306 self.skip_trivia(state);
307 }
308 state.eat(JasmTokenType::RightBrace);
309 }
310
311 state.finish_at(cp, JasmElementType::Method);
312 }
313}
314
315impl<'config> Parser<JasmLanguage> for JasmParser<'config> {
316 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<JasmLanguage>) -> ParseOutput<'a, JasmLanguage> {
317 let lexer = JasmLexer::new(&self.config);
318 parse_with_lexer(&lexer, text, edits, cache, |state| {
319 let checkpoint = state.checkpoint();
320
321 while state.not_at_end() {
322 self.skip_trivia(state);
323 if state.at(JasmTokenType::At) {
324 state.bump();
325 self.skip_trivia(state);
326 if state.at(JasmTokenType::Identifier) {
328 state.bump();
329 if state.at(JasmTokenType::LeftParen) {
331 state.bump();
332 self.skip_trivia(state);
333 while state.not_at_end() && !state.at(JasmTokenType::RightParen) {
335 if state.at(JasmTokenType::Identifier) || state.at(JasmTokenType::String) || state.at(JasmTokenType::Number) {
336 state.bump();
337 }
338 else if state.at(JasmTokenType::Comma) {
339 state.bump();
340 }
341 else {
342 state.advance();
343 }
344 self.skip_trivia(state);
345 }
346 if state.at(JasmTokenType::RightParen) {
347 state.bump();
348 }
349 }
350 }
351 }
352 else if state.at(JasmTokenType::Dot) {
353 state.bump();
354 self.skip_trivia(state);
355 if state.at(JasmTokenType::SourceKw) {
356 state.bump();
357 self.skip_trivia(state);
358 if state.at(JasmTokenType::String) {
360 state.bump();
361 }
362 else if state.at(JasmTokenType::Identifier) {
363 state.bump();
364 }
365 }
366 else if state.at(JasmTokenType::SuperKw) {
367 state.bump();
368 self.skip_trivia(state);
369 if state.at(JasmTokenType::Identifier) {
371 state.bump();
372 }
373 }
374 else if state.at(JasmTokenType::InterfaceKw) {
375 state.bump();
376 self.skip_trivia(state);
377 if state.at(JasmTokenType::Identifier) {
379 state.bump();
380 }
381 }
382 else if state.at(JasmTokenType::CatchKw) {
383 state.bump();
384 self.skip_trivia(state);
385 if state.at(JasmTokenType::Identifier) {
387 state.bump();
388 }
389 self.skip_trivia(state);
390 if state.at(JasmTokenType::Identifier) {
391 state.bump();
392 }
393 }
394 else if state.at(JasmTokenType::AttributeKw) {
395 state.bump();
396 self.skip_trivia(state);
397 if state.at(JasmTokenType::Identifier) {
399 state.bump();
400 }
401 self.skip_trivia(state);
402 if state.at(JasmTokenType::String) || state.at(JasmTokenType::Identifier) {
403 state.bump();
404 }
405 }
406 else if state.at(JasmTokenType::StackMapKw) {
407 state.bump();
408 self.skip_trivia(state);
409 while state.not_at_end() && !state.at(JasmTokenType::Newline) {
411 if state.at(JasmTokenType::Identifier) || state.at(JasmTokenType::Number) {
412 state.bump();
413 }
414 else {
415 state.advance();
416 }
417 self.skip_trivia(state);
418 }
419 }
420 }
421 else if state.at(JasmTokenType::ClassKw) {
422 self.parse_class(state);
423 }
424 else {
425 state.advance();
426 }
427 self.skip_trivia(state);
428 }
429
430 Ok(state.finish_at(checkpoint, JasmElementType::Root))
431 })
432 }
433}