oak_csharp/parser/
mod.rs

1use crate::language::CSharpLanguage;
2pub mod element_type;
3pub use element_type::CSharpElementType;
4use oak_core::{
5    GreenNode, OakError,
6    parser::{
7        ParseCache, ParseOutput, Parser, ParserState, parse_with_lexer,
8        pratt::{Associativity, Pratt, PrattParser, binary},
9    },
10    source::{Source, TextEdit},
11};
12
13pub(crate) type State<'a, S> = ParserState<'a, CSharpLanguage, S>;
14
15pub struct CSharpParser<'config> {
16    pub(crate) _language: &'config CSharpLanguage,
17}
18
19impl<'config> Pratt<CSharpLanguage> for CSharpParser<'config> {
20    fn primary<'a, S: oak_core::source::Source + ?Sized>(&self, state: &mut ParserState<'a, CSharpLanguage, S>) -> &'a GreenNode<'a, CSharpLanguage> {
21        use crate::{lexer::CSharpTokenType::*, parser::CSharpElementType::*};
22        let cp = state.checkpoint();
23        match state.peek_kind() {
24            Some(Identifier) => {
25                state.bump();
26                state.finish_at(cp, IdentifierName)
27            }
28            Some(Number) | Some(NumberLiteral) | Some(String) | Some(StringLiteral) | Some(TrueKeyword) | Some(FalseKeyword) | Some(NullKeyword) => {
29                state.bump();
30                state.finish_at(cp, LiteralExpression)
31            }
32            Some(LeftParen) => {
33                state.bump();
34                PrattParser::parse(state, 0, self);
35                state.expect(RightParen).ok();
36                state.finish_at(cp, BinaryExpression) // 简化处理
37            }
38            _ => {
39                state.bump();
40                state.finish_at(cp, Root)
41            }
42        }
43    }
44
45    fn prefix<'a, S: oak_core::source::Source + ?Sized>(&self, state: &mut ParserState<'a, CSharpLanguage, S>) -> &'a GreenNode<'a, CSharpLanguage> {
46        self.primary(state)
47    }
48
49    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>> {
50        use crate::{lexer::CSharpTokenType::*, parser::CSharpElementType::*};
51        let kind = state.peek_kind()?;
52
53        let (prec, assoc) = match kind {
54            Assign | PlusAssign | MinusAssign | StarAssign | SlashAssign | PercentAssign | AndAssign | OrAssign | XorAssign | LeftShiftAssign | RightShiftAssign | QuestionQuestionAssign => (1, Associativity::Right),
55            LogicalOr => (2, Associativity::Left),
56            LogicalAnd => (3, Associativity::Left),
57            Equal | NotEqual | Less | Greater | LessEqual | GreaterEqual | IsKeyword | AsKeyword => (4, Associativity::Left),
58            Plus | Minus => (10, Associativity::Left),
59            Star | Slash | Percent => (11, Associativity::Left),
60            LeftParen | LeftBracket | Dot => (15, Associativity::Left),
61            _ => return None,
62        };
63
64        if prec < min_precedence {
65            return None;
66        }
67
68        match kind {
69            LeftParen => {
70                let cp = state.checkpoint();
71                state.push_child(left);
72                state.expect(LeftParen).ok();
73                while state.not_at_end() && !state.at(RightParen) {
74                    state.bump();
75                }
76                state.expect(RightParen).ok();
77                Some(state.finish_at(cp, InvocationExpression))
78            }
79            LeftBracket => {
80                let cp = state.checkpoint();
81                state.push_child(left);
82                state.expect(LeftBracket).ok();
83                while state.not_at_end() && !state.at(RightBracket) {
84                    state.bump();
85                }
86                state.expect(RightBracket).ok();
87                Some(state.finish_at(cp, ElementAccessExpression))
88            }
89            Dot => {
90                let cp = state.checkpoint();
91                state.push_child(left);
92                state.expect(Dot).ok();
93                state.expect(Identifier).ok();
94                Some(state.finish_at(cp, MemberAccessExpression))
95            }
96            Assign | PlusAssign | MinusAssign | StarAssign | SlashAssign | PercentAssign | AndAssign | OrAssign | XorAssign | LeftShiftAssign | RightShiftAssign | QuestionQuestionAssign => {
97                Some(binary(state, left, kind, prec, assoc, AssignmentExpression, |s, p| PrattParser::parse(s, p, self)))
98            }
99            _ => Some(binary(state, left, kind, prec, assoc, BinaryExpression, |s, p| PrattParser::parse(s, p, self))),
100        }
101    }
102}
103
104impl<'config> CSharpParser<'config> {
105    pub fn new(language: &'config CSharpLanguage) -> Self {
106        Self { _language: language }
107    }
108
109    fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
110        use crate::lexer::CSharpTokenType::*;
111        match state.peek_kind() {
112            Some(NamespaceKeyword) => self.parse_namespace_declaration(state)?,
113            Some(UsingKeyword) => self.parse_using_directive(state)?,
114            Some(ClassKeyword) | Some(StructKeyword) | Some(InterfaceKeyword) | Some(EnumKeyword) | Some(PublicKeyword) | Some(PrivateKeyword) | Some(ProtectedKeyword) | Some(InternalKeyword) | Some(StaticKeyword) => self.parse_declaration(state)?,
115            Some(IfKeyword) => self.parse_if_statement(state)?,
116            Some(WhileKeyword) => self.parse_while_statement(state)?,
117            Some(ForKeyword) => self.parse_for_statement(state)?,
118            Some(ReturnKeyword) => self.parse_return_statement(state)?,
119            Some(LeftBrace) => self.parse_block(state)?,
120            _ => {
121                PrattParser::parse(state, 0, self);
122                state.eat(Semicolon);
123            }
124        }
125        Ok(())
126    }
127
128    fn parse_namespace_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
129        use crate::{lexer::CSharpTokenType::*, parser::CSharpElementType::*};
130        let cp = state.checkpoint();
131        state.expect(NamespaceKeyword).ok();
132        while state.not_at_end() && !state.at(LeftBrace) {
133            state.bump();
134        }
135        self.parse_block(state)?;
136        state.finish_at(cp, NamespaceDeclaration);
137        Ok(())
138    }
139
140    fn parse_using_directive<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
141        use crate::{lexer::CSharpTokenType::*, parser::CSharpElementType::*};
142        let cp = state.checkpoint();
143        state.expect(UsingKeyword).ok();
144        while state.not_at_end() && !state.at(Semicolon) {
145            state.bump();
146        }
147        state.eat(Semicolon);
148        state.finish_at(cp, UsingDirective);
149        Ok(())
150    }
151
152    fn parse_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
153        use crate::{lexer::CSharpTokenType::*, parser::CSharpElementType::*};
154        // 处理修饰符
155        while state.not_at_end() && matches!(state.peek_kind(), Some(PublicKeyword) | Some(PrivateKeyword) | Some(ProtectedKeyword) | Some(InternalKeyword) | Some(StaticKeyword) | Some(ReadonlyKeyword) | Some(AbstractKeyword)) {
156            state.bump();
157        }
158
159        match state.peek_kind() {
160            Some(ClassKeyword) => {
161                let cp = state.checkpoint();
162                state.bump();
163                state.expect(Identifier).ok();
164                while state.not_at_end() && !state.at(LeftBrace) {
165                    state.bump();
166                }
167                self.parse_block(state)?;
168                state.finish_at(cp, ClassDeclaration);
169            }
170            Some(InterfaceKeyword) => {
171                let cp = state.checkpoint();
172                state.bump();
173                state.expect(Identifier).ok();
174                self.parse_block(state)?;
175                state.finish_at(cp, InterfaceDeclaration);
176            }
177            _ => {
178                while state.not_at_end() && !state.at(Semicolon) && !state.at(LeftBrace) {
179                    state.bump();
180                }
181                if state.eat(LeftBrace) {
182                    while state.not_at_end() && !state.at(RightBrace) {
183                        self.parse_statement(state)?;
184                    }
185                    state.expect(RightBrace).ok();
186                }
187                else {
188                    state.eat(Semicolon);
189                }
190            }
191        }
192        Ok(())
193    }
194
195    fn parse_if_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
196        use crate::{lexer::CSharpTokenType::*, parser::CSharpElementType::*};
197        let cp = state.checkpoint();
198        state.bump(); // if
199        state.expect(LeftParen).ok();
200        PrattParser::parse(state, 0, self);
201        state.expect(RightParen).ok();
202        self.parse_statement(state)?;
203        if state.eat(ElseKeyword) {
204            self.parse_statement(state)?;
205        }
206        state.finish_at(cp, IfStatement);
207        Ok(())
208    }
209
210    fn parse_while_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
211        use crate::{lexer::CSharpTokenType::*, parser::CSharpElementType::*};
212        let cp = state.checkpoint();
213        state.bump(); // while
214        state.expect(LeftParen).ok();
215        PrattParser::parse(state, 0, self);
216        state.expect(RightParen).ok();
217        self.parse_statement(state)?;
218        state.finish_at(cp, WhileStatement);
219        Ok(())
220    }
221
222    fn parse_for_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
223        use crate::{lexer::CSharpTokenType::*, parser::CSharpElementType::*};
224        let cp = state.checkpoint();
225        state.bump(); // for
226        state.expect(LeftParen).ok();
227        PrattParser::parse(state, 0, self);
228        state.expect(RightParen).ok();
229        self.parse_statement(state)?;
230        state.finish_at(cp, ForStatement);
231        Ok(())
232    }
233
234    fn parse_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
235        use crate::{lexer::CSharpTokenType::*, parser::CSharpElementType::*};
236        let cp = state.checkpoint();
237        state.expect(LeftBrace).ok();
238        while state.not_at_end() && !state.at(RightBrace) {
239            self.parse_statement(state)?;
240        }
241        state.expect(RightBrace).ok();
242        state.finish_at(cp, Block);
243        Ok(())
244    }
245
246    fn parse_return_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
247        use crate::{lexer::CSharpTokenType::*, parser::CSharpElementType::*};
248        let cp = state.checkpoint();
249        state.bump(); // return
250        if !state.at(Semicolon) && !state.at(RightBrace) {
251            PrattParser::parse(state, 0, self);
252        }
253        state.eat(Semicolon);
254        state.finish_at(cp, ReturnStatement);
255        Ok(())
256    }
257}
258
259impl<'config> Parser<CSharpLanguage> for CSharpParser<'config> {
260    fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<CSharpLanguage>) -> ParseOutput<'a, CSharpLanguage> {
261        let lexer = crate::lexer::CSharpLexer::new(self._language);
262        parse_with_lexer(&lexer, text, edits, cache, |state| {
263            let cp = state.checkpoint();
264            while state.not_at_end() {
265                self.parse_statement(state)?;
266            }
267            Ok(state.finish_at(cp, crate::parser::CSharpElementType::Root))
268        })
269    }
270}