| 95 | } |
| 96 | |
| 97 | fn interpolated_parser<'a, I>( |
| 98 | ) -> impl Parser<'a, I, Vec<InterpolateItem>, extra::Err<Rich<'a, char, SimpleSpan>>> |
| 99 | where |
| 100 | I: ValueInput<'a, Token = char, Span = SimpleSpan> + SliceInput<'a, Slice = &'a str>, |
| 101 | { |
| 102 | let expr = interpolate_ident_part() |
| 103 | .separated_by(just('.')) |
| 104 | .at_least(1) |
| 105 | .collect() |
| 106 | .map(Ident::from_path) |
| 107 | .map(ExprKind::Ident) |
| 108 | .map_with(|kind, extra| { |
| 109 | // Convert SimpleSpan to our Span type (will be adjusted in parse() function) |
| 110 | let simple_span: SimpleSpan = extra.span(); |
| 111 | let span = Span { |
| 112 | start: simple_span.start, |
| 113 | end: simple_span.end, |
| 114 | source_id: 0, |
| 115 | }; |
| 116 | ExprKind::into_expr(kind, span) |
| 117 | }) |
| 118 | .map(Box::new) |
| 119 | .labelled("interpolated string variable") |
| 120 | .then( |
| 121 | just(':') |
| 122 | .ignore_then(none_of('}').repeated().collect::<String>()) |
| 123 | .or_not(), |
| 124 | ) |
| 125 | .delimited_by(just('{'), just('}')) |
| 126 | .map(|(expr, format)| InterpolateItem::Expr { expr, format }); |
| 127 | |
| 128 | // Convert double braces to single braces, and fail on any single braces. |
| 129 | let string = just("{{") |
| 130 | .to('{') |
| 131 | .or(just("}}").to('}')) |
| 132 | .or(none_of("{}")) |
| 133 | .repeated() |
| 134 | .at_least(1) |
| 135 | .collect::<String>() |
| 136 | .map(InterpolateItem::String); |
| 137 | |
| 138 | expr.or(string).repeated().collect().then_ignore(end()) |
| 139 | } |
| 140 | |
| 141 | pub(crate) fn interpolate_ident_part<'a, I>( |
| 142 | ) -> impl Parser<'a, I, String, extra::Err<Rich<'a, char, SimpleSpan>>> + Clone |