use crate::compiling::failing::position_info::PositionInfo;
use crate::compiling::failing::failure::Failure;
use super::{ Metadata, SyntaxModule };
pub fn token<T: AsRef<str>>(meta: &mut impl Metadata, text: T) -> Result<String, Failure> {
match meta.get_current_token() {
Some(token) => if token.word == text.as_ref() {
meta.increment_index();
Ok(token.word)
} else { Err(Failure::Quiet(PositionInfo::from_token(meta, Some(token)))) }
None => Err(Failure::Quiet(PositionInfo::at_eof(meta)))
}
}
pub fn token_by(meta: &mut impl Metadata, cb: impl Fn(&String) -> bool) -> Result<String, Failure> {
match meta.get_current_token() {
Some(token) => if cb(&token.word) {
meta.increment_index();
Ok(token.word)
} else { Err(Failure::Quiet(PositionInfo::from_token(meta, Some(token)))) }
None => Err(Failure::Quiet(PositionInfo::at_eof(meta)))
}
}
pub fn syntax<M: Metadata>(meta: &mut M, module: &mut impl SyntaxModule<M>) -> Result<(), Failure> {
let index = meta.get_index();
let result = match meta.get_debug() {
Some(_) => module.parse_debug(meta),
None => module.parse(meta)
};
if let Err(failure) = result {
meta.set_index(index);
Err(failure)
} else { Ok(()) }
}
pub fn indent(meta: &mut impl Metadata) -> Result<usize, Failure> {
let fun = |word: &String| word.starts_with('\n') && word.get(1..).unwrap().chars().all(|letter| letter == ' ');
match token_by(meta, fun) {
Ok(word) => Ok(word.get(1..).unwrap().len()),
Err(failure) => Err(failure)
}
}
pub fn indent_with(meta: &mut impl Metadata, size: usize) -> Result<std::cmp::Ordering, Failure> {
let index = meta.get_index();
let fun = |word: &String| word.starts_with('\n') && word.get(1..).unwrap().chars().all(|letter| letter == ' ');
match token_by(meta, fun) {
Ok(word) => {
let spaces = word.chars().count() - 1;
Ok(spaces.cmp(&size))
}
Err(details) => {
meta.set_index(index);
Err(details)
}
}
}
#[cfg(test)]
mod test {
use crate::compiling::{DefaultMetadata, Token};
use super::*;
#[test]
fn indent_test() {
let expr = vec![Token {word: format!("\n "), pos: (0, 0)}];
let mut meta = DefaultMetadata::new(expr, Some(format!("path/to/file")), None);
let res = indent(&mut meta);
assert!(res.is_ok());
assert_eq!(res.unwrap(), 4);
}
#[test]
fn indent_with_test() {
let expr = vec![Token { word: format!("\n "), pos: (0, 0) }];
let mut meta = DefaultMetadata::new(expr, Some(format!("path/to/file")), None);
let res = indent_with(&mut meta, 4);
assert!(res.is_ok());
}
}