starting ebnf representation

This commit is contained in:
Greg Shuflin 2024-01-31 00:24:18 -08:00
parent 4e813a7efd
commit 698e05081a
3 changed files with 105 additions and 4 deletions

View File

@ -7,6 +7,7 @@ mod parser;
mod primitives;
mod representation;
mod sequence;
mod util;
#[cfg(test)]
mod test;

View File

@ -1,12 +1,66 @@
use std::fmt;
use crate::util::intersperse_option;
#[derive(Debug)]
pub struct Representation {}
pub struct Representation {
production_output: EBNF,
}
impl Representation {
pub fn show(&self) {
println!("Not done");
pub fn show(&self) -> String {
self.production_output.to_string()
}
pub fn new() -> Self {
Self {}
Self {
production_output: EBNF::None,
}
}
pub fn with_production(production_output: EBNF) -> Self {
Self { production_output }
}
}
#[derive(Debug)]
pub enum EBNF {
None,
CharTerminal(char),
Alternation(Vec<EBNF>),
}
impl fmt::Display for EBNF {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
EBNF::None => write!(f, "none"),
EBNF::CharTerminal(ch) => write!(f, "'{ch}'"),
EBNF::Alternation(items) => {
for item in intersperse_option(items.iter()) {
match item {
None => write!(f, " | ")?,
Some(item) => write!(f, "{item}")?,
}
}
write!(f, "")
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ebnf_print() {
let example = EBNF::Alternation(vec![
EBNF::CharTerminal('f'),
EBNF::CharTerminal('a'),
EBNF::CharTerminal('k'),
EBNF::CharTerminal('e'),
]);
assert_eq!(example.to_string(), "'f' | 'a' | 'k' | 'e'");
}
}

46
src/util.rs Normal file
View File

@ -0,0 +1,46 @@
use std::iter::Peekable;
pub(crate) fn intersperse_option<I: Iterator>(iterator: I) -> impl Iterator<Item = Option<I::Item>>
where
I::Item: Clone,
{
intersperse(iterator.map(Some), None)
}
pub(crate) fn intersperse<I: Iterator>(iterator: I, separator: I::Item) -> Intersperse<I>
where
I::Item: Clone,
{
Intersperse {
inner: iterator.peekable(),
separator,
needs_sep: false,
}
}
pub struct Intersperse<I>
where
I: Iterator,
{
inner: Peekable<I>,
separator: I::Item,
needs_sep: bool,
}
impl<I> Iterator for Intersperse<I>
where
I: Iterator,
I::Item: Clone,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.needs_sep && self.inner.peek().is_some() {
self.needs_sep = false;
Some(self.separator.clone())
} else {
self.needs_sep = true;
self.inner.next()
}
}
}