use core::fmt;
use core::ops;
use crate::alloc::VecDeque;
use crate::ast::Spanned;
use crate::ast::{Kind, OptionSpanned, Span, Token};
use crate::compile::WithSpan;
use crate::compile::{self, ErrorKind};
use crate::macros::{TokenStream, TokenStreamIter};
use crate::parse::{Advance, Lexer, Parse, Peek};
use crate::shared::FixedVec;
use crate::SourceId;
#[derive(Debug)]
pub struct Parser<'a> {
peeker: Peeker<'a>,
}
impl<'a> Parser<'a> {
pub fn new(source: &'a str, source_id: SourceId, shebang: bool) -> Self {
Self::with_source(
Source {
inner: SourceInner::Lexer(Lexer::new(source, source_id, shebang)),
},
Span::new(0u32, source.len()),
)
}
pub fn from_token_stream(token_stream: &'a TokenStream, span: Span) -> Self {
Self::with_source(
Source {
inner: SourceInner::TokenStream(token_stream.iter()),
},
span,
)
}
pub fn parse<T>(&mut self) -> compile::Result<T>
where
T: Parse,
{
T::parse(self)
}
pub fn parse_all<T>(&mut self) -> compile::Result<T>
where
T: Parse,
{
let item = self.parse::<T>()?;
self.eof()?;
Ok(item)
}
pub fn peek<T>(&mut self) -> compile::Result<bool>
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 eof(&mut self) -> compile::Result<()> {
if let Some(token) = self.peeker.at(0)? {
return Err(compile::Error::new(
token,
ErrorKind::ExpectedEof { actual: token.kind },
));
}
Ok(())
}
pub fn is_eof(&mut self) -> compile::Result<bool> {
Ok(self.peeker.at(0)?.is_none())
}
fn with_source(source: Source<'a>, span: Span) -> Self {
let default_span = source.span().unwrap_or(span);
Self {
peeker: Peeker {
source,
buf: VecDeque::new(),
error: None,
last: None,
default_span,
},
}
}
pub fn try_consume<T>(&mut self) -> compile::Result<bool>
where
T: Parse + Peek,
{
Ok(if self.peek::<T>()? {
self.parse::<T>()?;
true
} else {
false
})
}
pub fn try_consume_all<T>(&mut self) -> compile::Result<bool>
where
T: Parse + Peek,
{
let mut consumed = false;
while self.peek::<T>()? {
self.parse::<T>()?;
consumed = true;
}
Ok(consumed)
}
pub(crate) fn span(&mut self, range: ops::Range<usize>) -> Span {
self.span_at(range.start).join(self.span_at(range.end))
}
pub(crate) fn peeker(&mut self) -> &mut Peeker<'a> {
&mut self.peeker
}
#[allow(clippy::should_implement_trait)]
pub(crate) fn next(&mut self) -> compile::Result<Token> {
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.next()? {
Some(t) => Ok(t),
None => Err(compile::Error::new(
self.last_span().tail(),
ErrorKind::UnexpectedEof,
)),
}
}
pub(crate) fn nth(&mut self, n: usize) -> compile::Result<Kind> {
if let Some(t) = self.peeker.at(n)? {
Ok(t.kind)
} else {
Ok(Kind::Eof)
}
}
pub(crate) fn span_at(&mut self, n: usize) -> Span {
if let Ok(Some(t)) = self.peeker.at(n) {
t.span
} else {
self.last_span().tail()
}
}
pub(crate) fn tok_at(&mut self, n: usize) -> compile::Result<Token> {
Ok(if let Some(t) = self.peeker.at(n)? {
t
} else {
Token {
kind: Kind::Eof,
span: self.last_span().tail(),
}
})
}
pub(crate) fn last_span(&self) -> Span {
self.peeker.last_span()
}
}
#[derive(Debug)]
pub struct Peeker<'a> {
source: Source<'a>,
buf: VecDeque<Token>,
error: Option<compile::Error>,
last: Option<Span>,
default_span: Span,
}
impl Peeker<'_> {
pub(crate) 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
}
}
}
pub(crate) fn array<const N: usize>(&mut self) -> FixedVec<Token, N> {
let mut vec = FixedVec::new();
if N == 0 {
return vec;
}
if let Err(error) = self.fill(N) {
self.error = Some(error);
}
let mut it = 0..N;
for (&tok, _) in self.buf.iter().zip(it.by_ref()) {
_ = vec.try_push(tok);
}
if let Some(error) = &self.error {
for _ in it {
_ = vec.try_push(Token {
kind: Kind::Error,
span: error.span(),
});
}
} else {
for _ in it {
_ = vec.try_push(Token {
kind: Kind::Eof,
span: self.last_span(),
});
}
}
vec
}
pub(crate) fn is_eof(&mut self) -> bool {
match self.at(0) {
Ok(t) => t.is_none(),
Err(error) => {
self.error = Some(error);
false
}
}
}
fn next(&mut self) -> compile::Result<Option<Token>> {
loop {
let Some(token) = self.source.next()? else {
return Ok(None);
};
match token.kind {
Kind::Comment | Kind::Whitespace => {
continue;
}
Kind::MultilineComment(term) => {
if !term {
return Err(compile::Error::new(
token.span,
ErrorKind::ExpectedMultilineCommentTerm,
));
}
continue;
}
_ => (),
}
return Ok(Some(token));
}
}
fn at(&mut self, n: usize) -> compile::Result<Option<Token>> {
self.fill(n)?;
Ok(self.buf.get(n).copied())
}
fn fill(&mut self, n: usize) -> compile::Result<()> {
if let Some(error) = self.error.take() {
return Err(error);
}
while self.buf.len() <= n {
let Some(tok) = self.next()? else {
break;
};
self.last = Some(tok.span);
self.buf.try_push_back(tok).with_span(tok.span)?;
}
Ok(())
}
fn last_span(&self) -> Span {
self.last.unwrap_or(self.default_span)
}
}
pub(crate) struct Source<'a> {
inner: SourceInner<'a>,
}
impl Source<'_> {
fn span(&self) -> Option<Span> {
match &self.inner {
SourceInner::Lexer(lexer) => Some(lexer.span()),
SourceInner::TokenStream(token_stream) => token_stream.option_span(),
}
}
fn next(&mut self) -> compile::Result<Option<Token>> {
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>),
}
impl Advance for Parser<'_> {
type Error = compile::Error;
#[inline]
fn advance(&mut self, n: usize) -> Result<(), Self::Error> {
for _ in 0..n {
self.next()?;
}
Ok(())
}
}