Actually just three programming languages in a trenchcoat
1use super::{pattern::Precedence, *};
2use crate::{Parser, Spanned};
3use source_span::Span;
4use trilogy_scanner::{Token, TokenType::*};
5
6#[derive(Clone, Debug)]
7pub struct GluePattern {
8 pub lhs: Pattern,
9 pub glue: Token,
10 pub rhs: Pattern,
11 pub span: Span,
12}
13
14impl Spanned for GluePattern {
15 fn span(&self) -> Span {
16 self.span
17 }
18}
19
20impl GluePattern {
21 pub(crate) fn new(lhs: Pattern, glue: Token, rhs: Pattern) -> Self {
22 Self {
23 span: lhs.span().union(rhs.span()),
24 lhs,
25 glue,
26 rhs,
27 }
28 }
29
30 pub(crate) fn parse(parser: &mut Parser, lhs: Pattern) -> SyntaxResult<Self> {
31 let glue = parser
32 .expect(OpGlue)
33 .expect("Caller should have found this");
34 let rhs = Pattern::parse_precedence(parser, Precedence::Glue)?;
35 Ok(Self {
36 span: lhs.span().union(rhs.span()),
37 lhs,
38 glue,
39 rhs,
40 })
41 }
42}
43
44impl TryFrom<BinaryOperation> for GluePattern {
45 type Error = SyntaxError;
46
47 fn try_from(value: BinaryOperation) -> Result<Self, Self::Error> {
48 let span = value.span();
49 match value.operator {
50 BinaryOperator::Glue(token) => Ok(Self {
51 span,
52 lhs: value.lhs.try_into()?,
53 glue: token,
54 rhs: value.rhs.try_into()?,
55 }),
56 _ => Err(SyntaxError::new(
57 value.span(),
58 "incorrect operator for glue pattern",
59 )),
60 }
61 }
62}
63
64#[cfg(test)]
65mod test {
66 use super::*;
67
68 test_parse!(glue_pattern_left_str: r#""hello" <> x"# => Pattern::parse => Pattern::Glue(GluePattern { .. }));
69 test_parse!(glue_pattern_right_str: r#"x <> "hello""# => Pattern::parse => Pattern::Glue(GluePattern { .. }));
70 test_parse!(glue_pattern_no_str: r#"x <> y"# => Pattern::parse => Pattern::Glue(GluePattern { .. }));
71 test_parse!(glue_pattern_both_str: r#""x" <> "y""# => Pattern::parse => Pattern::Glue(GluePattern { .. }));
72 test_parse!(glue_pattern_not_str: r#"1 <> x"# => Pattern::parse => Pattern::Glue(GluePattern { .. }));
73 test_parse_error!(glue_pattern_incomplete: r#"x <>"# => Pattern::parse);
74 test_parse_error!(glue_pattern_invalid_expr: r#"x <> {}"# => Pattern::parse);
75}