Skip to main content

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> TypeScriptParser<'config> {
18    pub fn new(config: &'config TypeScriptLanguage) -> Self {
19        Self { config }
20    }
21}
22
23impl<'config> Pratt<TypeScriptLanguage> for TypeScriptParser<'config> {
24    fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, TypeScriptLanguage> {
25        use crate::kind::TypeScriptSyntaxKind::*;
26        let kind = self.peek_kind(state);
27        let cp = state.checkpoint();
28        match kind {
29            Some(IdentifierName) => {
30                self.expect(state, IdentifierName).ok();
31                state.finish_at(cp, IdentifierName.into())
32            }
33            Some(NumericLiteral) | Some(StringLiteral) | Some(BigIntLiteral) | Some(TemplateString) | Some(True) | Some(False) | Some(Null) | Some(RegexLiteral) => {
34                let kind = state.peek_kind().unwrap();
35                state.bump();
36                state.finish_at(cp, kind.into())
37            }
38            Some(LeftParen) => {
39                state.bump();
40                PrattParser::parse(state, 0, self);
41                self.expect(state, RightParen).ok();
42                state.finish_at(cp, BinaryExpression.into()) // 简化处理
43            }
44            _ => {
45                state.bump();
46                state.finish_at(cp, Error.into())
47            }
48        }
49    }
50
51    fn prefix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, TypeScriptLanguage> {
52        use crate::kind::TypeScriptSyntaxKind::*;
53        let kind = self.peek_kind(state);
54        let cp = state.checkpoint();
55        match kind {
56            Some(Plus) | Some(Minus) | Some(Exclamation) | Some(Tilde) | Some(Typeof) | Some(Void) | Some(Delete) | Some(Await) => {
57                state.bump();
58                PrattParser::parse(state, 15, self); // High precedence for prefix
59                state.finish_at(cp, UnaryExpression.into())
60            }
61            Some(New) => {
62                state.bump();
63                PrattParser::parse(state, 17, self); // Higher precedence than call
64                if self.eat(state, LeftParen) {
65                    while state.not_at_end() && !self.at(state, RightParen) {
66                        let acp = state.checkpoint();
67                        PrattParser::parse(state, 0, self);
68                        state.finish_at(acp, CallArgument.into());
69                        self.eat(state, Comma);
70                    }
71                    self.expect(state, RightParen).ok();
72                }
73                state.finish_at(cp, NewExpression.into())
74            }
75            _ => self.primary(state),
76        }
77    }
78
79    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>> {
80        use crate::kind::TypeScriptSyntaxKind::*;
81        let kind = self.peek_kind(state)?;
82
83        let (prec, assoc) = match kind {
84            Equal
85            | PlusEqual
86            | MinusEqual
87            | StarEqual
88            | SlashEqual
89            | PercentEqual
90            | StarStarEqual
91            | LeftShiftEqual
92            | RightShiftEqual
93            | UnsignedRightShiftEqual
94            | AmpersandEqual
95            | PipeEqual
96            | CaretEqual
97            | AmpersandAmpersandEqual
98            | PipePipeEqual
99            | QuestionQuestionEqual => (1, Associativity::Right),
100            Question => (2, Associativity::Right),
101            PipePipe => (3, Associativity::Left),
102            AmpersandAmpersand => (4, Associativity::Left),
103            Pipe => (5, Associativity::Left),
104            Caret => (6, Associativity::Left),
105            Ampersand => (7, Associativity::Left),
106            EqualEqual | NotEqual | EqualEqualEqual | NotEqualEqual => (8, Associativity::Left),
107            Less | Greater | LessEqual | GreaterEqual | Instanceof | In => (9, Associativity::Left),
108            LeftShift | RightShift | UnsignedRightShift => (10, Associativity::Left),
109            Plus | Minus => (11, Associativity::Left),
110            Star | Slash | Percent => (12, Associativity::Left),
111            StarStar => (13, Associativity::Right),
112            As => (14, Associativity::Left),
113            LeftParen | Dot | LeftBracket | QuestionDot => (16, Associativity::Left),
114            _ => return None,
115        };
116
117        if prec < min_precedence {
118            return None;
119        }
120
121        match kind {
122            LeftParen => {
123                let cp = state.checkpoint();
124                state.push_child(left);
125                self.expect(state, LeftParen).ok();
126                while state.not_at_end() && !self.at(state, RightParen) {
127                    self.skip_trivia(state);
128                    let acp = state.checkpoint();
129                    PrattParser::parse(state, 0, self);
130                    state.finish_at(acp, CallArgument.into());
131                    self.eat(state, Comma);
132                }
133                self.expect(state, RightParen).ok();
134                Some(state.finish_at(cp, CallExpression.into()))
135            }
136            Dot | QuestionDot => {
137                let cp = state.checkpoint();
138                state.push_child(left);
139                let op = if kind == Dot { Dot } else { QuestionDot };
140                self.expect(state, op).ok();
141                self.expect(state, IdentifierName).ok();
142                Some(state.finish_at(cp, MemberExpression.into()))
143            }
144            LeftBracket => {
145                let cp = state.checkpoint();
146                state.push_child(left);
147                self.expect(state, LeftBracket).ok();
148                PrattParser::parse(state, 0, self);
149                self.expect(state, RightBracket).ok();
150                Some(state.finish_at(cp, MemberExpression.into()))
151            }
152            As => {
153                let cp = state.checkpoint();
154                state.push_child(left);
155                self.expect(state, As).ok();
156                // 简单处理类型:跳过接下来的标识符或基本类型
157                self.skip_trivia(state);
158                if state.at(IdentifierName.into()) {
159                    self.expect(state, IdentifierName).ok();
160                }
161                Some(state.finish_at(cp, AsExpression.into()))
162            }
163            Question => {
164                let cp = state.checkpoint();
165                state.push_child(left);
166                self.expect(state, Question).ok();
167                PrattParser::parse(state, 0, self);
168                self.expect(state, Colon).ok();
169                PrattParser::parse(state, 0, self);
170                Some(state.finish_at(cp, ConditionalExpression.into()))
171            }
172            _ => Some(binary(state, left, kind, prec, assoc, BinaryExpression.into(), |s, p| PrattParser::parse(s, p, self))),
173        }
174    }
175}
176
177impl<'config> TypeScriptParser<'config> {
178    fn peek_kind<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Option<TypeScriptSyntaxKind> {
179        self.skip_trivia(state);
180        state.peek_kind().map(|k| k.try_into().unwrap())
181    }
182
183    fn skip_trivia<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
184        while state.not_at_end() && state.current().map(|t| t.kind.is_ignored()).unwrap_or(false) {
185            state.bump();
186        }
187    }
188
189    fn expect<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, kind: TypeScriptSyntaxKind) -> Result<(), OakError> {
190        self.skip_trivia(state);
191        let cp = state.checkpoint();
192        let res = state.expect(kind.into());
193        if res.is_ok() {
194            state.finish_at(cp, kind.into());
195        }
196        res
197    }
198
199    fn eat<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, kind: TypeScriptSyntaxKind) -> bool {
200        self.skip_trivia(state);
201        let cp = state.checkpoint();
202        let res = state.eat(kind.into());
203        if res {
204            state.finish_at(cp, kind.into());
205        }
206        res
207    }
208
209    fn at<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, kind: TypeScriptSyntaxKind) -> bool {
210        self.skip_trivia(state);
211        state.at(kind.into())
212    }
213
214    pub(crate) fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
215        use crate::kind::TypeScriptSyntaxKind::*;
216        self.skip_trivia(state);
217        match state.peek_kind() {
218            Some(Var) | Some(Let) | Some(Const) => self.parse_variable_declaration(state)?,
219            Some(Function) => self.parse_function_declaration(state)?,
220            Some(Class) => self.parse_class_declaration(state)?,
221            Some(Interface) => self.parse_interface_declaration(state)?,
222            Some(Enum) => self.parse_enum_declaration(state)?,
223            Some(Type) => self.parse_type_alias_declaration(state)?,
224            Some(Namespace) | Some(Module) => self.parse_namespace_declaration(state)?,
225            Some(Import) => self.parse_import_declaration(state)?,
226            Some(Export) => self.parse_export_declaration(state)?,
227            Some(If) => self.parse_if_statement(state)?,
228            Some(For) => self.parse_for_statement(state)?,
229            Some(While) => self.parse_while_statement(state)?,
230            Some(Return) => self.parse_return_statement(state)?,
231            Some(LeftBrace) => self.parse_block(state)?,
232            _ => {
233                let cp = state.checkpoint();
234                PrattParser::parse(state, 0, self);
235                self.skip_trivia(state);
236                state.eat(Semicolon);
237                state.finish_at(cp, ExpressionStatement.into());
238            }
239        }
240        Ok(())
241    }
242
243    fn parse_variable_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
244        use crate::kind::TypeScriptSyntaxKind::*;
245        let cp = state.checkpoint();
246        state.bump(); // var, let, or const
247        self.skip_trivia(state);
248        while state.at(IdentifierName.into()) {
249            self.expect(state, IdentifierName).ok();
250            if self.eat(state, Equal) {
251                PrattParser::parse(state, 0, self);
252            }
253            if !self.eat(state, Comma) {
254                break;
255            }
256            self.skip_trivia(state);
257        }
258        self.eat(state, Semicolon);
259        state.finish_at(cp, VariableDeclaration.into());
260        Ok(())
261    }
262
263    fn parse_function_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
264        use crate::kind::TypeScriptSyntaxKind::*;
265        let cp = state.checkpoint();
266        state.bump(); // function
267        self.skip_trivia(state);
268        if self.at(state, IdentifierName) {
269            self.expect(state, IdentifierName).ok();
270        }
271        self.parse_parameters(state)?;
272        self.parse_block(state)?;
273        state.finish_at(cp, FunctionDeclaration.into());
274        Ok(())
275    }
276
277    fn parse_class_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
278        use crate::kind::TypeScriptSyntaxKind::*;
279        let cp = state.checkpoint();
280        state.bump(); // class
281        self.expect(state, IdentifierName).ok();
282        if self.eat(state, Extends) {
283            self.expect(state, IdentifierName).ok();
284        }
285        self.parse_class_body(state)?;
286        state.finish_at(cp, ClassDeclaration.into());
287        Ok(())
288    }
289
290    fn parse_class_body<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
291        use crate::kind::TypeScriptSyntaxKind::*;
292        let cp = state.checkpoint();
293        self.expect(state, LeftBrace).ok();
294        while state.not_at_end() && !self.at(state, RightBrace) {
295            self.skip_trivia(state);
296            let mcp = state.checkpoint();
297            self.eat(state, Static);
298            self.eat(state, Public);
299            self.eat(state, Private);
300            self.eat(state, Protected);
301
302            if self.at(state, IdentifierName) {
303                self.expect(state, IdentifierName).ok();
304                if self.at(state, LeftParen) {
305                    self.parse_parameters(state)?;
306                    self.skip_trivia(state);
307                    if self.eat(state, Colon) {
308                        self.expect(state, IdentifierName).ok();
309                    }
310                    self.parse_block(state)?;
311                    state.finish_at(mcp, MethodDeclaration.into());
312                }
313                else {
314                    if self.eat(state, Colon) {
315                        self.expect(state, IdentifierName).ok();
316                    }
317                    if self.eat(state, Equal) {
318                        PrattParser::parse(state, 0, self);
319                    }
320                    self.eat(state, Semicolon);
321                    state.finish_at(mcp, PropertyDeclaration.into());
322                }
323            }
324            else if self.at(state, Constructor) {
325                state.bump();
326                self.parse_parameters(state)?;
327                self.skip_trivia(state);
328                if self.eat(state, Colon) {
329                    self.expect(state, IdentifierName).ok();
330                }
331                self.parse_block(state)?;
332                state.finish_at(mcp, ConstructorDeclaration.into());
333            }
334            else if self.at(state, Semicolon) {
335                state.bump(); // Skip extra semicolons in class body
336            }
337            else if !self.at(state, RightBrace) && state.not_at_end() {
338                // If we encounter something unexpected, try to skip until next member or end of class
339                state.bump();
340            }
341            else {
342                break;
343            }
344        }
345        self.expect(state, RightBrace).ok();
346        state.finish_at(cp, ClassBody.into());
347        Ok(())
348    }
349
350    fn parse_interface_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
351        use crate::kind::TypeScriptSyntaxKind::*;
352        let cp = state.checkpoint();
353        state.bump(); // interface
354        self.expect(state, IdentifierName).ok();
355        self.parse_block(state)?;
356        state.finish_at(cp, InterfaceDeclaration.into());
357        Ok(())
358    }
359
360    fn parse_enum_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
361        use crate::kind::TypeScriptSyntaxKind::*;
362        let cp = state.checkpoint();
363        state.bump(); // enum
364        self.expect(state, IdentifierName).ok();
365        self.parse_block(state)?;
366        state.finish_at(cp, EnumDeclaration.into());
367        Ok(())
368    }
369
370    fn parse_type_alias_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
371        use crate::kind::TypeScriptSyntaxKind::*;
372        let cp = state.checkpoint();
373        state.bump(); // type
374        self.expect(state, IdentifierName).ok();
375        self.expect(state, Equal).ok();
376        while state.not_at_end() && !self.at(state, Semicolon) {
377            self.skip_trivia(state);
378            if state.not_at_end() && !self.at(state, Semicolon) {
379                state.bump();
380            }
381            else {
382                break;
383            }
384        }
385        self.eat(state, Semicolon);
386        state.finish_at(cp, TypeAliasDeclaration.into());
387        Ok(())
388    }
389
390    fn parse_namespace_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
391        use crate::kind::TypeScriptSyntaxKind::*;
392        let cp = state.checkpoint();
393        state.bump(); // namespace or module
394        self.expect(state, IdentifierName).ok();
395        self.parse_block(state)?;
396        state.finish_at(cp, NamespaceDeclaration.into());
397        Ok(())
398    }
399
400    fn parse_import_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
401        use crate::kind::TypeScriptSyntaxKind::*;
402        let cp = state.checkpoint();
403        state.bump(); // import
404
405        self.skip_trivia(state);
406        if self.eat(state, LeftBrace) {
407            // import { a, b as c } from '...'
408            while state.not_at_end() && !self.at(state, RightBrace) {
409                self.skip_trivia(state);
410                if self.at(state, IdentifierName) {
411                    self.expect(state, IdentifierName).ok();
412                    if self.eat(state, As) {
413                        self.expect(state, IdentifierName).ok();
414                    }
415                }
416                if !self.eat(state, Comma) {
417                    break;
418                }
419            }
420            self.expect(state, RightBrace).ok();
421        }
422        else if self.at(state, Star) {
423            // import * as ns from '...'
424            state.bump();
425            self.expect(state, As).ok();
426            self.expect(state, IdentifierName).ok();
427        }
428        else if self.at(state, IdentifierName) {
429            // import defaultExport from '...'
430            self.expect(state, IdentifierName).ok();
431        }
432
433        if self.eat(state, From) {
434            self.expect(state, StringLiteral).ok();
435        }
436        else if self.at(state, StringLiteral) {
437            // import '...'
438            self.expect(state, StringLiteral).ok();
439        }
440
441        self.eat(state, Semicolon);
442        state.finish_at(cp, ImportDeclaration.into());
443        Ok(())
444    }
445
446    fn parse_export_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
447        use crate::kind::TypeScriptSyntaxKind::*;
448        let cp = state.checkpoint();
449        state.bump(); // export
450
451        self.skip_trivia(state);
452        if self.eat(state, Default) {
453            self.parse_statement(state)?;
454        }
455        else if self.at(state, LeftBrace) {
456            // export { a, b as c }
457            state.bump();
458            while state.not_at_end() && !self.at(state, RightBrace) {
459                self.skip_trivia(state);
460                if self.at(state, IdentifierName) {
461                    state.bump();
462                    if self.eat(state, As) {
463                        self.expect(state, IdentifierName).ok();
464                    }
465                }
466                if !self.eat(state, Comma) {
467                    break;
468                }
469            }
470            self.expect(state, RightBrace).ok();
471            if self.eat(state, From) {
472                self.expect(state, StringLiteral).ok();
473            }
474            self.eat(state, Semicolon);
475        }
476        else if self.at(state, Star) {
477            // export * from '...'
478            state.bump();
479            if self.eat(state, As) {
480                self.expect(state, IdentifierName).ok();
481            }
482            self.expect(state, From).ok();
483            self.expect(state, StringLiteral).ok();
484            self.eat(state, Semicolon);
485        }
486        else {
487            self.parse_statement(state)?;
488        }
489
490        state.finish_at(cp, ExportDeclaration.into());
491        Ok(())
492    }
493
494    fn parse_if_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
495        use crate::kind::TypeScriptSyntaxKind::*;
496        let cp = state.checkpoint();
497        state.bump(); // if
498        self.expect(state, LeftParen).ok();
499        PrattParser::parse(state, 0, self);
500        self.expect(state, RightParen).ok();
501        self.parse_statement(state)?;
502        if self.eat(state, Else) {
503            self.parse_statement(state)?;
504        }
505        state.finish_at(cp, IfStatement.into());
506        Ok(())
507    }
508
509    fn parse_for_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
510        use crate::kind::TypeScriptSyntaxKind::*;
511        let cp = state.checkpoint();
512        state.bump(); // for
513        self.expect(state, LeftParen).ok();
514        while state.not_at_end() && !self.at(state, RightParen) {
515            self.skip_trivia(state);
516            if state.not_at_end() && !self.at(state, RightParen) {
517                state.bump();
518            }
519            else {
520                break;
521            }
522        }
523        self.expect(state, RightParen).ok();
524        self.parse_statement(state)?;
525        state.finish_at(cp, ForStatement.into());
526        Ok(())
527    }
528
529    fn parse_while_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
530        use crate::kind::TypeScriptSyntaxKind::*;
531        let cp = state.checkpoint();
532        state.bump(); // while
533        self.expect(state, LeftParen).ok();
534        PrattParser::parse(state, 0, self);
535        self.expect(state, RightParen).ok();
536        self.parse_statement(state)?;
537        state.finish_at(cp, WhileStatement.into());
538        Ok(())
539    }
540
541    fn parse_parameters<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
542        use crate::kind::TypeScriptSyntaxKind::*;
543        self.expect(state, LeftParen).ok();
544        while state.not_at_end() && !self.at(state, RightParen) {
545            self.skip_trivia(state);
546            let cp = state.checkpoint();
547            if self.at(state, IdentifierName) {
548                self.expect(state, IdentifierName).ok();
549                // Skip type annotation
550                if self.eat(state, Colon) {
551                    while state.not_at_end() && !self.at(state, Comma) && !self.at(state, RightParen) {
552                        self.skip_trivia(state);
553                        if state.not_at_end() && !self.at(state, Comma) && !self.at(state, RightParen) {
554                            state.bump();
555                        }
556                        else {
557                            break;
558                        }
559                    }
560                }
561            }
562            else {
563                state.bump();
564            }
565            state.finish_at(cp, Parameter.into());
566            self.eat(state, Comma);
567        }
568        self.expect(state, RightParen).ok();
569        Ok(())
570    }
571
572    fn parse_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
573        use crate::kind::TypeScriptSyntaxKind::*;
574        let cp = state.checkpoint();
575        self.expect(state, LeftBrace).ok();
576        while state.not_at_end() && !self.at(state, RightBrace) {
577            self.parse_statement(state)?;
578        }
579        self.expect(state, RightBrace).ok();
580        state.finish_at(cp, BlockStatement.into());
581        Ok(())
582    }
583
584    fn parse_return_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
585        use crate::kind::TypeScriptSyntaxKind::*;
586        let cp = state.checkpoint();
587        state.bump(); // return
588        if !self.at(state, Semicolon) && !self.at(state, RightBrace) {
589            PrattParser::parse(state, 0, self);
590        }
591        self.eat(state, Semicolon);
592        state.finish_at(cp, ReturnStatement.into());
593        Ok(())
594    }
595}
596
597impl<'config> Parser<TypeScriptLanguage> for TypeScriptParser<'config> {
598    fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<TypeScriptLanguage>) -> ParseOutput<'a, TypeScriptLanguage> {
599        let lexer = TypeScriptLexer::new(self.config);
600        parse_with_lexer(&lexer, text, edits, cache, |state| {
601            let checkpoint = state.checkpoint();
602            while state.not_at_end() {
603                self.skip_trivia(state);
604                if state.not_at_end() {
605                    self.parse_statement(state).ok();
606                }
607            }
608            Ok(state.finish_at(checkpoint, TypeScriptSyntaxKind::SourceFile.into()))
609        })
610    }
611}