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
use crate::lexer::Token;
use crate::parser::ParseTreeType;
use anyhow::Result;
use id_tree::{Node, NodeId, Tree};

///
/// The type of elements in the parser's parse tree stack.
/// * 'Nd' references nodes not yet inserted into the parse tree.
/// * 'Id' holds node ids to nodes that are already part of the parse tree.
///
#[derive(Debug)]
pub enum ParseTreeStackEntry<'t> {
    /// The node is not inserted into the parse tree yet.
    /// Thus we can access it directly.
    Nd(Node<ParseTreeType<'t>>),

    /// The node is already inserted into the parse tree.
    /// Wee need to lookup the node in the parse tree via the NodeId.
    Id(NodeId),
}

impl<'t> ParseTreeStackEntry<'t> {
    ///
    /// Abstracts from the actual place where the node exists and returns the
    /// inner ParseTreeType.
    ///
    /// `'a` refers to the lifetime of self.
    /// `'b` refers to the lifetime of the parse tree.
    ///
    pub fn get_parse_tree_type<'a, 'b>(
        &'a self,
        parse_tree: &'b Tree<ParseTreeType<'t>>,
    ) -> &'a ParseTreeType
    where
        'b: 'a,
    {
        match self {
            Self::Nd(n) => n.data(),
            Self::Id(i) => parse_tree.get(i).unwrap().data(),
        }
    }

    ///
    /// Tries to access the OwnedToken of the ParseTreeStackEntry.
    /// Can fail if the entry is no terminal (i.e. a non-terminal).
    ///
    /// `'a` refers to the lifetime of self.
    /// `'b` refers to the lifetime of the parse tree.
    ///
    pub fn token<'a, 'b>(&'a self, parse_tree: &'b Tree<ParseTreeType<'t>>) -> Result<&'a Token<'t>>
    where
        'b: 'a,
    {
        match self {
            Self::Nd(n) => n.data().token(),
            Self::Id(i) => parse_tree.get(i).unwrap().data().token(),
        }
    }

    ///
    /// Tries to access the text of the ParseTreeStackEntry.
    /// Can fail if the entry is no terminal (i.e. a non-terminal).
    ///
    /// `'a` refers to the lifetime of self.
    /// `'b` refers to the lifetime of the parse tree.
    ///
    pub fn symbol<'a, 'b>(&'a self, parse_tree: &'b Tree<ParseTreeType>) -> Result<&'a str>
    where
        'b: 'a,
    {
        match self {
            Self::Nd(node) => {
                let token = node.data().token()?;
                Ok(token.symbol)
            }
            Self::Id(i) => {
                let node = parse_tree.get(i)?;
                let token = node.data().token()?;
                Ok(token.symbol)
            }
        }
    }
}