use std::fmt::{Display, Formatter, Write};
use std::iter::Cloned;
use std::ops::Index;
use std::slice::Iter;
use crate::prelude::*;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ProductionString {
symbols: Vec<Symbol>
}
impl ProductionString {
pub fn new() -> Self {
ProductionString {
symbols: Vec::new()
}
}
#[inline]
pub fn empty() -> Self {
ProductionString::new()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.symbols.is_empty()
}
#[inline]
pub fn len(&self) -> usize {
self.symbols.len()
}
#[inline]
pub fn symbols(&self) -> &Vec<Symbol> {
&self.symbols
}
#[inline]
pub fn push_symbol(&mut self, symbol: Symbol) {
self.symbols.push(symbol);
}
#[inline]
pub fn iter(&self) -> Iter<'_, Symbol> {
self.symbols.iter()
}
}
impl Default for ProductionString {
fn default() -> Self {
ProductionString::new()
}
}
impl From<Vec<Symbol>> for ProductionString {
fn from(value: Vec<Symbol>) -> Self {
ProductionString {
symbols: value
}
}
}
impl Index<usize> for ProductionString {
type Output = Symbol;
fn index(&self, index: usize) -> &Self::Output {
&self.symbols[index]
}
}
impl From<Symbol> for ProductionString {
fn from(value: Symbol) -> Self {
ProductionString {
symbols: vec![value]
}
}
}
impl IntoIterator for ProductionString {
type Item = Symbol;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.symbols.into_iter()
}
}
impl<'a> IntoIterator for &'a ProductionString {
type Item = Symbol;
type IntoIter = Cloned<Iter<'a, Self::Item>>;
fn into_iter(self) -> Self::IntoIter {
self.symbols.iter().cloned()
}
}
impl Display for ProductionString {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut first = true;
for symbol in self.symbols() {
if !first {
f.write_char(' ')?;
} else {
first = false;
}
f.write_str(symbol.to_string().as_str())?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty_string_is_empty() {
let empty = ProductionString::empty();
assert!(empty.is_empty());
assert_eq!(empty.len(), 0);
}
}