2024-01-31 00:24:18 -08:00
|
|
|
use std::fmt;
|
|
|
|
|
|
|
|
use crate::util::intersperse_option;
|
|
|
|
|
2024-01-31 02:15:50 -08:00
|
|
|
#[derive(Debug, Clone)]
|
2024-01-31 00:24:18 -08:00
|
|
|
pub struct Representation {
|
|
|
|
production_output: EBNF,
|
|
|
|
}
|
2024-01-30 00:15:00 -08:00
|
|
|
|
|
|
|
impl Representation {
|
2024-01-31 00:24:18 -08:00
|
|
|
pub fn show(&self) -> String {
|
|
|
|
self.production_output.to_string()
|
2024-01-30 00:15:00 -08:00
|
|
|
}
|
|
|
|
|
2024-01-31 02:15:50 -08:00
|
|
|
pub fn production(&self) -> EBNF {
|
|
|
|
self.production_output.clone()
|
|
|
|
}
|
|
|
|
|
2024-01-30 00:15:00 -08:00
|
|
|
pub fn new() -> Self {
|
2024-01-31 00:24:18 -08:00
|
|
|
Self {
|
|
|
|
production_output: EBNF::None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-31 02:15:50 -08:00
|
|
|
pub fn with_production(self, production_output: EBNF) -> Self {
|
|
|
|
Self {
|
|
|
|
production_output,
|
|
|
|
..self
|
|
|
|
}
|
2024-01-31 00:24:18 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-31 02:15:50 -08:00
|
|
|
#[derive(Debug, Clone)]
|
2024-01-31 00:24:18 -08:00
|
|
|
pub enum EBNF {
|
|
|
|
None,
|
2024-01-31 00:31:16 -08:00
|
|
|
Nonterminal(String),
|
2024-01-31 00:24:18 -08:00
|
|
|
CharTerminal(char),
|
2024-01-31 00:47:45 -08:00
|
|
|
StringTerminal(String),
|
2024-01-31 03:13:46 -08:00
|
|
|
LabeledTerminal(String),
|
2024-01-31 00:24:18 -08:00
|
|
|
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, "")
|
|
|
|
}
|
2024-01-31 00:31:16 -08:00
|
|
|
EBNF::Nonterminal(name) => write!(f, "{name}"),
|
2024-01-31 00:47:45 -08:00
|
|
|
EBNF::StringTerminal(term) => write!(f, r#""{term}""#),
|
2024-01-31 03:13:46 -08:00
|
|
|
EBNF::LabeledTerminal(s) => write!(f, "<{s}>"),
|
2024-01-31 00:24:18 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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'");
|
2024-01-31 00:31:16 -08:00
|
|
|
|
|
|
|
let example = EBNF::Alternation(vec![
|
|
|
|
EBNF::Nonterminal("other-rule".into()),
|
|
|
|
EBNF::CharTerminal('q'),
|
|
|
|
EBNF::CharTerminal('m'),
|
2024-01-31 00:47:45 -08:00
|
|
|
EBNF::StringTerminal("focus".into()),
|
2024-01-31 00:31:16 -08:00
|
|
|
]);
|
2024-01-31 00:47:45 -08:00
|
|
|
assert_eq!(example.to_string(), "other-rule | 'q' | 'm' | \"focus\"");
|
2024-01-30 00:15:00 -08:00
|
|
|
}
|
|
|
|
}
|