parol 4.4.0

LL(k) and LALR(1) parser generator for Rust
Documentation
use std::{
    fmt::{Debug, Display, Error, Formatter},
    ops::Index,
};

use parol_runtime::NonTerminalIndex;

#[derive(Debug, Default, Clone)]
pub struct StrVec {
    vec: Vec<String>,
    indent: String,
    indent_first_line: bool,
}

impl Display for StrVec {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
        for (i, s) in self.vec.iter().enumerate() {
            let indent = if i == 0 && !self.indent_first_line {
                ""
            } else {
                &self.indent
            };
            writeln!(f, "{indent}{s}")?
        }
        Ok(())
    }
}

#[allow(dead_code)]
impl StrVec {
    pub fn new(indent: usize) -> Self {
        Self {
            vec: Vec::new(),
            indent: Self::build_indent(indent),
            indent_first_line: true,
        }
    }
    pub fn first_line_no_indent(mut self) -> Self {
        self.indent_first_line = false;
        self
    }
    pub fn push(&mut self, s: String) {
        self.vec.push(s);
    }
    pub fn max_content_len(&self) -> usize {
        self.vec
            .iter()
            .fold(0usize, |acc, e| std::cmp::max(acc, e.len()))
    }
    pub fn len(&self) -> usize {
        self.vec.len()
    }
    pub fn is_empty(&self) -> bool {
        self.vec.is_empty()
    }
    pub fn iter(&self) -> StrVecIterator<'_> {
        StrVecIterator { vec: self, pos: 0 }
    }
    fn build_indent(amount: usize) -> String {
        let space = " ".to_string();
        space.repeat(amount)
    }

    pub fn pop(&mut self) -> Option<String> {
        self.vec.pop()
    }

    pub(crate) fn join(&self, arg: &str) -> String {
        self.vec.join(arg)
    }
}

pub struct StrVecIterator<'a> {
    vec: &'a StrVec,
    pos: usize,
}

impl<'a> Iterator for StrVecIterator<'a> {
    type Item = &'a String;
    fn next(&mut self) -> std::option::Option<<Self as std::iter::Iterator>::Item> {
        let current_pos = self.pos;
        if self.vec.len() > current_pos {
            self.pos += 1;
            Some(&self.vec.vec[current_pos])
        } else {
            None
        }
    }
}

impl<'a> IntoIterator for &'a StrVec {
    type Item = &'a String;
    type IntoIter = StrVecIterator<'a>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl Index<NonTerminalIndex> for StrVec {
    type Output = String;
    fn index(&self, index: NonTerminalIndex) -> &Self::Output {
        &self.vec[index]
    }
}

impl FromIterator<String> for StrVec {
    fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
        Self {
            vec: iter.into_iter().collect(),
            indent: Self::build_indent(0),
            indent_first_line: true,
        }
    }
}