ezno_parser/extensions/
is_expression.rs

1use iterator_endiate::EndiateIteratorExt;
2use source_map::Span;
3use tokenizer_lib::{sized_tokens::TokenStart, TokenReader};
4use visitable_derive::Visitable;
5
6use crate::{
7	derive_ASTNode,
8	expressions::{ExpressionOrBlock, MultipleExpression},
9	ASTNode, TSXToken, TypeAnnotation,
10};
11
12#[apply(derive_ASTNode)]
13#[derive(Debug, PartialEq, Clone, Visitable, get_field_by_type::GetFieldByType)]
14#[get_field_by_type_target(Span)]
15pub struct IsExpression {
16	pub matcher: Box<MultipleExpression>,
17	pub branches: Vec<(TypeAnnotation, ExpressionOrBlock)>,
18	pub position: Span,
19}
20
21impl ASTNode for IsExpression {
22	fn from_reader(
23		reader: &mut impl tokenizer_lib::TokenReader<crate::TSXToken, crate::TokenStart>,
24		state: &mut crate::ParsingState,
25		options: &crate::ParseOptions,
26	) -> crate::ParseResult<Self> {
27		let start = state.expect_keyword(reader, crate::TSXKeyword::Is)?;
28		is_expression_from_reader_sub_is_keyword(reader, state, options, start)
29	}
30
31	fn to_string_from_buffer<T: source_map::ToString>(
32		&self,
33		buf: &mut T,
34		options: &crate::ToStringOptions,
35		local: crate::LocalToStringInformation,
36	) {
37		buf.push_str("is (");
38		self.matcher.to_string_from_buffer(buf, options, local);
39		buf.push_str(") {");
40		for (at_end, (l, r)) in self.branches.iter().endiate() {
41			l.to_string_from_buffer(buf, options, local);
42			buf.push_str(" => ");
43			r.to_string_from_buffer(buf, options, local);
44			if !at_end {
45				buf.push_str(", ");
46			}
47		}
48		buf.push('}');
49	}
50
51	fn get_position(&self) -> Span {
52		self.position
53	}
54}
55
56pub(crate) fn is_expression_from_reader_sub_is_keyword(
57	reader: &mut impl TokenReader<crate::TSXToken, crate::TokenStart>,
58	state: &mut crate::ParsingState,
59	options: &crate::ParseOptions,
60	start: TokenStart,
61) -> Result<IsExpression, crate::ParseError> {
62	reader.expect_next(TSXToken::OpenParentheses)?;
63	let matcher = MultipleExpression::from_reader(reader, state, options)?;
64	reader.expect_next(TSXToken::CloseParentheses)?;
65	reader.expect_next(TSXToken::OpenBrace)?;
66	let mut branches = Vec::new();
67	loop {
68		// Function important here for
69		let type_annotation = TypeAnnotation::from_reader_with_config(
70			reader,
71			state,
72			options,
73			Some(crate::type_annotations::TypeOperatorKind::Function),
74			None,
75		)?;
76		reader.expect_next(TSXToken::Arrow)?;
77		let body = ExpressionOrBlock::from_reader(reader, state, options)?;
78		if let Some(token) = reader.conditional_next(|t| matches!(t, TSXToken::CloseBrace)) {
79			branches.push((type_annotation, body));
80			return Ok(IsExpression {
81				position: start.union(token.get_end()),
82				matcher: Box::new(matcher),
83				branches,
84			});
85		}
86		if matches!(body, ExpressionOrBlock::Expression(..)) {
87			reader.expect_next(TSXToken::Comma)?;
88		}
89		branches.push((type_annotation, body));
90	}
91}