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()) }
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); state.finish_at(cp, UnaryExpression.into())
60 }
61 Some(New) => {
62 state.bump();
63 PrattParser::parse(state, 17, self); 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 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(); 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(); 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(); 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(); }
337 else if !self.at(state, RightBrace) && state.not_at_end() {
338 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(); 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(); 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(); 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(); 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(); self.skip_trivia(state);
406 if self.eat(state, LeftBrace) {
407 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 state.bump();
425 self.expect(state, As).ok();
426 self.expect(state, IdentifierName).ok();
427 }
428 else if self.at(state, IdentifierName) {
429 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 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(); self.skip_trivia(state);
452 if self.eat(state, Default) {
453 self.parse_statement(state)?;
454 }
455 else if self.at(state, LeftBrace) {
456 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 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(); 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(); 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(); 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 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(); 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}