1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use crate::lexer::token::LexToken;
use crate::parser::Parser;
use crate::syntax::{Delimiter, NonEmptySyntax, Syntax};

use lark_debug_derive::DebugWith;
use lark_error::ErrorReported;
use lark_span::{FileName, Spanned};

macro_rules! sigil_type {
    ($($v:vis struct $name:ident = ($kind:path, $token:expr);)*) => {
        $(
            #[derive(DebugWith)]
            $v struct $name;

            impl $name {
                $v const KIND: LexToken = $kind;
                $v const TEXT: &'static str = $token;
            }

            impl Syntax<'parse> for $name {
                type Data = Spanned<LexToken, FileName>;

                fn test(&mut self, parser: &Parser<'parse>) -> bool {
                    parser.is($kind) && parser.peek_str() == $name::TEXT
                }

                fn expect(&mut self, parser: &mut Parser<'parse>) -> Result<Self::Data, ErrorReported> {
                    if self.test(parser) {
                        Ok(parser.shift())
                    } else {
                        Err(parser.report_error(
                            format!("expected `{}`", $name::TEXT),
                            parser.peek_span(),
                        ))
                    }
                }
            }

            impl NonEmptySyntax<'parse> for $name { }
        )*
    }
}

sigil_type! {
    pub struct OpenCurly = (LexToken::Sigil, "{");
    pub struct CloseCurly = (LexToken::Sigil, "}");
    pub struct OpenParenthesis = (LexToken::Sigil, "(");
    pub struct CloseParenthesis = (LexToken::Sigil, ")");
    pub struct OpenSquare = (LexToken::Sigil, "[");
    pub struct CloseSquare = (LexToken::Sigil, "]");
    pub struct Colon = (LexToken::Sigil, ":");
    pub struct Semicolon = (LexToken::Sigil, ";");
    pub struct Comma = (LexToken::Sigil, ",");
    pub struct RightArrow = (LexToken::Sigil, "->");
    pub struct Dot = (LexToken::Sigil, ".");
    pub struct Let = (LexToken::Identifier, "let");
    pub struct ExclamationPoint = (LexToken::Sigil, "!");
    pub struct Plus = (LexToken::Sigil, "+");
    pub struct Minus = (LexToken::Sigil, "-");
    pub struct Star = (LexToken::Sigil, "*");
    pub struct Slash = (LexToken::Sigil, "/");
    pub struct Equals = (LexToken::Sigil, "=");
}

#[derive(DebugWith)]
pub struct Curlies;

impl Delimiter<'parse> for Curlies {
    type Open = OpenCurly;
    type Close = CloseCurly;

    fn open_syntax(&self) -> Self::Open {
        OpenCurly
    }

    fn close_syntax(&self) -> Self::Close {
        CloseCurly
    }
}

#[derive(DebugWith)]
pub struct Parentheses;

impl Delimiter<'parse> for Parentheses {
    type Open = OpenParenthesis;
    type Close = CloseParenthesis;

    fn open_syntax(&self) -> Self::Open {
        OpenParenthesis
    }

    fn close_syntax(&self) -> Self::Close {
        CloseParenthesis
    }
}