1use crate::language::CSharpLanguage;
4pub mod element_type;
6pub use element_type::CSharpElementType;
7use oak_core::{
8 GreenNode, OakError,
9 parser::{
10 ParseCache, ParseOutput, Parser, ParserState, parse_with_lexer,
11 pratt::{Associativity, Pratt, PrattParser, binary},
12 },
13 source::{Source, TextEdit},
14};
15
16pub(crate) type State<'a, S> = ParserState<'a, CSharpLanguage, S>;
17
18pub struct CSharpParser<'config> {
23 pub(crate) _language: &'config CSharpLanguage,
24}
25
26impl<'config> Pratt<CSharpLanguage> for CSharpParser<'config> {
27 fn primary<'a, S: oak_core::source::Source + ?Sized>(&self, state: &mut ParserState<'a, CSharpLanguage, S>) -> &'a GreenNode<'a, CSharpLanguage> {
28 use crate::lexer::token_type::CSharpTokenType;
29 let cp = state.checkpoint();
30 match state.peek_kind() {
31 Some(CSharpTokenType::Identifier) => {
32 state.bump();
33 state.finish_at(cp, crate::parser::element_type::CSharpElementType::IdentifierName)
34 }
35 Some(CSharpTokenType::Number)
36 | Some(CSharpTokenType::NumberLiteral)
37 | Some(CSharpTokenType::String)
38 | Some(CSharpTokenType::StringLiteral)
39 | Some(CSharpTokenType::TrueKeyword)
40 | Some(CSharpTokenType::FalseKeyword)
41 | Some(CSharpTokenType::NullKeyword) => {
42 state.bump();
43 state.finish_at(cp, crate::parser::element_type::CSharpElementType::LiteralExpression)
44 }
45 Some(CSharpTokenType::LeftParen) => {
46 state.bump();
47 PrattParser::parse(state, 0, self);
48 state.expect(CSharpTokenType::RightParen).ok();
49 state.finish_at(cp, crate::parser::element_type::CSharpElementType::ParenthesizedExpression)
50 }
51 Some(CSharpTokenType::This) => {
52 state.bump();
53 state.finish_at(cp, crate::parser::element_type::CSharpElementType::ThisExpression)
54 }
55 Some(CSharpTokenType::Base) => {
56 state.bump();
57 state.finish_at(cp, crate::parser::element_type::CSharpElementType::BaseExpression)
58 }
59 Some(CSharpTokenType::New) => {
60 state.bump();
61 self.parse_new_expression(state);
62 state.finish_at(cp, crate::parser::element_type::CSharpElementType::ObjectCreationExpression)
63 }
64 Some(CSharpTokenType::Await) => {
65 state.bump();
66 PrattParser::parse(state, 0, self);
67 state.finish_at(cp, crate::parser::element_type::CSharpElementType::AwaitExpression)
68 }
69 _ => {
70 state.bump();
71 state.finish_at(cp, crate::parser::element_type::CSharpElementType::Root)
72 }
73 }
74 }
75
76 fn prefix<'a, S: oak_core::source::Source + ?Sized>(&self, state: &mut ParserState<'a, CSharpLanguage, S>) -> &'a GreenNode<'a, CSharpLanguage> {
77 self.primary(state)
78 }
79
80 fn infix<'a, S: oak_core::source::Source + ?Sized>(&self, state: &mut ParserState<'a, CSharpLanguage, S>, left: &'a GreenNode<'a, CSharpLanguage>, min_precedence: u8) -> Option<&'a GreenNode<'a, CSharpLanguage>> {
81 use crate::{lexer::token_type::CSharpTokenType, parser::CSharpElementType::*};
82 let kind = state.peek_kind()?;
83
84 let (prec, assoc) = match kind {
85 CSharpTokenType::Assign
86 | CSharpTokenType::PlusAssign
87 | CSharpTokenType::MinusAssign
88 | CSharpTokenType::StarAssign
89 | CSharpTokenType::SlashAssign
90 | CSharpTokenType::PercentAssign
91 | CSharpTokenType::AndAssign
92 | CSharpTokenType::OrAssign
93 | CSharpTokenType::XorAssign
94 | CSharpTokenType::LeftShiftAssign
95 | CSharpTokenType::RightShiftAssign
96 | CSharpTokenType::QuestionQuestionAssign => (1, Associativity::Right),
97 CSharpTokenType::Lambda => (2, Associativity::Right),
98 CSharpTokenType::LogicalOr => (3, Associativity::Left),
99 CSharpTokenType::LogicalAnd => (4, Associativity::Left),
100 CSharpTokenType::Equal | CSharpTokenType::NotEqual | CSharpTokenType::Less | CSharpTokenType::Greater | CSharpTokenType::LessEqual | CSharpTokenType::GreaterEqual | CSharpTokenType::IsKeyword | CSharpTokenType::AsKeyword => {
101 (5, Associativity::Left)
102 }
103 CSharpTokenType::Plus | CSharpTokenType::Minus => (10, Associativity::Left),
104 CSharpTokenType::Star | CSharpTokenType::Slash | CSharpTokenType::Percent => (11, Associativity::Left),
105 CSharpTokenType::LeftParen | CSharpTokenType::LeftBracket | CSharpTokenType::Dot => (15, Associativity::Left),
106 _ => return None,
107 };
108
109 if prec < min_precedence {
110 return None;
111 }
112
113 match kind {
114 CSharpTokenType::LeftParen => {
115 let cp = state.checkpoint();
116 state.push_child(left);
117 state.expect(CSharpTokenType::LeftParen).ok();
118 while state.not_at_end() && !state.at(CSharpTokenType::RightParen) {
119 PrattParser::parse(state, 0, self);
120 if state.at(CSharpTokenType::Comma) {
121 state.bump();
122 }
123 }
124 state.expect(CSharpTokenType::RightParen).ok();
125 Some(state.finish_at(cp, crate::parser::element_type::CSharpElementType::InvocationExpression))
126 }
127 CSharpTokenType::LeftBracket => {
128 let cp = state.checkpoint();
129 state.push_child(left);
130 state.expect(CSharpTokenType::LeftBracket).ok();
131 while state.not_at_end() && !state.at(CSharpTokenType::RightBracket) {
132 PrattParser::parse(state, 0, self);
133 if state.at(CSharpTokenType::Comma) {
134 state.bump();
135 }
136 }
137 state.expect(CSharpTokenType::RightBracket).ok();
138 Some(state.finish_at(cp, crate::parser::element_type::CSharpElementType::ElementAccessExpression))
139 }
140 CSharpTokenType::Dot => {
141 let cp = state.checkpoint();
142 state.push_child(left);
143 state.expect(CSharpTokenType::Dot).ok();
144 state.expect(CSharpTokenType::Identifier).ok();
145 Some(state.finish_at(cp, crate::parser::element_type::CSharpElementType::MemberAccessExpression))
146 }
147 CSharpTokenType::Lambda => {
148 let cp = state.checkpoint();
149 state.push_child(left);
150 state.expect(CSharpTokenType::Lambda).ok();
151 PrattParser::parse(state, 0, self);
152 Some(state.finish_at(cp, crate::parser::element_type::CSharpElementType::LambdaExpression))
153 }
154 CSharpTokenType::Assign
155 | CSharpTokenType::PlusAssign
156 | CSharpTokenType::MinusAssign
157 | CSharpTokenType::StarAssign
158 | CSharpTokenType::SlashAssign
159 | CSharpTokenType::PercentAssign
160 | CSharpTokenType::AndAssign
161 | CSharpTokenType::OrAssign
162 | CSharpTokenType::XorAssign
163 | CSharpTokenType::LeftShiftAssign
164 | CSharpTokenType::RightShiftAssign
165 | CSharpTokenType::QuestionQuestionAssign => Some(binary(state, left, kind, prec, assoc, AssignmentExpression, |s, p| PrattParser::parse(s, p, self))),
166 _ => Some(binary(state, left, kind, prec, assoc, BinaryExpression, |s, p| PrattParser::parse(s, p, self))),
167 }
168 }
169}
170
171impl<'config> CSharpParser<'config> {
172 pub fn new(language: &'config CSharpLanguage) -> Self {
174 Self { _language: language }
175 }
176
177 fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
182 use crate::lexer::token_type::CSharpTokenType;
183 match state.peek_kind() {
184 Some(CSharpTokenType::Namespace) => self.parse_namespace_declaration(state)?,
185 Some(CSharpTokenType::Using) => self.parse_using_directive(state)?,
186 Some(CSharpTokenType::Class)
187 | Some(CSharpTokenType::Struct)
188 | Some(CSharpTokenType::Interface)
189 | Some(CSharpTokenType::Enum)
190 | Some(CSharpTokenType::Record)
191 | Some(CSharpTokenType::Delegate)
192 | Some(CSharpTokenType::Public)
193 | Some(CSharpTokenType::Private)
194 | Some(CSharpTokenType::Protected)
195 | Some(CSharpTokenType::Internal)
196 | Some(CSharpTokenType::Static)
197 | Some(CSharpTokenType::AsyncKeyword)
198 | Some(CSharpTokenType::Abstract)
199 | Some(CSharpTokenType::Virtual)
200 | Some(CSharpTokenType::Override) => self.parse_declaration(state)?,
201 Some(CSharpTokenType::If) => self.parse_if_statement(state)?,
202 Some(CSharpTokenType::While) => self.parse_while_statement(state)?,
203 Some(CSharpTokenType::For) => self.parse_for_statement(state)?,
204 Some(CSharpTokenType::Foreach) => self.parse_foreach_statement(state)?,
205 Some(CSharpTokenType::Return) => self.parse_return_statement(state)?,
206 Some(CSharpTokenType::Break) => {
207 let cp = state.checkpoint();
208 state.bump();
209 state.eat(CSharpTokenType::Semicolon);
210 state.finish_at(cp, crate::parser::CSharpElementType::BreakStatement);
211 }
212 Some(CSharpTokenType::Continue) => {
213 let cp = state.checkpoint();
214 state.bump();
215 state.eat(CSharpTokenType::Semicolon);
216 state.finish_at(cp, crate::parser::CSharpElementType::ContinueStatement);
217 }
218 Some(CSharpTokenType::Switch) => self.parse_switch_statement(state)?,
219 Some(CSharpTokenType::Try) => self.parse_try_statement(state)?,
220 Some(CSharpTokenType::LeftBrace) => self.parse_block(state)?,
221 _ => {
222 let cp = state.checkpoint();
223 PrattParser::parse(state, 0, self);
224 state.eat(CSharpTokenType::Semicolon);
225 state.finish_at(cp, crate::parser::CSharpElementType::ExpressionStatement);
226 }
227 }
228 Ok(())
229 }
230
231 fn parse_foreach_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
235 use crate::lexer::token_type::CSharpTokenType;
236 let cp = state.checkpoint();
237 state.bump(); state.expect(CSharpTokenType::LeftParen).ok();
239 while state.not_at_end() && !state.at(CSharpTokenType::RightParen) {
241 state.bump();
242 }
243 state.expect(CSharpTokenType::RightParen).ok();
244 self.parse_statement(state)?;
245 state.finish_at(cp, crate::parser::element_type::CSharpElementType::ForeachStatement);
246 Ok(())
247 }
248
249 fn parse_namespace_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
251 use crate::lexer::token_type::CSharpTokenType;
252 let cp = state.checkpoint();
253 state.expect(CSharpTokenType::Namespace).ok();
254 while state.not_at_end() && !state.at(CSharpTokenType::LeftBrace) && !state.at(CSharpTokenType::Semicolon) {
255 state.bump();
256 }
257 if state.at(CSharpTokenType::LeftBrace) {
258 self.parse_block(state)?;
260 }
261 else {
262 state.eat(CSharpTokenType::Semicolon);
264 }
265 state.finish_at(cp, crate::parser::element_type::CSharpElementType::NamespaceDeclaration);
266 Ok(())
267 }
268
269 fn parse_using_directive<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
271 use crate::lexer::token_type::CSharpTokenType;
272 let cp = state.checkpoint();
273 state.expect(CSharpTokenType::Using).ok();
274 while state.not_at_end() && !state.at(CSharpTokenType::Semicolon) {
275 state.bump();
276 }
277 state.eat(CSharpTokenType::Semicolon);
278 state.finish_at(cp, crate::parser::element_type::CSharpElementType::UsingDirective);
279 Ok(())
280 }
281
282 fn parse_accessor_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
284 use crate::lexer::token_type::CSharpTokenType;
285 state.expect(CSharpTokenType::LeftBrace).ok();
286 while state.not_at_end() && !state.at(CSharpTokenType::RightBrace) {
287 match state.peek_kind() {
288 Some(CSharpTokenType::GetKeyword) | Some(CSharpTokenType::SetKeyword) | Some(CSharpTokenType::AddKeyword) | Some(CSharpTokenType::RemoveKeyword) => {
289 state.bump();
290 if state.at(CSharpTokenType::LeftBrace) {
291 self.parse_block(state)?;
292 }
293 else {
294 state.eat(CSharpTokenType::Semicolon);
295 }
296 }
297 _ => {
298 state.bump();
299 }
300 }
301 }
302 state.expect(CSharpTokenType::RightBrace).ok();
303 Ok(())
304 }
305
306 fn parse_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
308 use crate::lexer::token_type::CSharpTokenType;
309 let cp = state.checkpoint();
310
311 while state.not_at_end()
313 && matches!(
314 state.peek_kind(),
315 Some(CSharpTokenType::Public)
316 | Some(CSharpTokenType::Private)
317 | Some(CSharpTokenType::Protected)
318 | Some(CSharpTokenType::Internal)
319 | Some(CSharpTokenType::Static)
320 | Some(CSharpTokenType::Readonly)
321 | Some(CSharpTokenType::Abstract)
322 | Some(CSharpTokenType::Virtual)
323 | Some(CSharpTokenType::Override)
324 | Some(CSharpTokenType::AsyncKeyword)
325 )
326 {
327 state.bump();
328 }
329
330 match state.peek_kind() {
331 Some(CSharpTokenType::Class) => {
332 state.bump();
333 state.expect(CSharpTokenType::Identifier).ok();
334 while state.not_at_end() && !state.at(CSharpTokenType::LeftBrace) {
336 state.bump();
337 }
338 self.parse_block(state)?;
339 state.finish_at(cp, crate::parser::element_type::CSharpElementType::ClassDeclaration);
340 }
341 Some(CSharpTokenType::Interface) => {
342 state.bump();
343 state.expect(CSharpTokenType::Identifier).ok();
344 while state.not_at_end() && !state.at(CSharpTokenType::LeftBrace) {
345 state.bump();
346 }
347 self.parse_block(state)?;
348 state.finish_at(cp, crate::parser::element_type::CSharpElementType::InterfaceDeclaration);
349 }
350 Some(CSharpTokenType::Struct) => {
351 state.bump();
352 state.expect(CSharpTokenType::Identifier).ok();
353 while state.not_at_end() && !state.at(CSharpTokenType::LeftBrace) {
354 state.bump();
355 }
356 self.parse_block(state)?;
357 state.finish_at(cp, crate::parser::element_type::CSharpElementType::StructDeclaration);
358 }
359 Some(CSharpTokenType::Enum) => {
360 state.bump();
361 state.expect(CSharpTokenType::Identifier).ok();
362 self.parse_block(state)?;
363 state.finish_at(cp, crate::parser::element_type::CSharpElementType::EnumDeclaration);
364 }
365 Some(CSharpTokenType::Record) => {
366 state.bump();
367 if state.eat(CSharpTokenType::Struct) {
369 }
371 state.expect(CSharpTokenType::Identifier).ok();
372 while state.not_at_end() && !state.at(CSharpTokenType::LeftBrace) && !state.at(CSharpTokenType::Semicolon) {
373 state.bump();
374 }
375 if state.at(CSharpTokenType::LeftBrace) {
376 self.parse_block(state)?;
377 }
378 else {
379 state.eat(CSharpTokenType::Semicolon);
380 }
381 state.finish_at(cp, crate::parser::element_type::CSharpElementType::RecordDeclaration);
382 }
383 Some(CSharpTokenType::Delegate) => {
384 state.bump();
385 while state.not_at_end() && !state.at(CSharpTokenType::Semicolon) {
387 state.bump();
388 }
389 state.eat(CSharpTokenType::Semicolon);
390 state.finish_at(cp, crate::parser::element_type::CSharpElementType::DelegateDeclaration);
391 }
392 Some(CSharpTokenType::Event) => {
393 state.bump();
394 while state.not_at_end() && !state.at(CSharpTokenType::Semicolon) && !state.at(CSharpTokenType::LeftBrace) {
396 state.bump();
397 }
398 if state.at(CSharpTokenType::LeftBrace) {
399 self.parse_accessor_block(state)?;
400 }
401 else {
402 state.eat(CSharpTokenType::Semicolon);
403 }
404 state.finish_at(cp, crate::parser::element_type::CSharpElementType::EventDeclaration);
405 }
406 _ => {
407 state.bump(); while state.not_at_end() && !state.at(CSharpTokenType::Semicolon) && !state.at(CSharpTokenType::LeftBrace) && !state.at(CSharpTokenType::LeftParen) {
411 state.bump();
412 }
413
414 if state.eat(CSharpTokenType::This) && state.at(CSharpTokenType::LeftBracket) {
415 state.bump(); while state.not_at_end() && !state.at(CSharpTokenType::RightBracket) {
418 state.bump();
419 }
420 state.expect(CSharpTokenType::RightBracket).ok();
421 self.parse_accessor_block(state)?;
422 state.finish_at(cp, crate::parser::element_type::CSharpElementType::IndexerDeclaration);
423 }
424 else {
425 state.expect(CSharpTokenType::Identifier).ok();
426 if state.at(CSharpTokenType::LeftParen) {
427 state.bump(); while state.not_at_end() && !state.at(CSharpTokenType::RightParen) {
430 state.bump();
431 }
432 state.expect(CSharpTokenType::RightParen).ok();
433 if state.at(CSharpTokenType::LeftBrace) {
434 self.parse_block(state)?;
435 }
436 else {
437 state.eat(CSharpTokenType::Semicolon);
438 }
439 state.finish_at(cp, crate::parser::element_type::CSharpElementType::MethodDeclaration);
440 }
441 else if state.at(CSharpTokenType::LeftBrace) {
442 self.parse_accessor_block(state)?;
444 state.finish_at(cp, crate::parser::element_type::CSharpElementType::PropertyDeclaration);
445 }
446 else {
447 state.eat(CSharpTokenType::Semicolon);
449 state.finish_at(cp, crate::parser::element_type::CSharpElementType::FieldDeclaration);
450 }
451 }
452 }
453 }
454 Ok(())
455 }
456
457 fn parse_if_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
459 use crate::lexer::token_type::CSharpTokenType;
460 let cp = state.checkpoint();
461 state.bump(); state.expect(CSharpTokenType::LeftParen).ok();
463 PrattParser::parse(state, 0, self);
464 state.expect(CSharpTokenType::RightParen).ok();
465 self.parse_statement(state)?;
466 if state.eat(CSharpTokenType::Else) {
467 self.parse_statement(state)?;
468 }
469 state.finish_at(cp, crate::parser::element_type::CSharpElementType::IfStatement);
470 Ok(())
471 }
472
473 fn parse_while_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
475 use crate::lexer::token_type::CSharpTokenType;
476 let cp = state.checkpoint();
477 state.bump(); state.expect(CSharpTokenType::LeftParen).ok();
479 PrattParser::parse(state, 0, self);
480 state.expect(CSharpTokenType::RightParen).ok();
481 self.parse_statement(state)?;
482 state.finish_at(cp, crate::parser::element_type::CSharpElementType::WhileStatement);
483 Ok(())
484 }
485
486 fn parse_for_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
488 use crate::lexer::token_type::CSharpTokenType;
489 let cp = state.checkpoint();
490 state.bump(); state.expect(CSharpTokenType::LeftParen).ok();
492 PrattParser::parse(state, 0, self);
493 state.expect(CSharpTokenType::RightParen).ok();
494 self.parse_statement(state)?;
495 state.finish_at(cp, crate::parser::element_type::CSharpElementType::ForStatement);
496 Ok(())
497 }
498
499 fn parse_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
501 use crate::lexer::token_type::CSharpTokenType;
502 let cp = state.checkpoint();
503 state.expect(CSharpTokenType::LeftBrace).ok();
504 while state.not_at_end() && !state.at(CSharpTokenType::RightBrace) {
505 self.parse_statement(state)?;
506 }
507 state.expect(CSharpTokenType::RightBrace).ok();
508 state.finish_at(cp, crate::parser::element_type::CSharpElementType::Block);
509 Ok(())
510 }
511
512 fn parse_return_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
514 use crate::lexer::token_type::CSharpTokenType;
515 let cp = state.checkpoint();
516 state.bump(); if !state.at(CSharpTokenType::Semicolon) {
518 PrattParser::parse(state, 0, self);
519 }
520 state.eat(CSharpTokenType::Semicolon);
521 state.finish_at(cp, crate::parser::element_type::CSharpElementType::ReturnStatement);
522 Ok(())
523 }
524
525 fn parse_new_expression<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
527 use crate::lexer::token_type::CSharpTokenType;
528 while state.not_at_end() && !state.at(CSharpTokenType::LeftParen) && !state.at(CSharpTokenType::LeftBrace) {
530 state.bump();
531 }
532
533 if state.at(CSharpTokenType::LeftParen) {
535 state.bump();
536 while state.not_at_end() && !state.at(CSharpTokenType::RightParen) {
537 PrattParser::parse(state, 0, self);
538 if state.at(CSharpTokenType::Comma) {
539 state.bump();
540 }
541 }
542 state.expect(CSharpTokenType::RightParen).ok();
543 }
544
545 if state.at(CSharpTokenType::LeftBrace) {
547 self.parse_block(state).ok();
548 }
549 }
550
551 fn parse_switch_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
553 use crate::lexer::token_type::CSharpTokenType;
554 let cp = state.checkpoint();
555 state.bump(); state.expect(CSharpTokenType::LeftParen).ok();
557 PrattParser::parse(state, 0, self);
558 state.expect(CSharpTokenType::RightParen).ok();
559 state.expect(CSharpTokenType::LeftBrace).ok();
560
561 while state.not_at_end() && !state.at(CSharpTokenType::RightBrace) {
562 match state.peek_kind() {
563 Some(CSharpTokenType::Case) => {
564 state.bump();
565 PrattParser::parse(state, 0, self);
566 state.expect(CSharpTokenType::Colon).ok();
567 while state.not_at_end() && !state.at(CSharpTokenType::Case) && !state.at(CSharpTokenType::Default) && !state.at(CSharpTokenType::RightBrace) {
568 self.parse_statement(state)?;
569 }
570 }
571 Some(CSharpTokenType::Default) => {
572 state.bump();
573 state.expect(CSharpTokenType::Colon).ok();
574 while state.not_at_end() && !state.at(CSharpTokenType::RightBrace) {
575 self.parse_statement(state)?;
576 }
577 }
578 _ => {
579 state.bump();
580 }
581 }
582 }
583
584 state.expect(CSharpTokenType::RightBrace).ok();
585 state.finish_at(cp, crate::parser::element_type::CSharpElementType::SwitchStatement);
586 Ok(())
587 }
588
589 fn parse_try_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
591 use crate::lexer::token_type::CSharpTokenType;
592 let cp = state.checkpoint();
593 state.bump(); self.parse_block(state)?;
595
596 while state.not_at_end() && state.at(CSharpTokenType::Catch) {
598 state.bump(); if state.at(CSharpTokenType::LeftParen) {
600 state.bump();
601 while state.not_at_end() && !state.at(CSharpTokenType::RightParen) {
602 state.bump();
603 }
604 state.expect(CSharpTokenType::RightParen).ok();
605 }
606 self.parse_block(state)?;
607 }
608
609 if state.not_at_end() && state.at(CSharpTokenType::Finally) {
611 state.bump(); self.parse_block(state)?;
613 }
614
615 state.finish_at(cp, crate::parser::element_type::CSharpElementType::TryStatement);
616 Ok(())
617 }
618}
619
620impl<'config> Parser<CSharpLanguage> for CSharpParser<'config> {
621 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<CSharpLanguage>) -> ParseOutput<'a, CSharpLanguage> {
622 let lexer = crate::lexer::CSharpLexer::new(self._language);
623 parse_with_lexer(&lexer, text, edits, cache, |state| {
624 let cp = state.checkpoint();
625 while state.not_at_end() {
626 self.parse_statement(state)?;
627 }
628 Ok(state.finish_at(cp, crate::parser::element_type::CSharpElementType::Root))
629 })
630 }
631}