Files
lang/src/parser/cursor/mod.rs
T
2026-04-17 18:51:12 -04:00

103 lines
2.4 KiB
Rust

use std::borrow::Borrow;
use crate::io::{CompilerMsg, Span, Spanned};
mod lit;
mod token;
pub use lit::*;
pub use token::*;
pub struct Cursor<'a> {
pub span: Span,
next: Option<TokenInst>,
tokens: Tokens<'a>,
}
impl<'a> Cursor<'a> {
pub fn new(text: &'a str, file: usize) -> Self {
let mut s = Self {
span: Span {
start: 0,
end: 0,
file,
},
next: None,
tokens: Tokens::new(text, file),
};
s.next();
s
}
pub fn next(&mut self) -> Option<Token> {
let mut next = self.tokens.next();
std::mem::swap(&mut self.next, &mut next);
next.map(|inst| {
self.span = inst.span;
inst.inner
})
}
pub fn next_if(&mut self, token: impl Borrow<Token>) -> bool {
if self.peek().is_some_and(|t| t == token.borrow()) {
self.next();
true
} else {
false
}
}
pub fn peek(&self) -> Option<&Token> {
self.next.as_ref().map(|i| &i.inner)
}
pub fn expect_next(&mut self) -> Result<Token, CompilerMsg> {
self.next().ok_or_else(CompilerMsg::unexpected_eof)
}
pub fn expect_peek(&self) -> Result<&Token, CompilerMsg> {
self.peek().ok_or_else(CompilerMsg::unexpected_eof)
}
pub fn expect(&mut self, token: impl Borrow<Token>) -> Result<Token, CompilerMsg> {
let token = token.borrow();
let next = self.expect_next()?;
if next == *token {
Ok(next)
} else {
self.unexpected(&next, &format!("'{token}'"))
}
}
pub fn unexpected<T>(&self, token: &Token, expected: &str) -> Result<T, CompilerMsg> {
Err(CompilerMsg::unexpected_token(token, self.span, expected))
}
pub fn peek_start(&mut self) -> usize {
self.next.as_ref().map(|i| i.span.start).unwrap_or(0)
}
pub fn cur_end(&mut self) -> usize {
self.span.end
}
pub fn file(&mut self) -> usize {
self.span.file
}
}
impl CompilerMsg {
pub fn unexpected_token(token: &Token, span: Span, expected: &str) -> Self {
Self {
spans: vec![span],
msg: format!("Unexpected token '{}', expected {expected}", token),
}
}
pub fn unexpected_eof() -> Self {
Self {
spans: Vec::new(),
msg: "unexpected end of file".to_string(),
}
}
}