mod buffered_lexer;
use super::ParseError;
use crate::syntax::{
ast::Punctuator,
lexer::{InputElement, Lexer, Position, Token, TokenKind},
};
use buffered_lexer::BufferedLexer;
use std::io::Read;
#[derive(Debug)]
pub(super) enum SemicolonResult<'s> {
Found(Option<&'s Token>),
NotFound(&'s Token),
}
#[derive(Debug)]
pub(super) struct Cursor<R> {
buffered_lexer: BufferedLexer<R>,
}
impl<R> Cursor<R>
where
R: Read,
{
#[inline]
pub(super) fn new(reader: R) -> Self {
Self {
buffered_lexer: Lexer::new(reader).into(),
}
}
#[inline]
pub(super) fn set_goal(&mut self, elm: InputElement) {
self.buffered_lexer.set_goal(elm)
}
#[inline]
pub(super) fn lex_regex(&mut self, start: Position) -> Result<Token, ParseError> {
self.buffered_lexer.lex_regex(start)
}
#[inline]
pub(super) fn next(&mut self) -> Result<Option<Token>, ParseError> {
self.buffered_lexer.next(true)
}
#[inline]
pub(super) fn peek(&mut self, skip_n: usize) -> Result<Option<&Token>, ParseError> {
self.buffered_lexer.peek(skip_n, true)
}
#[inline]
pub(super) fn expect<K>(&mut self, kind: K, context: &'static str) -> Result<Token, ParseError>
where
K: Into<TokenKind>,
{
let next_token = self.next()?.ok_or(ParseError::AbruptEnd)?;
let kind = kind.into();
if next_token.kind() == &kind {
Ok(next_token)
} else {
Err(ParseError::expected(vec![kind], next_token, context))
}
}
#[inline]
pub(super) fn peek_semicolon(&mut self) -> Result<SemicolonResult<'_>, ParseError> {
match self.buffered_lexer.peek(0, false)? {
Some(tk) => match tk.kind() {
TokenKind::Punctuator(Punctuator::Semicolon)
| TokenKind::LineTerminator
| TokenKind::Punctuator(Punctuator::CloseBlock) => {
Ok(SemicolonResult::Found(Some(tk)))
}
_ => Ok(SemicolonResult::NotFound(tk)),
},
None => Ok(SemicolonResult::Found(None)),
}
}
#[inline]
pub(super) fn expect_semicolon(&mut self, context: &'static str) -> Result<(), ParseError> {
match self.peek_semicolon()? {
SemicolonResult::Found(Some(tk)) => match *tk.kind() {
TokenKind::Punctuator(Punctuator::Semicolon) | TokenKind::LineTerminator => {
let _ = self.buffered_lexer.next(false)?;
Ok(())
}
_ => Ok(()),
},
SemicolonResult::Found(None) => Ok(()),
SemicolonResult::NotFound(tk) => Err(ParseError::expected(
vec![TokenKind::Punctuator(Punctuator::Semicolon)],
tk.clone(),
context,
)),
}
}
#[inline]
pub(super) fn peek_expect_no_lineterminator(
&mut self,
skip_n: usize,
) -> Result<&Token, ParseError> {
if let Some(t) = self.buffered_lexer.peek(skip_n, false)? {
if t.kind() == &TokenKind::LineTerminator {
Err(ParseError::unexpected(t.clone(), None))
} else {
Ok(t)
}
} else {
Err(ParseError::AbruptEnd)
}
}
#[inline]
pub(super) fn next_if<K>(&mut self, kind: K) -> Result<Option<Token>, ParseError>
where
K: Into<TokenKind>,
{
Ok(if let Some(token) = self.peek(0)? {
if token.kind() == &kind.into() {
self.next()?
} else {
None
}
} else {
None
})
}
}