#![deny(missing_docs)]
#[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),
}
}
}
pub enum ParsingState {
Fine,
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 type MacroFn<T> = fn(
input_char: Option<char>,
token_list: &mut Vec<Token>,
parser: &mut Parser<T>,
) -> ParsingState;
pub struct MacroMap<T: Iterator<Item = char>>(HashMap<char, MacroFn<T>>);
impl<T: Iterator<Item = char>> MacroMap<T> {
pub fn new() -> Self {
MacroMap(HashMap::new())
}
pub fn with_separating_whitespaces(mut self) -> Self {
self.set(' ', Some(parse_empty));
self.set('\n', Some(parse_empty));
self.set('\t', Some(parse_empty));
self
}
pub fn with_lists(mut self, list_delimiter: char) -> Self {
self.set(list_delimiter, Some(parse_list));
self.set(
closing_bracket(list_delimiter).expect("Not a possible opening bracket"),
Some(parse_panic),
);
self
}
pub fn with_strings(mut self, string_delimiter: char) -> Self {
self.set(string_delimiter, Some(parse_string));
self
}
pub fn with_comments(mut self, comment_char: char) -> Self {
self.set(comment_char, Some(parse_comment));
self
}
pub fn with_infix_left(mut self, infix_char: char) -> Self {
self.set(infix_char, Some(parse_infix_left));
self
}
pub fn with_macro_character(mut self, char: char, value: MacroFn<T>) -> Self {
self.set(char, Some(value));
self
}
pub fn from_hash_map(map: HashMap<char, MacroFn<T>>) -> Self {
MacroMap(map)
}
pub fn set(&mut self, char: char, value: Option<MacroFn<T>>) -> Option<MacroFn<T>> {
if let Some(value) = value {
self.0.insert(char, value)
} else {
self.0.remove(&char)
}
}
}
pub struct Parser<T: Iterator<Item = char>> {
char: Option<char>,
chars: T,
map: MacroMap<T>,
}
pub struct CharHandle<'a, T: Iterator<Item = char>>
where
Parser<T>: 'a,
{
char: char,
parser: &'a mut Parser<T>,
fun: Option<MacroFn<T>>,
}
use std::result::Result;
impl<'a, T: Iterator<Item = char>> CharHandle<'a, T> {
pub fn char(self) -> char {
self.char
}
pub fn is_macro(&self) -> bool {
self.fun.is_some()
}
pub fn call(self, vec: &mut Vec<Token>) -> Result<ParsingState, char> {
let Self { char, parser, fun } = self;
if let Some(fun) = fun {
Ok(fun(Some(char), vec, parser))
} else {
Err(char)
}
}
pub fn discard(self) {
self.parser.char = Some(self.char);
}
}
impl<T: Iterator<Item = char>> Parser<T> {
pub fn get(&mut self) -> Option<CharHandle<T>> {
let char = if let Some(old_char) = self.char {
self.char = None;
old_char
} else {
self.chars.next()?
};
let fun = if self.map.0.contains_key(&char) {
Some(self.map.0[&char])
} else {
None
};
Some(CharHandle {
char,
parser: self,
fun,
})
}
pub fn set(&mut self, char: char, value: Option<MacroFn<T>>) -> Option<MacroFn<T>> {
self.map.set(char, value)
}
}
pub fn parse_sexp<T: IntoIterator<Item = char>>(
stream: T,
macro_fn: MacroFn<T::IntoIter>,
map: MacroMap<T::IntoIter>,
) -> Vec<Token> {
let mut parser = Parser {
chars: stream.into_iter(),
map,
char: None,
};
let mut tokens = Vec::new();
macro_fn(None, &mut tokens, &mut parser);
tokens
}
use crate::functions::*;
pub mod functions {
use super::*;
pub fn parse_empty<T: Iterator<Item = char>>(
_: Option<char>,
_: &mut Vec<Token>,
_: &mut Parser<T>,
) -> ParsingState {
Fine
}
pub fn parse_panic<T: Iterator<Item = char>>(
char: Option<char>,
_: &mut Vec<Token>,
_: &mut Parser<T>,
) -> ParsingState {
panic!("Invalid macro character {:?}", char)
}
pub fn parse_delegate<T: Iterator<Item = char>>(
char: Option<char>,
_: &mut Vec<Token>,
_: &mut Parser<T>,
) -> ParsingState {
Delegate(char.expect("Delegate as main function not possible"))
}
pub fn parse_string<T: Iterator<Item = char>>(
char: Option<char>,
vec: &mut Vec<Token>,
parser: &mut Parser<T>,
) -> ParsingState {
use std::str::FromStr;
let mut str = String::new();
loop {
if let Some(handle) = parser.get() {
let new_char = handle.char();
if let Some(char) = char {
if new_char == char {
let list = List(vec![
Symbol(String::from_str("string").unwrap()),
Symbol(str),
]);
vec.push(list);
return Fine;
}
}
str.push(new_char)
} else {
if char.is_none() {
let list = List(vec![
Symbol(String::from_str("string").unwrap()),
Symbol(str),
]);
vec.push(list);
return Fine;
} else {
panic!("End of file inside string");
}
}
}
}
pub fn parse_comment<T: Iterator<Item = char>>(
_: Option<char>,
_: &mut Vec<Token>,
parser: &mut Parser<T>,
) -> ParsingState {
loop {
if let Some(handle) = parser.get() {
let new_char = handle.char();
if new_char == '\n' {
return Fine;
}
} else {
return Finished;
}
}
}
pub fn parse_list<T: Iterator<Item = char>>(
char: Option<char>,
vec: &mut Vec<Token>,
parser: &mut Parser<T>,
) -> ParsingState {
let mut in_vec = Vec::new();
let result = parse_list_inline(char, &mut in_vec, parser);
vec.push(List(in_vec));
result
}
pub fn closing_bracket(bracket: char) -> Option<char> {
match bracket {
'(' => Some(')'),
')' => Some('('),
'[' => Some(']'),
']' => Some('['),
'{' => Some('}'),
'}' => Some('{'),
'<' => Some('>'),
'>' => Some('<'),
_ => None,
}
}
pub fn parse_list_inline<T: Iterator<Item = char>>(
char: Option<char>,
vec: &mut Vec<Token>,
parser: &mut Parser<T>,
) -> ParsingState {
let mut str = String::new();
let (end, set_back) = if let Some(char) = char {
let close = closing_bracket(char).expect("This character is not a list delimiter");
(Some(close), Some(parser.set(close, Some(parse_delegate))))
} else {
(None, None)
};
let result = loop {
if let Some(handle) = parser.get() {
if handle.is_macro() {
if !str.is_empty() {
vec.push(Symbol(str));
str = String::new();
}
let state = handle.call(vec).unwrap();
match state {
Fine => (),
Finished => {
if char.is_none() {
break Finished;
} else {
panic!("End of file inside list")
}
}
Delegate(char) => {
if let Some(end) = end {
if char == end {
if !str.is_empty() {
vec.push(Symbol(str));
}
break Fine;
} else {
panic!("Unexpected delegate")
}
} else {
panic!("Unexpected delegate")
}
}
}
} else {
let char = handle.char();
if let Some(end) = end {
if end == char {}
}
str.push(char);
}
} else {
if char.is_none() {
break Finished;
} else {
panic!("End of file inside list")
}
}
};
if let (Some(end), Some(set_back)) = (end, set_back) {
parser.set(end, set_back);
}
result
}
pub fn parse_infix_left<T: Iterator<Item = char>>(
char: Option<char>,
vec: &mut Vec<Token>,
parser: &mut Parser<T>,
) -> ParsingState {
let mut str = String::new();
let mut new_vec = Vec::new();
let mut char_string = String::new();
char_string.push(char.expect("Infix can only be called with a character"));
new_vec.push(Symbol(char_string));
new_vec.push(vec.pop().expect("Infix operator cannot stand alone"));
loop {
if let Some(handle) = parser.get() {
if handle.is_macro() {
if !str.is_empty() {
new_vec.push(Symbol(str));
vec.push(List(new_vec));
handle.discard();
break Fine;
}
let state = handle.call(&mut new_vec).unwrap();
match state {
Fine => (),
Finished => break Finished,
Delegate(char) => break Delegate(char),
}
} else {
let char = handle.char();
str.push(char);
}
} else {
if char.is_none() {
break Finished;
} else {
panic!("End of file inside list")
}
}
}
}
}