Add TokenInfo for error logging, hopefully
This commit is contained in:
parent
f473fe324e
commit
2e170879ea
71
src/lexer.rs
71
src/lexer.rs
|
@ -1,4 +1,5 @@
|
|||
use logos::Logos;
|
||||
use std::fmt::{Display, Formatter, Result as FmtResult};
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(Logos, Debug, PartialEq)]
|
||||
|
@ -52,22 +53,55 @@ pub enum Token {
|
|||
#[regex(r"//[^\n]*", logos::skip)]
|
||||
SingleLineComment,
|
||||
|
||||
#[regex(r"[ \t\n\f ]+", logos::skip)]
|
||||
#[regex(r"[ \t\f ]+", logos::skip)]
|
||||
Whitespace,
|
||||
|
||||
#[token("\n")]
|
||||
Newline,
|
||||
|
||||
#[error]
|
||||
Error,
|
||||
}
|
||||
|
||||
pub struct Lexer<'a>(logos::Lexer<'a, Token>);
|
||||
pub struct TokenInfo<'a> {
|
||||
pub line: &'a str,
|
||||
pub line_num: usize,
|
||||
pub token_start: usize,
|
||||
pub token_end: usize,
|
||||
}
|
||||
|
||||
impl<'a> Display for TokenInfo<'a> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "{:04}| {}\n |", self.line_num, self.line)?;
|
||||
|
||||
write!(f, "{} ^", " ".repeat(self.token_start))?;
|
||||
|
||||
let token_len = self.token_end - self.token_start;
|
||||
if token_len > 1 {
|
||||
write!(f, "{}^", "-".repeat(token_len - 2))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Lexer<'a> {
|
||||
inner: logos::Lexer<'a, Token>,
|
||||
line_num: usize,
|
||||
line_start: usize,
|
||||
}
|
||||
|
||||
impl<'a> Lexer<'a> {
|
||||
pub fn new(source: &'a str) -> Self {
|
||||
Self(Token::lexer(source))
|
||||
Self {
|
||||
inner: Token::lexer(source),
|
||||
line_num: 0,
|
||||
line_start: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn slice(&self) -> &'a str {
|
||||
self.0.slice()
|
||||
self.inner.slice()
|
||||
}
|
||||
|
||||
pub fn eat_id(&mut self) -> Result<&'a str, Option<Token>> {
|
||||
|
@ -78,14 +112,37 @@ impl<'a> Lexer<'a> {
|
|||
Err(tok)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_info(&self) -> TokenInfo<'a> {
|
||||
let from_start = &self.inner.source()[self.line_start..];
|
||||
let line_end = from_start.find("\n").unwrap_or(from_start.len());
|
||||
let line = &from_start[..line_end];
|
||||
let span = self.inner.span();
|
||||
|
||||
TokenInfo {
|
||||
line,
|
||||
line_num: self.line_num,
|
||||
token_start: span.start - self.line_start,
|
||||
token_end: span.end - self.line_start,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Lexer<'a> {
|
||||
type Item = Token;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let tok = self.0.next();
|
||||
println!("ate: {:?}", tok);
|
||||
tok
|
||||
while let Some(tok) = self.inner.next() {
|
||||
println!("ate: {:?}", tok);
|
||||
if tok == Token::Newline {
|
||||
self.line_start = self.inner.span().end;
|
||||
self.line_num += 1;
|
||||
} else {
|
||||
println!("{}", self.get_info());
|
||||
return Some(tok);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue