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
use crate::analysis::k_tuple::TerminalMappings;
use crate::grammar::cfg::TerminalIndexFn;
use crate::{Symbol, Terminal};
use parol_runtime::lexer::EOI;
use parol_runtime::TerminalIndex;
use std::fmt::{Debug, Display, Error, Formatter};

///
/// Epsilon token constant
/// Can be contained in FIRST sets
///
pub const EPS: TerminalIndex = TerminalIndex::MAX;

///
/// Invalid token, used as placeholder and initial value in Default
pub(crate) const INVALID: TerminalIndex = TerminalIndex::MAX - 1;

// ---------------------------------------------------
// Part of the Public API
// *Changes will affect crate's version according to semver*
// ---------------------------------------------------
///
/// Internal data structure to represent a compiled terminal, a TerminalIndex.
///
#[derive(Default, Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub struct CompiledTerminal(pub TerminalIndex);

impl CompiledTerminal {
    /// Creates a new item from a Symbol
    pub fn create<F, R>(s: &Symbol, terminal_index_resolver: R) -> Self
    where
        R: AsRef<F>,
        F: TerminalIndexFn,
    {
        match s {
            Symbol::T(Terminal::Trm(t, k, ..)) => {
                Self(terminal_index_resolver.as_ref().terminal_index(t, *k))
            }
            Symbol::T(Terminal::End) => Self(EOI),
            _ => panic!("Unexpected symbol type: {:?}", s),
        }
    }
}

impl AsRef<TerminalIndex> for CompiledTerminal {
    fn as_ref(&self) -> &TerminalIndex {
        &self.0
    }
}

impl Display for CompiledTerminal {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
        write!(f, "{}", self.0)
    }
}

impl From<TerminalIndex> for CompiledTerminal {
    fn from(t: TerminalIndex) -> Self {
        Self(t)
    }
}

impl TerminalMappings<CompiledTerminal> for CompiledTerminal {
    #[inline]
    fn eps() -> CompiledTerminal {
        Self(EPS)
    }

    #[inline]
    fn end() -> CompiledTerminal {
        Self(EOI)
    }

    #[inline]
    fn is_eps(&self) -> bool {
        self.0 == EPS
    }

    #[inline]
    fn is_end(&self) -> bool {
        self.0 == EOI
    }

    #[inline]
    fn is_inv(&self) -> bool {
        self.0 == INVALID
    }
}