use super::{
ast::metadata::AstNodeMeta,
lexer::{
tokens::{Token, TokenTy},
IndexedLexer, IndexedToken,
}, error::{ParserError, ParserErrorVariant},
};
use crate::filemap::{FileId, FileMap};
use codespan_reporting::files::Files;
#[cfg(doc)]
use std::iter::Peekable;
use std::ops::Range;
#[derive(Debug, Clone)]
pub struct ParserState<'src> {
file_map: &'src FileMap,
file_id: FileId,
pub source: &'src str,
lexer: IndexedLexer<'src>,
peeked_token: Option<Option<IndexedToken>>,
}
impl<'src> ParserState<'src> {
pub fn new(file_map: &'src FileMap, file_id: FileId) -> Self {
let source = file_map
.source(file_id)
.expect("file id exists in file map");
ParserState {
file_map,
file_id,
source,
lexer: IndexedLexer::new(source),
peeked_token: None,
}
}
pub fn make_ast_node_meta(&self, index: usize, length: usize) -> AstNodeMeta<'src> {
AstNodeMeta {
file_map: self.file_map,
file_id: self.file_id,
index,
matching_source: &self.source[index..index + length],
}
}
pub fn peek_token(&mut self) -> Option<&IndexedToken> {
let iter = &mut self.lexer;
self.peeked_token
.get_or_insert_with(|| iter.next())
.as_ref()
}
pub fn peek_token_ty(&mut self) -> Option<&TokenTy> {
self.peek_token()
.map(|indexed_token| &indexed_token.token.variant)
}
pub fn index(&self) -> usize {
match self.peeked_token.as_ref() {
Some(Some(IndexedToken { index, .. })) => *index,
_ => self.lexer.index,
}
}
pub fn next_token(&mut self) -> Option<IndexedToken> {
match self.peeked_token.take() {
Some(peeked_token) => peeked_token,
None => self.lexer.next(),
}
}
pub fn next_token_if_ty_eq(&mut self, token_ty: TokenTy) -> Option<IndexedToken> {
match self.next_token() {
Some(
token @ IndexedToken {
token: Token { variant, .. },
..
},
) if variant == token_ty => Some(token),
other => {
assert!(self.peeked_token.is_none());
self.peeked_token = Some(other);
None
}
}
}
pub fn peek_byte_range(&mut self) -> Range<usize> {
if let Some(IndexedToken {
index,
token: Token { length, .. },
}) = self.peek_token()
{
*index..*index + *length
} else {
self.index()..self.index()
}
}
#[inline]
pub(crate) fn peek_byte_range_into_error(&mut self, err_ty: ParserErrorVariant) -> ParserError {
ParserError { byte_range: self.peek_byte_range(), ty: err_ty }
}
}