use gramatika::{ArcStr, ParseStreamer, SpannedError, Token as _, TokenCtor};
use crate::{
comment::Comment,
token::{Lexer, Token},
TokenKind,
};
pub struct ParseStream {
inner: gramatika::ParseStream<Token, Lexer>,
comments: Vec<Comment>,
parsing_comment: bool,
pub(crate) errors: Vec<SpannedError>,
}
pub struct ParseResult {
pub source: ArcStr,
pub tokens: Vec<Token>,
pub comments: Vec<Comment>,
pub errors: Vec<SpannedError>,
}
impl ParseStream {
pub fn source(&self) -> ArcStr {
self.inner.source()
}
pub fn into_inner(self) -> ParseResult {
let (source, tokens) = self.inner.into_inner();
ParseResult {
source,
tokens,
comments: self.comments,
errors: self.errors,
}
}
pub fn split_next(
&mut self,
split_at: usize,
ctors: (TokenCtor<Token>, TokenCtor<Token>),
) -> gramatika::Result<Token> {
self.inner.split_next(split_at, ctors)
}
fn did_parse_comment(&mut self) -> bool {
let Some(token) = self.inner.peek() else {
return false;
};
match token.kind() {
TokenKind::CommentStart => {
self.parsing_comment = true;
match self.parse::<Comment>() {
Ok(comment) => {
self.comments.push(comment);
self.parsing_comment = false;
true
}
Err(error) => {
self.errors.push(error);
self.parsing_comment = false;
true
}
}
}
_ => false,
}
}
}
impl<S> From<S> for ParseStream
where S: Into<ArcStr>
{
fn from(value: S) -> Self {
Self {
inner: gramatika::ParseStream::from(value),
comments: vec![],
parsing_comment: false,
errors: vec![],
}
}
}
impl ParseStreamer for ParseStream {
type Token = Token;
fn is_empty(&mut self) -> bool {
self.inner.is_empty()
}
fn peek(&mut self) -> Option<&Token> {
if !self.parsing_comment && self.did_parse_comment() {
self.peek()
} else {
self.inner.peek()
}
}
fn prev(&mut self) -> Option<&Token> {
self.inner.prev()
}
fn check_kind(&mut self, kind: TokenKind) -> bool {
if !self.parsing_comment && self.did_parse_comment() {
self.check_kind(kind)
} else {
self.inner.check_kind(kind)
}
}
fn check(&mut self, compare: Token) -> bool {
if !self.parsing_comment && self.did_parse_comment() {
self.check(compare)
} else {
self.inner.check(compare)
}
}
fn consume(&mut self, compare: Token) -> gramatika::Result<Token> {
if !self.parsing_comment && self.did_parse_comment() {
self.consume(compare)
} else {
self.inner.consume(compare)
}
}
fn consume_kind(&mut self, kind: TokenKind) -> gramatika::Result<Token> {
if !self.parsing_comment && self.did_parse_comment() {
self.consume_kind(kind)
} else {
self.inner.consume_kind(kind)
}
}
fn consume_as(
&mut self,
kind: TokenKind,
convert: TokenCtor<Token>,
) -> gramatika::Result<Token> {
if !self.parsing_comment && self.did_parse_comment() {
self.consume_as(kind, convert)
} else {
self.inner.consume_as(kind, convert)
}
}
fn upgrade_last(
&mut self,
kind: TokenKind,
convert: TokenCtor<Token>,
) -> gramatika::Result<Token> {
self.inner.upgrade_last(kind, convert)
}
fn upgrade(
&mut self,
token: Self::Token,
convert: TokenCtor<Token>,
) -> gramatika::Result<Token> {
self.inner.upgrade(token, convert)
}
fn discard(&mut self) {
self.inner.discard();
}
}
impl Iterator for ParseStream {
type Item = Token;
fn next(&mut self) -> Option<Token> {
self.inner.next()
}
}