#![deny(missing_docs)]
use derive_destructure::destructure;
use std::rc::Rc;
#[derive(Clone, Debug)]
pub enum Token {
Symbol(String),
List(Vec<Token>),
}
use Token::*;
impl Token {
pub fn symbol(self) -> Option<String> {
match self {
Symbol(string) => Some(string),
List(_) => None,
}
}
pub fn symbol_ref(&self) -> Option<&String> {
match self {
Symbol(string) => Some(string),
List(_) => None,
}
}
pub fn list(self) -> Option<Vec<Token>> {
match self {
Symbol(_) => None,
List(tokens) => Some(tokens),
}
}
pub fn list_ref(&self) -> Option<&Vec<Token>> {
match self {
Symbol(_) => None,
List(tokens) => Some(tokens),
}
}
}
#[derive(Copy, Clone, Debug)]
pub enum ParsingState {
Fine(bool),
Finished,
Delegate(char),
}
use ParsingState::*;
mod implement_display {
use std::fmt::{Display, Formatter, Result};
use crate::Token;
impl Display for Token {
fn fmt(&self, f: &mut Formatter) -> Result {
match self {
Token::Symbol(string) => write!(f, "'{}'", string),
Token::List(vec) => {
let mut first = true;
write!(f, "(").expect("Unexpected end of file");
for tok in vec.iter() {
if !first {
write!(f, " ").expect("Unexpected end of file");
} else {
first = false;
}
let result = write!(f, "{}", tok);
if result.is_err() {
return result;
}
}
write!(f, ")")
}
}
}
}
}
use std::collections::HashMap;
pub struct MacroMap<T>(HashMap<char, Rc<dyn Parser<T>>>);
impl<T: Iterator<Item = char>> MacroMap<T> {
pub fn new() -> Self {
MacroMap(HashMap::new())
}
pub fn set(
&mut self,
char: char,
value: Option<impl Parser<T> + 'static>,
) -> Option<Rc<dyn Parser<T>>> {
if let Some(value) = value {
self.0.insert(char, Rc::new(value))
} else {
self.0.remove(&char)
}
}
pub fn with(mut self, char: char, value: impl Parser<T> + 'static) -> Self {
self.0.insert(char, Rc::new(value));
self
}
pub fn with_separating_whitespaces(self) -> Self {
self.with(' ', EmptyParser(Fine(false)))
.with('\n', EmptyParser(Fine(false)))
.with('\t', EmptyParser(Fine(false)))
}
pub fn with_lists(self, start_char: char, end_char: char) -> Self {
self.with(
start_char,
ListWrapper {
prefix: None,
parser: DelimitedListParser(end_char),
},
)
.with(end_char, PanicParser)
}
pub fn with_macro_characters_ignored(self, delimiter: char) -> Self {
self.with(delimiter, DelimitedSymbolParser)
}
pub fn with_strings(
self,
prefix: String,
delimiter: char,
replacements: Vec<(String, String)>,
) -> Self {
self.with(
delimiter,
ListWrapper {
prefix: Some(prefix),
parser: SymbolReplacer {
replacements,
parser: DelimitedSymbolParser,
},
},
)
}
pub fn with_comments(self, comment_char: char) -> Self {
self.with(comment_char, CommentParser)
}
pub fn with_infix(self, infix_char: char, kind: InfixKind, right: bool) -> Self {
self.with(infix_char, InfixParser(kind, right))
}
pub fn from_hash_map(map: HashMap<char, Rc<dyn Parser<T>>>) -> Self {
MacroMap(map)
}
pub fn insert(
&mut self,
char: char,
value: Option<Rc<dyn Parser<T>>>,
) -> Option<Rc<dyn Parser<T>>> {
if let Some(value) = value {
self.0.insert(char, value)
} else {
self.0.remove(&char)
}
}
}
pub struct ParsingContext<T: Iterator<Item = char>> {
char: Option<char>,
chars: T,
maps: Vec<MacroMap<T>>,
}
#[derive(destructure)]
pub struct MacroHandle<'a, T: Iterator<Item = char>>
where
ParsingContext<T>: 'a,
{
char: char,
context: &'a mut ParsingContext<T>,
parser: Option<Rc<dyn Parser<T>>>,
}
use std::result::Result;
impl<'a, T: Iterator<Item = char>> MacroHandle<'a, T> {
pub fn call(self, result: &mut Vec<Token>) -> Result<ParsingState, char> {
let (char, context, parser) = self.destructure();
if let Some(parser) = parser {
Ok(parser.parse(Some(char), result, context))
} else {
Err(char)
}
}
}
impl<'a, T: Iterator<Item = char>> Drop for MacroHandle<'a, T> {
fn drop(&mut self) {
self.context.char = Some(self.char);
}
}
impl<T: Iterator<Item = char>> ParsingContext<T> {
pub fn parse(&mut self, tokens: &mut Vec<Token>) -> Option<MacroHandle<T>> {
let mut symbol = String::new();
let (char, parser) = loop {
let char = if let Some(old_char) = self.char {
self.char = None;
old_char
} else {
if let Some(next) = self.chars.next() {
next
} else {
if !symbol.is_empty() {
tokens.push(Symbol(symbol));
}
return None;
}
};
let parser = if let Some(map) = self.maps.last() {
map.0.get(&char).cloned()
} else {
None
};
if parser.is_none() {
symbol = format!("{}{}", symbol, char);
} else {
break (char, parser);
}
};
if !symbol.is_empty() {
tokens.push(Symbol(symbol));
}
Some(MacroHandle {
char,
context: self,
parser,
})
}
pub fn set(
&mut self,
char: char,
value: Option<impl Parser<T> + 'static>,
) -> Option<Rc<dyn Parser<T>>> {
if let Some(map) = self.maps.last_mut() {
map.set(char, value)
} else {
None
}
}
pub fn insert(
&mut self,
char: char,
value: Option<Rc<dyn Parser<T>>>,
) -> Option<Rc<dyn Parser<T>>> {
if let Some(map) = self.maps.last_mut() {
map.insert(char, value)
} else {
None
}
}
pub fn push(&mut self, map: MacroMap<T>) {
self.maps.push(map);
}
pub fn pop(&mut self) -> Option<MacroMap<T>> {
self.maps.pop()
}
}
pub fn parse<T: IntoIterator<Item = char>>(
stream: T,
parser: impl Parser<T::IntoIter>,
map: MacroMap<T::IntoIter>,
) -> Vec<Token> {
let mut context = ParsingContext {
char: None,
chars: stream.into_iter(),
maps: vec![map],
};
let mut tokens = Vec::new();
parser.parse(None, &mut tokens, &mut context);
tokens
}
pub trait Parser<T: Iterator<Item = char>> {
fn parse(
&self,
char: Option<char>,
result: &mut Vec<Token>,
context: &mut ParsingContext<T>,
) -> ParsingState;
}
use parsers::*;
pub mod parsers {
use super::*;
pub struct EmptyParser(pub ParsingState);
impl<T: Iterator<Item = char>> Parser<T> for EmptyParser {
fn parse(
&self,
_char: Option<char>,
_result: &mut Vec<Token>,
_context: &mut ParsingContext<T>,
) -> ParsingState {
self.0
}
}
pub struct PanicParser;
impl<T: Iterator<Item = char>> Parser<T> for PanicParser {
fn parse(
&self,
char: Option<char>,
_result: &mut Vec<Token>,
_context: &mut ParsingContext<T>,
) -> ParsingState {
panic!("Invalid macro character {:?}", char)
}
}
pub struct DelegateParser;
impl<T: Iterator<Item = char>> Parser<T> for DelegateParser {
fn parse(
&self,
char: Option<char>,
_result: &mut Vec<Token>,
_context: &mut ParsingContext<T>,
) -> ParsingState {
Delegate(char.expect("Delegate as main parser not possible"))
}
}
pub struct DelimitedSymbolParser;
impl<T: Iterator<Item = char>> Parser<T> for DelimitedSymbolParser {
fn parse(
&self,
char: Option<char>,
result: &mut Vec<Token>,
context: &mut ParsingContext<T>,
) -> ParsingState {
let char = char.expect("Delimited Symbol parsers are not allowed as single");
context.push(MacroMap::new().with(char, DelegateParser));
let state = loop {
if let Some(handle) = context.parse(result) {
if let Delegate(c) = handle.call(&mut Vec::new()).unwrap() {
if c == char {
break Fine(true);
}
}
} else {
panic!("End of file inside symbol");
}
};
context.pop();
return state;
}
}
pub struct CommentParser;
impl<T: Iterator<Item = char>> Parser<T> for CommentParser {
fn parse(
&self,
_char: Option<char>,
_result: &mut Vec<Token>,
context: &mut ParsingContext<T>,
) -> ParsingState {
context.push(MacroMap::new().with('\n', DelegateParser));
let state = loop {
if let Some(handle) = context.parse(&mut Vec::new()) {
if let Delegate('\n') = handle.call(&mut Vec::new()).unwrap() {
break Fine(false);
}
} else {
break Finished;
}
};
context.pop();
return state;
}
}
pub struct ListWrapper<P> {
pub prefix: Option<String>,
pub parser: P,
}
impl<T: Iterator<Item = char>, P: Parser<T>> Parser<T> for ListWrapper<P> {
fn parse(
&self,
char: Option<char>,
result: &mut Vec<Token>,
context: &mut ParsingContext<T>,
) -> ParsingState {
let mut contents = Vec::new();
let Self { prefix, parser } = self;
contents.extend(prefix.into_iter().map(|name| Token::Symbol(name.clone())));
let state = parser.parse(char, &mut contents, context);
result.push(List(contents));
state
}
}
pub struct SymbolReplacer<P> {
pub replacements: Vec<(String, String)>,
pub parser: P,
}
impl<T: Iterator<Item = char>, P: Parser<T>> Parser<T> for SymbolReplacer<P> {
fn parse(
&self,
char: Option<char>,
result: &mut Vec<Token>,
context: &mut ParsingContext<T>,
) -> ParsingState {
let Self {
replacements,
parser,
} = self;
let state = parser.parse(char, result, context);
if let Some(Symbol(name)) = result.last_mut() {
for (from, to) in replacements {
*name = name.replace(&from[..], &to[..]);
}
}
state
}
}
pub struct DelimitedListParser(pub char);
impl<T: Iterator<Item = char>> Parser<T> for DelimitedListParser {
fn parse(
&self,
char: Option<char>,
result: &mut Vec<Token>,
context: &mut ParsingContext<T>,
) -> ParsingState {
let reset = context.set(self.0, Some(DelegateParser));
let state = loop {
if let Some(handle) = context.parse(result) {
let state = handle.call(result).unwrap();
match state {
Fine(_) => (),
Finished => {
if char.is_none() {
break Finished;
} else {
panic!("End of file inside list")
}
}
Delegate(char) => {
if char == self.0 {
break Fine(true);
} else {
panic!("Unexpected delegate")
}
}
}
} else {
if char.is_none() {
break Finished;
} else {
panic!("End of file inside list")
}
}
};
context.insert(self.0, reset);
state
}
}
pub enum InfixKind {
List,
Prefix(String),
Append,
}
pub struct InfixParser(pub InfixKind, pub bool);
impl<T: Iterator<Item = char>> Parser<T> for InfixParser {
fn parse(
&self,
_char: Option<char>,
result: &mut Vec<Token>,
context: &mut ParsingContext<T>,
) -> ParsingState {
let last = result.pop().expect("Infix operator cannot stand alone");
let mut new_list = if let (InfixKind::Append, false) = (&self.0, self.1) {
last.list().expect(
"First argument of left associative infix append is required to be a list",
)
} else {
let mut new_list = Vec::new();
if let InfixKind::Prefix(op) = &self.0 {
new_list.push(Symbol(op.clone()));
}
new_list.push(last);
new_list
};
let state = loop {
let count = new_list.len();
let handle = context.parse(&mut new_list);
if count < new_list.len() {
break Fine(true);
}
if let Some(handle) = handle {
let state = handle.call(&mut new_list).unwrap();
if let Fine(false) = state {
continue;
}
break state;
} else {
break Finished;
}
};
if self.1 {
if let Fine(_) = state {
let mut next_list = Vec::new();
next_list.push(new_list.pop().unwrap());
let state = loop {
if let Some(handle) = context.parse(&mut next_list) {
let state = handle.call(&mut next_list).unwrap();
if let Fine(_) = state {
continue;
}
break state;
} else {
break Finished;
}
};
let mut append = next_list.into_iter();
let first = append.next().unwrap();
if let (InfixKind::Append, true) = (&self.0, self.1) {
new_list.extend(first.list().expect("Last argument of right associative infix append is required to be a list"));
} else {
new_list.push(first);
}
result.push(List(new_list));
result.extend(append);
return state;
}
}
result.push(List(new_list));
return state;
}
}
}