use crate::ast::{Kind, Token};
use crate::macros::{TokenStream, TokenStreamIter};
use crate::parsing::{Lexer, Parse, ParseError, ParseErrorKind, Peek};
use crate::OptionSpanned as _;
use runestick::Span;
use std::collections::VecDeque;
use std::fmt;
use std::ops;
#[derive(Debug)]
pub struct Parser<'a> {
peeker: Peeker<'a>,
span: Option<Span>,
}
impl<'a> Parser<'a> {
pub fn new(source: &'a str) -> Self {
Self::with_source(Source {
inner: SourceInner::Lexer(Lexer::new(source)),
})
}
pub fn try_consume<T>(&mut self) -> Result<bool, ParseError>
where
T: Parse + Peek,
{
Ok(if self.peek::<T>()? {
self.parse::<T>()?;
true
} else {
false
})
}
pub fn try_consume_all<T>(&mut self) -> Result<bool, ParseError>
where
T: Parse + Peek,
{
let mut consumed = false;
while self.peek::<T>()? {
self.parse::<T>()?;
consumed = true;
}
Ok(consumed)
}
pub fn from_token_stream(token_stream: &'a TokenStream) -> Self {
Self::with_source(Source {
inner: SourceInner::TokenStream(token_stream.iter()),
})
}
fn with_source(source: Source<'a>) -> Self {
let span = source.span().or_else(crate::macros::current_stream_span);
Self {
peeker: Peeker {
source,
buf: VecDeque::new(),
error: None,
last: None,
},
span,
}
}
pub fn span(&mut self, range: ops::Range<usize>) -> Span {
self.span_at(range.start).join(self.span_at(range.end))
}
pub fn parse<T>(&mut self) -> Result<T, ParseError>
where
T: Parse,
{
T::parse(self)
}
pub fn parse_all<T>(&mut self) -> Result<T, ParseError>
where
T: Parse,
{
let item = self.parse::<T>()?;
self.eof()?;
Ok(item)
}
pub fn peek<T>(&mut self) -> Result<bool, ParseError>
where
T: Peek,
{
if let Some(error) = self.peeker.error.take() {
return Err(error);
}
let result = T::peek(&mut self.peeker);
if let Some(error) = self.peeker.error.take() {
return Err(error);
}
Ok(result)
}
pub fn peeker(&mut self) -> &mut Peeker<'a> {
&mut self.peeker
}
#[allow(clippy::should_implement_trait)]
pub fn next(&mut self) -> Result<Token, ParseError> {
if let Some(error) = self.peeker.error.take() {
return Err(error);
}
if let Some(t) = self.peeker.buf.pop_front() {
return Ok(t);
}
match self.peeker.source.next()? {
Some(t) => Ok(t),
None => Err(ParseError::new(
self.last_span().end(),
ParseErrorKind::UnexpectedEof,
)),
}
}
pub fn is_eof(&mut self) -> Result<bool, ParseError> {
Ok(self.peeker.at(0)?.is_none())
}
pub fn eof(&mut self) -> Result<(), ParseError> {
if let Some(token) = self.peeker.at(0)? {
return Err(ParseError::new(
token,
ParseErrorKind::ExpectedEof { actual: token.kind },
));
}
Ok(())
}
pub fn nth(&mut self, n: usize) -> Result<Kind, ParseError> {
if let Some(t) = self.peeker.at(n)? {
Ok(t.kind)
} else {
Ok(Kind::Eof)
}
}
pub fn span_at(&mut self, n: usize) -> Span {
if let Ok(Some(t)) = self.peeker.at(n) {
t.span
} else {
self.last_span().end()
}
}
pub fn tok_at(&mut self, n: usize) -> Result<Token, ParseError> {
Ok(if let Some(t) = self.peeker.at(n)? {
t
} else {
Token {
kind: Kind::Eof,
span: self.last_span().end(),
}
})
}
pub fn last_span(&self) -> Span {
self.peeker.last.or(self.span).unwrap_or_default()
}
}
#[derive(Debug)]
pub struct Peeker<'a> {
pub(crate) source: Source<'a>,
buf: VecDeque<Token>,
error: Option<ParseError>,
last: Option<Span>,
}
impl<'a> Peeker<'a> {
pub fn nth(&mut self, n: usize) -> Kind {
if self.error.is_some() {
return Kind::Error;
}
match self.at(n) {
Ok(t) => match t {
Some(t) => t.kind,
None => Kind::Eof,
},
Err(error) => {
self.error = Some(error);
Kind::Error
}
}
}
fn at(&mut self, n: usize) -> Result<Option<Token>, ParseError> {
if let Some(error) = self.error.take() {
return Err(error);
}
while self.buf.len() <= n {
let token = match self.source.next()? {
Some(token) => token,
None => break,
};
self.last = Some(token.span);
self.buf.push_back(token);
}
Ok(self.buf.get(n).copied())
}
pub fn is_eof(&mut self) -> bool {
match self.at(0) {
Ok(t) => t.is_none(),
Err(error) => {
self.error = Some(error);
false
}
}
}
}
pub(crate) struct Source<'a> {
inner: SourceInner<'a>,
}
impl Source<'_> {
pub(crate) fn span(&self) -> Option<Span> {
match &self.inner {
SourceInner::Lexer(lexer) => Some(lexer.span()),
SourceInner::TokenStream(token_stream) => token_stream.option_span(),
}
}
pub(crate) fn next(&mut self) -> Result<Option<Token>, ParseError> {
match &mut self.inner {
SourceInner::Lexer(lexer) => lexer.next(),
SourceInner::TokenStream(token_stream) => Ok(token_stream.next()),
}
}
}
impl fmt::Debug for Source<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.inner, f)
}
}
#[derive(Debug)]
enum SourceInner<'a> {
Lexer(Lexer<'a>),
TokenStream(TokenStreamIter<'a>),
}