From be2579f2f8da3874d40e3660e4f050a73ad3ae8a Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Wed, 5 Apr 2023 21:47:08 -0400 Subject: [PATCH 01/16] spiking glimmer template parser extension --- crates/swc_ecma_ast/src/class.rs | 4 ++ crates/swc_ecma_ast/src/expr.rs | 5 +++ crates/swc_ecma_ast/src/glimmer.rs | 14 +++++++ crates/swc_ecma_ast/src/lib.rs | 2 + crates/swc_ecma_parser/src/lexer/mod.rs | 39 +++++++++++++++++++ crates/swc_ecma_parser/src/lexer/state.rs | 18 +++++++++ crates/swc_ecma_parser/src/macros.rs | 8 ++++ .../src/parser/class_and_fn.rs | 8 ++++ crates/swc_ecma_parser/src/parser/expr.rs | 28 +++++++++++++ crates/swc_ecma_parser/src/parser/util.rs | 2 + crates/swc_ecma_parser/src/token.rs | 9 +++++ 11 files changed, 137 insertions(+) create mode 100644 crates/swc_ecma_ast/src/glimmer.rs diff --git a/crates/swc_ecma_ast/src/class.rs b/crates/swc_ecma_ast/src/class.rs index 975d48e9dd12..a117107343f0 100644 --- a/crates/swc_ecma_ast/src/class.rs +++ b/crates/swc_ecma_ast/src/class.rs @@ -6,6 +6,7 @@ use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP}; use crate::{ expr::Expr, function::{Function, ParamOrTsParamProp}, + glimmer::GlimmerTemplate, ident::PrivateName, prop::PropName, stmt::BlockStmt, @@ -88,6 +89,9 @@ pub enum ClassMember { /// Stage 3 #[tag("AutoAccessor")] AutoAccessor(AutoAccessor), + + #[tag("GlimmerTemplate")] + GlimmerTemplate(GlimmerTemplate), } impl Take for ClassMember { diff --git a/crates/swc_ecma_ast/src/expr.rs b/crates/swc_ecma_ast/src/expr.rs index e90e15f3ec59..29ce8ef1fb1a 100644 --- a/crates/swc_ecma_ast/src/expr.rs +++ b/crates/swc_ecma_ast/src/expr.rs @@ -15,6 +15,7 @@ use swc_common::{ast_node, util::take::Take, BytePos, EqIgnoreSpan, Span, Spanne use crate::{ class::Class, function::Function, + glimmer::GlimmerTemplate, ident::{Ident, PrivateName}, jsx::{JSXElement, JSXEmptyExpr, JSXFragment, JSXMemberExpr, JSXNamespacedName}, lit::Lit, @@ -143,6 +144,9 @@ pub enum Expr { #[tag("JSXFragment")] JSXFragment(JSXFragment), + #[tag("GlimmerTemplate")] + GlimmerTemplate(GlimmerTemplate), + #[tag("TsTypeAssertion")] TsTypeAssertion(TsTypeAssertion), @@ -268,6 +272,7 @@ impl Clone for Expr { JSXEmpty(e) => JSXEmpty(e.clone()), JSXElement(e) => JSXElement(e.clone()), JSXFragment(e) => JSXFragment(e.clone()), + GlimmerTemplate(e) => GlimmerTemplate(e.clone()), TsTypeAssertion(e) => TsTypeAssertion(e.clone()), TsConstAssertion(e) => TsConstAssertion(e.clone()), TsNonNull(e) => TsNonNull(e.clone()), diff --git a/crates/swc_ecma_ast/src/glimmer.rs b/crates/swc_ecma_ast/src/glimmer.rs new file mode 100644 index 000000000000..6999bc1a245d --- /dev/null +++ b/crates/swc_ecma_ast/src/glimmer.rs @@ -0,0 +1,14 @@ +use swc_atoms::JsWord; +use swc_common::{ast_node, EqIgnoreSpan, Span}; + +#[ast_node("GlimmerTemplate")] +#[derive(Eq, Hash, EqIgnoreSpan)] +pub struct GlimmerTemplate { + pub span: Span, + + #[cfg_attr( + any(feature = "rkyv-impl", feature = "rkyv-bytecheck-impl"), + with(swc_atoms::EncodeJsWord) + )] + pub contents: JsWord, +} diff --git a/crates/swc_ecma_ast/src/lib.rs b/crates/swc_ecma_ast/src/lib.rs index 301c26afd774..237435bbe0d0 100644 --- a/crates/swc_ecma_ast/src/lib.rs +++ b/crates/swc_ecma_ast/src/lib.rs @@ -30,6 +30,7 @@ pub use self::{ SuperPropExpr, TaggedTpl, ThisExpr, Tpl, TplElement, UnaryExpr, UpdateExpr, YieldExpr, }, function::{Function, Param, ParamOrTsParamProp}, + glimmer::GlimmerTemplate, ident::{BindingIdent, Id, Ident, IdentExt, PrivateName}, jsx::{ JSXAttr, JSXAttrName, JSXAttrOrSpread, JSXAttrValue, JSXClosingElement, JSXClosingFragment, @@ -85,6 +86,7 @@ mod class; mod decl; mod expr; mod function; +mod glimmer; mod ident; mod jsx; mod list; diff --git a/crates/swc_ecma_parser/src/lexer/mod.rs b/crates/swc_ecma_parser/src/lexer/mod.rs index d513df1658c8..7a81a7f25cb8 100644 --- a/crates/swc_ecma_parser/src/lexer/mod.rs +++ b/crates/swc_ecma_parser/src/lexer/mod.rs @@ -21,6 +21,7 @@ pub use self::{ }; use crate::{ error::{Error, SyntaxError}, + lexer::state::GlimmerTemplateState, token::*, Context, Syntax, }; @@ -634,6 +635,35 @@ impl<'a> Lexer<'a> { })) } + fn read_glimmer_template(&mut self) -> LexResult { + let start = self.cur_pos(); + loop { + if !self.cur().is_some() { + return self.error(start, SyntaxError::Eof); + } + if self.is_str("") { + self.state.glimmer_template = GlimmerTemplateState::Ending; + let slice_end = self.cur_pos(); + return Ok(GlimmerTemplateContent { + value: self.input.slice(start, slice_end).into(), + }); + } + self.bump(); + } + } + + fn end_glimmer_template(&mut self) -> LexResult { + let start = self.cur_pos(); + if !self.cur().is_some() || !self.is_str("") { + return self.error(start, SyntaxError::Eof); + } + for _ in 0..11 { + self.bump(); + } + self.state.glimmer_template = GlimmerTemplateState::None; + return Ok(GlimmerTemplateEnd); + } + #[inline(never)] fn read_token_lt_gt(&mut self) -> LexResult> { debug_assert!(self.cur() == Some('<') || self.cur() == Some('>')); @@ -643,6 +673,15 @@ impl<'a> Lexer<'a> { let c = self.cur().unwrap(); self.bump(); + if c == '<' && self.is_str("template>") { + // consume the rest of the opening