use std::{cell::RefCell, fmt::Debug, rc::Rc};
use crate::{
lexer::{Cursor, LexerState, Span, TryConvert},
LexIt,
};
#[derive(Debug)]
pub struct Error {
pub span: Span,
}
impl Error {
pub fn new(span: Span) -> Self {
Self { span }
}
}
pub struct ParserState<'a, L> {
lexer: L,
lexbuf: LexerState<'a>,
stack: Rc<RefCell<Vec<(&'static str, usize)>>>,
}
impl<'a, L: LexIt + Clone> ParserState<'a, L> {
pub fn new(input: &'a str) -> Self {
Self {
lexer: L::new(),
lexbuf: LexerState::new(input),
stack: Rc::new(RefCell::new(Vec::new())),
}
}
pub fn cursor(&self) -> Cursor {
self.lexbuf.cursor()
}
fn next(&mut self) -> Option<L::Token<'a>> {
self.lexer.next(&mut self.lexbuf)
}
pub fn parse_with<T>(
&mut self,
matches: impl FnOnce(L::Token<'a>) -> Option<T>,
) -> Result<T, Error> {
self.next().and_then(matches).ok_or_else(|| self.error())
}
pub fn parse_type<T>(&mut self) -> Result<T, Error>
where
L::Token<'a>: TryConvert<T>,
T: PartialEq,
{
self.parse_with(|tt| tt.try_convert())
}
pub fn parse_char(&mut self, c: char) -> Result<char, Error> {
self.next().ok_or_else(|| self.error())?;
let lexeme = self.lexbuf.lexeme();
let mut chars = lexeme.chars();
let ch = chars.next().ok_or_else(|| self.error())?;
if ch == c && chars.as_str().is_empty() {
Ok(ch)
} else {
Err(self.error())
}
}
pub fn parse_str(&mut self, literal: &'a str) -> Result<&str, Error> {
self.next().ok_or_else(|| self.error())?;
let lexeme = self.lexbuf.lexeme();
if lexeme == literal {
Ok(lexeme)
} else {
Err(self.error())
}
}
pub fn error(&self) -> Error {
Error::new(self.lexbuf.span())
}
pub fn is_empty(&self) -> bool {
self.lexbuf.is_empty()
}
pub fn advance_to(&mut self, other: &Self) {
self.advance_to_cursor(other.lexbuf.cursor())
}
pub fn advance_to_cursor(&mut self, cursor: Cursor) {
assert!(cursor >= self.lexbuf.cursor(), "you cannot rewind");
self.lexbuf.advance_to_cursor(cursor);
}
pub fn fork(&self) -> Self {
Self {
lexer: self.lexer.clone(),
lexbuf: self.lexbuf.clone(),
stack: self.stack.clone(),
}
}
pub fn push(&self, name: &'static str) {
self.stack.borrow_mut().push((name, self.lexbuf.span().end));
}
pub fn pop(&self) {
self.stack.borrow_mut().pop();
}
pub fn debug(&self) -> String {
format!("{:?}", self.stack.borrow())
}
}