Skip to main content

ezno_parser/expressions/
template_literal.rs

1use super::{Expression, MultipleExpression};
2use crate::{
3	derive_ASTNode, errors::parse_lexing_error, ASTNode, ParseOptions, ParseResult, Span, TSXToken,
4	Token, TokenReader,
5};
6use tokenizer_lib::sized_tokens::TokenStart;
7use visitable_derive::Visitable;
8
9#[apply(derive_ASTNode)]
10#[derive(Debug, Clone, PartialEq, Visitable, get_field_by_type::GetFieldByType)]
11#[get_field_by_type_target(Span)]
12pub struct TemplateLiteral {
13	pub tag: Option<Box<Expression>>,
14	pub parts: Vec<(String, MultipleExpression)>,
15	pub last: String,
16	pub position: Span,
17}
18
19impl ASTNode for TemplateLiteral {
20	fn get_position(&self) -> Span {
21		self.position
22	}
23
24	fn from_reader(
25		reader: &mut impl TokenReader<TSXToken, crate::TokenStart>,
26		state: &mut crate::ParsingState,
27		options: &ParseOptions,
28	) -> ParseResult<Self> {
29		let start = reader.expect_next(TSXToken::TemplateLiteralStart)?;
30		Self::from_reader_sub_start_with_tag(reader, state, options, None, start)
31	}
32
33	fn to_string_from_buffer<T: source_map::ToString>(
34		&self,
35		buf: &mut T,
36		options: &crate::ToStringOptions,
37		local: crate::LocalToStringInformation,
38	) {
39		if let Some(tag) = &self.tag {
40			tag.to_string_from_buffer(buf, options, local);
41		}
42		buf.push('`');
43		for (static_part, dynamic_part) in &self.parts {
44			buf.push_str_contains_new_line(static_part.as_str());
45
46			buf.push_str("${");
47			dynamic_part.to_string_from_buffer(buf, options, local);
48			buf.push('}');
49		}
50		buf.push_str_contains_new_line(self.last.as_str());
51		buf.push('`');
52	}
53}
54
55impl TemplateLiteral {
56	pub(crate) fn from_reader_sub_start_with_tag(
57		reader: &mut impl TokenReader<TSXToken, crate::TokenStart>,
58		state: &mut crate::ParsingState,
59		options: &ParseOptions,
60		tag: Option<Box<Expression>>,
61		start: TokenStart,
62	) -> ParseResult<Self> {
63		let mut parts = Vec::new();
64		let mut last = String::new();
65		loop {
66			match reader.next().ok_or_else(parse_lexing_error)? {
67				Token(TSXToken::TemplateLiteralChunk(chunk), _) => {
68					last = chunk;
69				}
70				Token(TSXToken::TemplateLiteralExpressionStart, _) => {
71					let expression = MultipleExpression::from_reader(reader, state, options)?;
72					parts.push((std::mem::take(&mut last), expression));
73					reader.expect_next(TSXToken::TemplateLiteralExpressionEnd)?;
74				}
75				t @ Token(TSXToken::TemplateLiteralEnd, _) => {
76					return Ok(Self { parts, last, tag, position: start.union(t.get_end()) });
77				}
78				Token(TSXToken::EOS, _) => return Err(parse_lexing_error()),
79				t => unreachable!("Token {:?}", t),
80			}
81		}
82	}
83}