1use std::fmt::{Display, Formatter, Write};
9use std::iter::Cloned;
10use std::ops::Index;
11use std::slice::Iter;
12use crate::prelude::*;
13
14#[derive(Debug, Clone, PartialEq, Eq, Hash)]
26pub struct ProductionString {
27 symbols: Vec<Symbol>
28}
29
30impl ProductionString {
31 pub fn new() -> Self {
33 ProductionString {
34 symbols: Vec::new()
35 }
36 }
37
38 #[inline]
41 pub fn empty() -> Self {
42 ProductionString::new()
43 }
44
45 #[inline]
48 pub fn is_empty(&self) -> bool {
49 self.symbols.is_empty()
50 }
51
52 #[inline]
54 pub fn len(&self) -> usize {
55 self.symbols.len()
56 }
57
58 #[inline]
60 pub fn symbols(&self) -> &Vec<Symbol> {
61 &self.symbols
62 }
63
64 #[inline]
66 pub fn push_symbol(&mut self, symbol: Symbol) {
67 self.symbols.push(symbol);
68 }
69
70 #[inline]
72 pub fn iter(&self) -> Iter<'_, Symbol> {
73 self.symbols.iter()
74 }
75}
76
77impl Default for ProductionString {
78 fn default() -> Self {
79 ProductionString::new()
80 }
81}
82
83impl From<Vec<Symbol>> for ProductionString {
84 fn from(value: Vec<Symbol>) -> Self {
85 ProductionString {
86 symbols: value
87 }
88 }
89}
90
91impl Index<usize> for ProductionString {
92 type Output = Symbol;
93
94 fn index(&self, index: usize) -> &Self::Output {
95 &self.symbols[index]
96 }
97}
98
99
100impl From<Symbol> for ProductionString {
101 fn from(value: Symbol) -> Self {
102 ProductionString {
103 symbols: vec![value]
104 }
105 }
106}
107
108impl IntoIterator for ProductionString {
109 type Item = Symbol;
110 type IntoIter = std::vec::IntoIter<Self::Item>;
111
112 fn into_iter(self) -> Self::IntoIter {
113 self.symbols.into_iter()
114 }
115}
116
117impl<'a> IntoIterator for &'a ProductionString {
118 type Item = Symbol;
119 type IntoIter = Cloned<Iter<'a, Self::Item>>;
120
121 fn into_iter(self) -> Self::IntoIter {
122 self.symbols.iter().cloned()
123 }
124}
125
126impl Display for ProductionString {
127 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
128 let mut first = true;
129 for symbol in self.symbols() {
130 if !first {
131 f.write_char(' ')?;
132 } else {
133 first = false;
134 }
135 f.write_str(symbol.to_string().as_str())?;
136 }
137
138 Ok(())
139
140 }
141}
142
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn empty_string_is_empty() {
150 let empty = ProductionString::empty();
151
152 assert!(empty.is_empty());
153 assert_eq!(empty.len(), 0);
154 }
155}