#![doc = include_str!("../README.md")]
mod lexer;
mod token;
#[cfg(test)]
mod tests;
use std::iter::FusedIterator;
pub(crate) use grammar::*;
pub(crate) use lexer::*;
pub use token::*;
pub mod grammar {
#![allow(missing_docs)]
include!(concat!(env!("OUT_DIR"), "/grammar.rs"));
}
pub struct Lexer<I>
where
I: Iterator<Item = char> + FusedIterator,
{
cursor: LexerCursor<I>,
buffered_token: Option<Token>,
}
impl<I> Lexer<I>
where
I: Iterator<Item = char> + FusedIterator,
{
pub fn new(iter: I) -> Self {
Self {
cursor: LexerCursor::new(iter),
buffered_token: None,
}
}
}
impl<I> Iterator for Lexer<I>
where
I: Iterator<Item = char> + FusedIterator,
{
type Item = Token;
fn next(&mut self) -> Option<Self::Item> {
match self.buffered_token.take() {
Some(tok) => Some(tok),
None => match self.cursor.next()? {
(tok, unknown_token) if unknown_token.is_none() => Some(tok),
(tok, unknown_token) => {
debug_assert!(self.buffered_token.is_none());
self.buffered_token = Some(tok);
unknown_token
}
},
}
}
}