use crate::ast::span::MissingLocationError;
use crate::ast::{Location, Span, Spanned};
use crate::lexer::Token;
use chumsky::input::{BorrowInput, ExactSizeInput, SliceInput, ValueInput};
use chumsky::prelude::*;
use std::fmt::Debug;
use std::ops::{Range, RangeFrom};
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct TokenIndex(usize);
#[derive(Clone, Eq, PartialEq)]
pub struct TokenVec {
tokens: Vec<Spanned<Token>>,
eof: Location,
}
impl TokenVec {
#[inline]
pub fn as_stream(&self) -> TokenStream<'_> {
TokenStream {
tokens: &self.tokens,
eof: self.eof,
}
}
pub(super) fn from_raw_parts(tokens: Vec<Spanned<Token>>, eof: Location) -> Self {
if let Some(last) = tokens.last() {
let last_location = last.span.end();
assert!(!last_location.is_missing());
assert!(last_location <= eof);
}
TokenVec { tokens, eof }
}
}
impl Debug for TokenVec {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_list()
.entries(self.tokens.iter().map(|s| &s.value))
.finish()
}
}
impl PartialEq<Vec<Token>> for TokenVec {
fn eq(&self, other: &Vec<Token>) -> bool {
self.tokens.len() == other.len() && self.tokens.iter().map(|tk| &tk.value).eq(other.iter())
}
}
#[derive(Clone)]
pub struct TokenStream<'a> {
tokens: &'a [Spanned<Token>],
eof: Location,
}
impl<'a> TokenStream<'a> {
#[inline]
fn span_for(&self, idx: TokenIndex) -> Span {
if idx.0 == self.tokens.len() {
self.eof.to_span()
} else {
self.tokens[idx.0].span
}
}
#[inline]
fn do_next(cache: &mut Self, cursor: &mut TokenIndex) -> Option<&'a Token> {
if let Some(tok) = cache.tokens.get(cursor.0) {
cursor.0 += 1;
Some(&tok.value)
} else {
None
}
}
}
impl<'a> Input<'a> for TokenStream<'a> {
type Span = Span;
type Token = Token;
type MaybeToken = &'a Token;
type Cursor = TokenIndex;
type Cache = Self;
#[inline]
fn begin(self) -> (Self::Cursor, Self::Cache) {
(TokenIndex(0), self)
}
#[inline]
fn cursor_location(cursor: &Self::Cursor) -> usize {
cursor.0
}
#[inline]
unsafe fn next_maybe(cache: &mut Self, cursor: &mut TokenIndex) -> Option<Self::MaybeToken> {
Self::do_next(cache, cursor)
}
#[inline]
unsafe fn span(state: &mut Self, range: Range<&TokenIndex>) -> Self::Span {
let state = &*state;
assert!(range.start <= range.end);
join_spans(state.span_for(*range.start), state.span_for(*range.end))
}
}
impl<'a> ValueInput<'a> for TokenStream<'a> {
#[inline]
unsafe fn next(cache: &mut Self, cursor: &mut Self::Cursor) -> Option<Token> {
Self::do_next(cache, cursor).cloned()
}
}
impl<'a> BorrowInput<'a> for TokenStream<'a> {
#[inline]
unsafe fn next_ref(cache: &mut Self, cursor: &mut Self::Cursor) -> Option<&'a Token> {
Self::do_next(cache, cursor)
}
}
impl<'a> ExactSizeInput<'a> for TokenStream<'a> {
unsafe fn span_from(state: &mut Self::Cache, range: RangeFrom<&Self::Cursor>) -> Self::Span {
join_spans(state.span_for(*range.start), state.eof)
}
}
impl<'a> SliceInput<'a> for TokenStream<'a> {
type Slice = TokenStream<'a>;
#[inline]
fn full_slice(cache: &mut Self::Cache) -> Self::Slice {
(*cache).clone()
}
#[inline]
unsafe fn slice(cache: &mut Self::Cache, range: Range<&Self::Cursor>) -> Self::Slice {
TokenStream {
tokens: &cache.tokens[range.start.0..range.end.0],
eof: cache.eof,
}
}
#[inline]
unsafe fn slice_from(cache: &mut Self::Cache, range: RangeFrom<&Self::Cursor>) -> Self::Slice {
TokenStream {
tokens: &cache.tokens[range.start.0..],
eof: cache.eof,
}
}
}
#[inline]
fn join_spans(first: impl Into<Span>, second: impl Into<Span>) -> Span {
#[inline]
fn do_join_spans(first: Span, second: Span) -> Result<Span, MissingLocationError> {
let start = first.start().byte_offset()?;
let end = second.end().byte_offset()?;
assert!(start <= end);
Ok(Span::from_byte_range(start..end))
}
do_join_spans(first.into(), second.into()).unwrap_or(Span::MISSING)
}