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
/// Enum representing all the tokens the Lexer can produce
#[derive(Debug, PartialEq, Clone)]
pub enum TokenKind {
    Identifier(String),
    Literal(bool),
    Not,
    And,
    Or,
    Implies,
    IfAndOnlyIf,
    OpenParen,
    CloseParen
}

/// An [`Span`] represents a range of characters in the source code
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Span {
    pub start: usize,
    pub end: usize
}

/// Represents the tokens that the [`Lexer`] will produce and the [`Parser`]
/// will consume
#[derive(Debug, Clone)]
pub struct Token {
    pub kind: TokenKind,
    pub span: Span
}

impl Token {
    pub fn new<T>(kind: TokenKind, span: T) -> Token
    where T: Into<Span> {
        Token { kind, span: span.into() }
    }
}

// -> Other traits implementations

impl std::fmt::Display for TokenKind {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            TokenKind::Identifier(i) => write!(f, "Identifier({})", i),
            TokenKind::Literal(l) => write!(f, "Literal({})", l),
            TokenKind::Not => write!(f, "Not()"),
            TokenKind::And => write!(f, "And()"),
            TokenKind::Or => write!(f, "Or()"),
            TokenKind::Implies => write!(f, "Implies()"),
            TokenKind::IfAndOnlyIf => write!(f, "IfAndOnlyIf()"),
            TokenKind::OpenParen => write!(f, "OpenParen()"),
            TokenKind::CloseParen => write!(f, "CloseParen()"),
        }
    }
}

impl From<(usize, usize)> for Span {
    fn from(value: (usize, usize)) -> Self {
        Span { start: value.0, end: value.1 }
    }
}