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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
//! This file implements a type of labels that could be used as the
//! labels of a parse forest.
use super::*;
/// The actual label of a grammar label.
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub enum GrammarLabelType {
/// A terminal or a non-terminal.
TNT(TNT),
/// A rule position.
Rule(usize),
}
impl GrammarLabelType {
/// Return the name of this label with the help of the associated
/// grammar.
pub fn name(&self, grammar: &Grammar) -> Result<String, Error> {
match self {
Self::TNT(tnt) => grammar.name_of_tnt(*tnt),
Self::Rule(pos) => grammar.rule_pos_to_string(*pos),
}
}
}
/// The label to be used in a forest.
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct GrammarLabel {
/// The actual label.
label: GrammarLabelType,
/// The start in the input that this label correponds to.
start: usize,
/// The end in the input that this label correponds to.
end: Option<usize>,
/// A node in the forest might be a packed node.
packed_p: bool,
}
impl core::fmt::Display for GrammarLabel {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
// Simply displaying this without the help of a grammar is not
// of much help, so we just use the debug method to cheat,
// haha.
write!(f, "{:?}", self)
}
}
impl GrammarLabel {
/// Construct a new label.
pub fn new(label: GrammarLabelType, start: usize) -> Self {
let end = None;
let packed_p = false;
Self {
label,
start,
end,
packed_p,
}
}
/// Return the end in the input.
pub fn end(&self) -> Option<usize> {
self.end
}
/// Return the start in the input.
pub fn start(&self) -> usize {
self.start
}
/// Return the actual label.
pub fn label(&self) -> GrammarLabelType {
self.label
}
/// Update the end.
pub fn set_end(&mut self, end: usize) {
self.end = Some(end);
}
/// Check whether the node is a packed node.
pub fn is_packed(&self) -> bool {
self.packed_p
}
/// Update the packed status.
pub fn set_packed_p(&mut self, packed_p: bool) {
self.packed_p = packed_p;
}
/// Return a string description with the help of the associated
/// grammar.
pub fn to_string(&self, grammar: &Grammar) -> Result<String, Error> {
// REVIEW: It needs at least 34 bytes, so we just double it.
// Of course we can also calculate the length exactly, but
// this can be postponed till later.
let mut s = String::with_capacity(68);
s.push_str("a ");
if self.is_packed() {
s.push_str("packed ");
} else {
s.push_str("normal ");
}
s.push_str("node labelled ");
s.push_str(&self.label().name(grammar)?);
s.push_str(" from ");
s.push_str(&format!("{} ", self.start()));
if let Some(end) = self.end() {
s.push_str(&format!("to {end}"));
} else {
s.push_str("onwards");
}
Ok(s)
}
}
|