use crate::input::core::{Input, InputToken};
use crate::input::position::Position;
use crate::input::source::InputSource;
use std::iter::Peekable;
#[derive(Clone, PartialEq, Debug)]
pub struct CharToken {
token: char,
position: Position,
}
impl InputToken for CharToken {
type Token = char;
fn token(&self) -> &char {
&self.token
}
fn token_owned(self) -> char {
self.token
}
fn position(&self) -> Position {
self.position
}
}
impl CharToken {
fn new(token: char, position: Position) -> Self {
Self { token, position }
}
}
struct StringInputSource<I>
where
I: Iterator<Item = char>,
{
source: Peekable<I>,
source_name: Option<String>,
position: Position,
peeked_token: Option<CharToken>,
}
impl<I> StringInputSource<I>
where
I: Iterator<Item = char>,
{
pub(crate) fn new<S>(source: S, source_name: Option<String>) -> Self
where
S: IntoIterator<Item = char, IntoIter = I>,
{
StringInputSource {
source: source.into_iter().peekable(),
source_name,
position: Position::new(1, 1),
peeked_token: None,
}
}
}
impl<I> InputSource for StringInputSource<I>
where
I: Iterator<Item = char>,
{
type Token = CharToken;
fn source_name(&self) -> Option<&String> {
self.source_name.as_ref()
}
fn next_token(&mut self) -> Option<CharToken> {
let token = self.source.next()?;
let token = CharToken::new(token, self.position);
self.position.advance_column();
Some(token)
}
fn peek(&mut self) -> Option<&CharToken> {
let token = self.source.peek()?;
self.peeked_token = Some(CharToken::new(*token, self.position));
self.peeked_token.as_ref()
}
}
pub type StringInput<'a> = Input<'a, CharToken>;
impl<'a> StringInput<'a> {
pub fn new_from_chars<S>(chars: S, source_name: Option<String>) -> Input<'a, CharToken>
where
S: IntoIterator<Item = char, IntoIter: Iterator<Item = char> + 'a>,
{
let source = StringInputSource::new(chars, source_name);
Input::new(Box::new(source))
}
}