oak_typescript/parser/
mod.rs

1use crate::{kind::TypeScriptSyntaxKind, language::TypeScriptLanguage, lexer::TypeScriptLexer};
2use oak_core::{
3    GreenNode, OakError, TextEdit, TokenType,
4    parser::{
5        ParseCache, ParseOutput, Parser, ParserState, parse_with_lexer,
6        pratt::{Associativity, Pratt, PrattParser, binary},
7    },
8    source::Source,
9};
10
11pub(crate) type State<'a, S> = ParserState<'a, TypeScriptLanguage, S>;
12
13pub struct TypeScriptParser<'config> {
14    pub(crate) config: &'config TypeScriptLanguage,
15}
16
17impl<'config> Pratt<TypeScriptLanguage> for TypeScriptParser<'config> {
18    fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, TypeScriptLanguage> {
19        use crate::kind::TypeScriptSyntaxKind::*;
20        let cp = state.checkpoint();
21        match state.peek_kind() {
22            Some(IdentifierName) => {
23                state.bump();
24                state.finish_at(cp, IdentifierName.into())
25            }
26            Some(NumericLiteral) | Some(StringLiteral) | Some(True) | Some(False) | Some(Null) => {
27                state.bump();
28                state.finish_at(cp, NumericLiteral.into()) // 简化处理
29            }
30            Some(LeftParen) => {
31                state.bump();
32                PrattParser::parse(state, 0, self);
33                state.expect(RightParen).ok();
34                state.finish_at(cp, BinaryExpression.into()) // 简化处理
35            }
36            _ => {
37                state.bump();
38                state.finish_at(cp, Error.into())
39            }
40        }
41    }
42
43    fn prefix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, TypeScriptLanguage> {
44        self.primary(state)
45    }
46
47    fn infix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, left: &'a GreenNode<'a, TypeScriptLanguage>, min_precedence: u8) -> Option<&'a GreenNode<'a, TypeScriptLanguage>> {
48        use crate::kind::TypeScriptSyntaxKind::*;
49        let kind = state.peek_kind()?;
50
51        let (prec, assoc) = match kind {
52            Equal
53            | PlusEqual
54            | MinusEqual
55            | StarEqual
56            | SlashEqual
57            | PercentEqual
58            | StarStarEqual
59            | LeftShiftEqual
60            | RightShiftEqual
61            | UnsignedRightShiftEqual
62            | AmpersandEqual
63            | PipeEqual
64            | CaretEqual
65            | AmpersandAmpersandEqual
66            | PipePipeEqual
67            | QuestionQuestionEqual => (1, Associativity::Right),
68            PipePipe => (2, Associativity::Left),
69            AmpersandAmpersand => (3, Associativity::Left),
70            EqualEqual | NotEqual | EqualEqualEqual | NotEqualEqual => (4, Associativity::Left),
71            As => (14, Associativity::Left),
72            Plus | Minus => (10, Associativity::Left),
73            Star | Slash | Percent => (11, Associativity::Left),
74            LeftParen | Dot => (15, Associativity::Left),
75            _ => return None,
76        };
77
78        if prec < min_precedence {
79            return None;
80        }
81
82        match kind {
83            LeftParen => {
84                let cp = state.checkpoint();
85                state.push_child(left);
86                state.expect(LeftParen).ok();
87                while state.not_at_end() && !state.at(RightParen) {
88                    state.advance();
89                }
90                state.expect(RightParen).ok();
91                Some(state.finish_at(cp, CallExpression.into()))
92            }
93            Dot => {
94                let cp = state.checkpoint();
95                state.push_child(left);
96                state.expect(Dot).ok();
97                state.expect(IdentifierName).ok();
98                Some(state.finish_at(cp, MemberExpression.into()))
99            }
100            As => {
101                let cp = state.checkpoint();
102                state.push_child(left);
103                state.expect(As).ok();
104                // 简单处理类型
105                state.advance();
106                Some(state.finish_at(cp, AsExpression.into()))
107            }
108            _ => Some(binary(state, left, kind, prec, assoc, BinaryExpression.into(), |s, p| PrattParser::parse(s, p, self))),
109        }
110    }
111}
112
113impl<'config> TypeScriptParser<'config> {
114    pub fn new(config: &'config TypeScriptLanguage) -> Self {
115        Self { config }
116    }
117
118    pub(crate) fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
119        use crate::kind::TypeScriptSyntaxKind::*;
120        match state.peek_kind() {
121            Some(Var) | Some(Let) | Some(Const) => self.parse_variable_declaration(state)?,
122            Some(Function) => self.parse_function_declaration(state)?,
123            Some(Class) => self.parse_class_declaration(state)?,
124            Some(Interface) => self.parse_interface_declaration(state)?,
125            Some(Enum) => self.parse_enum_declaration(state)?,
126            Some(Type) => self.parse_type_alias_declaration(state)?,
127            Some(Namespace) | Some(Module) => self.parse_namespace_declaration(state)?,
128            Some(Import) => self.parse_import_declaration(state)?,
129            Some(Export) => self.parse_export_declaration(state)?,
130            Some(If) => self.parse_if_statement(state)?,
131            Some(For) => self.parse_for_statement(state)?,
132            Some(While) => self.parse_while_statement(state)?,
133            Some(Return) => self.parse_return_statement(state)?,
134            Some(LeftBrace) => self.parse_block(state)?,
135            _ => {
136                PrattParser::parse(state, 0, self);
137                state.eat(Semicolon);
138            }
139        }
140        Ok(())
141    }
142
143    fn parse_variable_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
144        use crate::kind::TypeScriptSyntaxKind::*;
145        let cp = state.checkpoint();
146        state.bump(); // var, let, or const
147        while state.at(IdentifierName) {
148            state.bump();
149            if state.eat(Equal) {
150                PrattParser::parse(state, 0, self);
151            }
152            if !state.eat(Comma) {
153                break;
154            }
155        }
156        state.eat(Semicolon);
157        state.finish_at(cp, VariableDeclaration.into());
158        Ok(())
159    }
160
161    fn parse_function_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
162        use crate::kind::TypeScriptSyntaxKind::*;
163        let cp = state.checkpoint();
164        state.bump(); // function
165        state.expect(IdentifierName).ok();
166        self.parse_parameters(state)?;
167        self.parse_block(state)?;
168        state.finish_at(cp, FunctionDeclaration.into());
169        Ok(())
170    }
171
172    fn parse_class_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
173        use crate::kind::TypeScriptSyntaxKind::*;
174        let cp = state.checkpoint();
175        state.bump(); // class
176        state.expect(IdentifierName).ok();
177        if state.eat(Extends) {
178            state.expect(IdentifierName).ok();
179        }
180        self.parse_block(state)?;
181        state.finish_at(cp, ClassDeclaration.into());
182        Ok(())
183    }
184
185    fn parse_interface_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
186        use crate::kind::TypeScriptSyntaxKind::*;
187        let cp = state.checkpoint();
188        state.bump(); // interface
189        state.expect(IdentifierName).ok();
190        self.parse_block(state)?;
191        state.finish_at(cp, InterfaceDeclaration.into());
192        Ok(())
193    }
194
195    fn parse_enum_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
196        use crate::kind::TypeScriptSyntaxKind::*;
197        let cp = state.checkpoint();
198        state.bump(); // enum
199        state.expect(IdentifierName).ok();
200        self.parse_block(state)?;
201        state.finish_at(cp, EnumDeclaration.into());
202        Ok(())
203    }
204
205    fn parse_type_alias_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
206        use crate::kind::TypeScriptSyntaxKind::*;
207        let cp = state.checkpoint();
208        state.bump(); // type
209        state.expect(IdentifierName).ok();
210        state.expect(Equal).ok();
211        while state.not_at_end() && !state.at(Semicolon) {
212            state.advance();
213        }
214        state.eat(Semicolon);
215        state.finish_at(cp, TypeAliasDeclaration.into());
216        Ok(())
217    }
218
219    fn parse_namespace_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
220        use crate::kind::TypeScriptSyntaxKind::*;
221        let cp = state.checkpoint();
222        state.bump(); // namespace or module
223        state.expect(IdentifierName).ok();
224        self.parse_block(state)?;
225        state.finish_at(cp, NamespaceDeclaration.into());
226        Ok(())
227    }
228
229    fn parse_import_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
230        use crate::kind::TypeScriptSyntaxKind::*;
231        let cp = state.checkpoint();
232        state.bump(); // import
233        while state.not_at_end() && !state.at(Semicolon) {
234            state.advance();
235        }
236        state.eat(Semicolon);
237        state.finish_at(cp, ImportDeclaration.into());
238        Ok(())
239    }
240
241    fn parse_export_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
242        use crate::kind::TypeScriptSyntaxKind::*;
243        let cp = state.checkpoint();
244        state.bump(); // export
245        self.parse_statement(state)?;
246        state.finish_at(cp, ExportDeclaration.into());
247        Ok(())
248    }
249
250    fn parse_if_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
251        use crate::kind::TypeScriptSyntaxKind::*;
252        let cp = state.checkpoint();
253        state.bump(); // if
254        state.expect(LeftParen).ok();
255        PrattParser::parse(state, 0, self);
256        state.expect(RightParen).ok();
257        self.parse_statement(state)?;
258        if state.eat(Else) {
259            self.parse_statement(state)?;
260        }
261        state.finish_at(cp, IfStatement.into());
262        Ok(())
263    }
264
265    fn parse_for_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
266        use crate::kind::TypeScriptSyntaxKind::*;
267        let cp = state.checkpoint();
268        state.bump(); // for
269        state.expect(LeftParen).ok();
270        while state.not_at_end() && !state.at(RightParen) {
271            state.advance();
272        }
273        state.expect(RightParen).ok();
274        self.parse_statement(state)?;
275        state.finish_at(cp, ForStatement.into());
276        Ok(())
277    }
278
279    fn parse_while_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
280        use crate::kind::TypeScriptSyntaxKind::*;
281        let cp = state.checkpoint();
282        state.bump(); // while
283        state.expect(LeftParen).ok();
284        PrattParser::parse(state, 0, self);
285        state.expect(RightParen).ok();
286        self.parse_statement(state)?;
287        state.finish_at(cp, WhileStatement.into());
288        Ok(())
289    }
290
291    fn parse_parameters<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
292        use crate::kind::TypeScriptSyntaxKind::*;
293        state.expect(LeftParen).ok();
294        while state.not_at_end() && !state.at(RightParen) {
295            state.advance();
296        }
297        state.expect(RightParen).ok();
298        Ok(())
299    }
300
301    fn parse_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
302        use crate::kind::TypeScriptSyntaxKind::*;
303        let cp = state.checkpoint();
304        state.expect(LeftBrace).ok();
305        while state.not_at_end() && !state.at(RightBrace) {
306            self.parse_statement(state)?;
307        }
308        state.expect(RightBrace).ok();
309        state.finish_at(cp, BlockStatement.into());
310        Ok(())
311    }
312
313    fn parse_return_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
314        use crate::kind::TypeScriptSyntaxKind::*;
315        let cp = state.checkpoint();
316        state.bump(); // return
317        if !state.at(Semicolon) && !state.at(RightBrace) {
318            PrattParser::parse(state, 0, self);
319        }
320        state.eat(Semicolon);
321        state.finish_at(cp, ReturnStatement.into());
322        Ok(())
323    }
324}
325
326impl<'config> Parser<TypeScriptLanguage> for TypeScriptParser<'config> {
327    fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<TypeScriptLanguage>) -> ParseOutput<'a, TypeScriptLanguage> {
328        let lexer = TypeScriptLexer::new(self.config);
329        parse_with_lexer(&lexer, text, edits, cache, |state| {
330            let checkpoint = state.checkpoint();
331            while state.not_at_end() {
332                if state.current().map(|t| t.kind.is_ignored()).unwrap_or(false) {
333                    state.advance();
334                    continue;
335                }
336                self.parse_statement(state).ok();
337            }
338            Ok(state.finish_at(checkpoint, TypeScriptSyntaxKind::SourceFile.into()))
339        })
340    }
341}