use std::fmt::{Display, Formatter};
use std::ops::Bound;
use crate::{
Lex, Parse, ParseStream, Span, Spanned, TokenGroup, TokenParseError, TokenStream, TokenTree,
TrailingTrivia,
};
use these_macros_should_be_illegal::discriminated_str;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[discriminated_str(expression_name)]
pub enum DelimiterKind {
Parenthesis = "parenthesized expression",
Bracket = "array expression",
Brace = "list expression",
AngleBar = "angle-bar list expression",
}
pub trait DelimiterValue: Spanned + Lex + Sized {
fn from_delimiter(delimiter: Delimiter) -> Option<Self>;
fn delimiter(&self) -> Delimiter;
fn expected() -> &'static str;
fn opening_trivia(&self) -> &TrailingTrivia;
fn opening_trivia_mut(&mut self) -> &mut TrailingTrivia;
fn closing_trivia(&self) -> &TrailingTrivia;
fn closing_trivia_mut(&mut self) -> &mut TrailingTrivia;
fn surround(&self, output: &mut TokenStream, contents: TokenStream) {
let mut grouped = TokenStream::new();
self.opening_trivia().to_tokens(&mut grouped);
contents.to_tokens(&mut grouped);
output.extend([TokenGroup::new(self.delimiter(), grouped)]);
self.closing_trivia().to_tokens(output);
}
}
pub trait DelimiterToken: Parse + DelimiterValue {
const KIND: DelimiterKind;
fn new(spans: DoubleSpan) -> Self;
fn spans(&self) -> DoubleSpan;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DoubleSpan(pub Span, pub Bound<Span>);
impl DoubleSpan {
pub fn new(open: Span, close: Span) -> Self {
Self(open, Bound::Included(close))
}
pub fn synthetic(kind: DelimiterKind) -> Self {
let spelling = format!("{}{}", kind.opening(), kind.closing());
let span = Span::for_text(spelling);
let boundary = kind.opening().len();
Self::new(
span.subspan(0, boundary),
span.subspan(boundary, span.len().unwrap_or(boundary)),
)
}
pub fn unclosed(open: Span) -> Self {
Self(open, Bound::Unbounded)
}
pub fn open(&self) -> Span {
self.0.clone()
}
pub fn close(&self) -> Option<Span> {
match &self.1 {
Bound::Included(span) | Bound::Excluded(span) => Some(span.clone()),
Bound::Unbounded => None,
}
}
pub fn close_bound(&self) -> Bound<Span> {
self.1.clone()
}
pub(crate) fn complete(&mut self, close: Span) {
debug_assert!(matches!(self.1, Bound::Unbounded));
self.1 = Bound::Included(close);
}
pub fn is_closed(&self) -> bool {
!matches!(self.1, Bound::Unbounded)
}
}
impl Spanned for DoubleSpan {
fn try_span(&self) -> Option<Span> {
self.close()
.and_then(|close| self.0.join(close))
.or_else(|| Some(self.0.clone()))
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Delimiter {
pub kind: DelimiterKind,
pub spans: DoubleSpan,
opening_trivia: TrailingTrivia,
closing_trivia: TrailingTrivia,
}
impl Delimiter {
pub fn new(kind: DelimiterKind, spans: DoubleSpan) -> Self {
Self {
kind,
spans,
opening_trivia: TrailingTrivia::default(),
closing_trivia: TrailingTrivia::default(),
}
}
pub fn opening_span(&self) -> Span {
self.spans.open()
}
pub fn closing_span(&self) -> Option<Span> {
self.spans.close()
}
pub fn is_closed(&self) -> bool {
self.spans.is_closed()
}
}
impl Spanned for Delimiter {
fn try_span(&self) -> Option<Span> {
self.spans.try_span()
}
}
impl DelimiterValue for Delimiter {
fn from_delimiter(delimiter: Delimiter) -> Option<Self> {
Some(delimiter)
}
fn delimiter(&self) -> Delimiter {
self.clone()
}
fn expected() -> &'static str {
"a delimited group"
}
fn opening_trivia(&self) -> &TrailingTrivia {
&self.opening_trivia
}
fn opening_trivia_mut(&mut self) -> &mut TrailingTrivia {
&mut self.opening_trivia
}
fn closing_trivia(&self) -> &TrailingTrivia {
&self.closing_trivia
}
fn closing_trivia_mut(&mut self) -> &mut TrailingTrivia {
&mut self.closing_trivia
}
}
impl Parse for Delimiter {
fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
let group = parse_any_group(input, Self::expected())?;
if !group.stream().is_empty() {
return Err(TokenParseError::unexpected(
"an empty delimited group",
group.delim_kind().opening(),
group.expect_span(),
));
}
Ok(group.delimiter().clone())
}
}
impl Lex for Delimiter {
fn to_tokens(&self, output: &mut TokenStream) {
self.surround(output, TokenStream::new());
}
}
#[doc(hidden)]
pub fn parse_delimiter<D: DelimiterToken>(input: &mut ParseStream) -> Result<D, TokenParseError> {
let kind = D::KIND;
let group = parse_group(input, kind)?;
if !group.stream().is_empty() {
return Err(TokenParseError::unexpected(
kind.opening(),
kind.opening(),
group.expect_span(),
));
}
Ok(D::new(group.delimiter().spans.clone()))
}
pub(crate) fn parse_group(
input: &mut ParseStream,
kind: DelimiterKind,
) -> Result<TokenGroup, TokenParseError> {
let group = parse_any_group(input, kind.opening())?;
if group.delim_kind() != kind {
return Err(TokenParseError::unexpected(
kind.opening(),
group.delim_kind().opening(),
group.expect_span(),
));
}
Ok(group)
}
pub(crate) fn parse_any_group(
input: &mut ParseStream,
expected: &'static str,
) -> Result<TokenGroup, TokenParseError> {
let Some(token) = input.next_token() else {
return Err(TokenParseError::unexpected_end(expected, input.eof_span()));
};
let TokenTree::Group(group) = token else {
return Err(TokenParseError::unexpected_token(expected, &token));
};
Ok(group)
}
impl Display for Delimiter {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
formatter.write_str(self.kind.opening())
}
}
impl Display for DelimiterKind {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
formatter.write_str(self.opening())
}
}
impl DelimiterKind {
pub fn opening(self) -> &'static str {
match self {
Self::Parenthesis => "(",
Self::Bracket => "[",
Self::Brace => "{",
Self::AngleBar => "<|",
}
}
pub fn closing(self) -> &'static str {
match self {
Self::Parenthesis => ")",
Self::Bracket => "]",
Self::Brace => "}",
Self::AngleBar => "|>",
}
}
}