mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-23 00:18:24 +00:00
48 lines
1.3 KiB
Rust
48 lines
1.3 KiB
Rust
use std::{fmt::Display, ops::Range};
|
|
|
|
use logos::{Logos, SpannedIter};
|
|
|
|
use crate::tokens::{LexingError, Token};
|
|
|
|
pub type Spanned<Tok, Loc, Error> = Result<(Loc, Tok, Loc), Error>;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum LexicalError {
|
|
InvalidToken(LexingError, Range<usize>),
|
|
}
|
|
|
|
impl Display for LexicalError {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
LexicalError::InvalidToken(err, span) => {
|
|
write!(f, "lexical error at ({:?}): {:?}", err, span)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct Lexer<'input> {
|
|
// instead of an iterator over characters, we have a token iterator
|
|
token_stream: SpannedIter<'input, Token>,
|
|
}
|
|
|
|
impl<'input> Lexer<'input> {
|
|
pub fn new(input: &'input str) -> Self {
|
|
// the Token::lexer() method is provided by the Logos trait
|
|
Self {
|
|
token_stream: Token::lexer(input).spanned(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'input> Iterator for Lexer<'input> {
|
|
type Item = Spanned<Token, usize, LexicalError>;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
self.token_stream.next().map(|(token, span)| match token {
|
|
Ok(token) => Ok((span.start, token, span.end)),
|
|
Err(err) => Err(LexicalError::InvalidToken(err, span)),
|
|
})
|
|
}
|
|
}
|