ezno_parser/extensions/
is_expression.rs1use 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 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}