1use crate::{
4 CellStream, DelimiterKind, DelimiterToken, Parse, ParseStream, Span, Spanned, TextRange,
5 ToCells, ToTokens, TokenParseError, TokenStream, TokenTree, parse1,
6};
7
8#[derive(Debug, Clone, PartialEq, Eq, Spanned)]
25pub struct Delimited<S, D> {
26 pub delimiter: D,
28 pub contents: S,
30}
31
32#[macro_export]
37macro_rules! paren {
38 ($contents:expr, $span:expr $(,)?) => {
39 $crate::Delimited::new($crate::Delimiter, $contents)
40 };
41 ($contents:ty) => {
42 $crate::Delimited<$contents, $crate::Delimiter![()]>
43 };
44}
45
46#[macro_export]
50macro_rules! braces {
51 ($contents:expr, $span:expr $(,)?) => {
52 $crate::Delimited::new($crate::Delimiter, $contents)
53 };
54 ($contents:ty) => {
55 $crate::Delimited<$contents, $crate::Delimiter![{}]>
56 };
57}
58
59#[macro_export]
63macro_rules! brackets {
64 ($contents:expr, $span:expr $(,)?) => {
65 $crate::Delimited::new($crate::Delimiter![[]]($span), $contents)
66 };
67 ($contents:ty) => {
68 $crate::Delimited<$contents, $crate::Delimiter![[]]>
69 };
70}
71
72#[macro_export]
77macro_rules! angle_bars {
78 ($contents:expr, $span:expr $(,)?) => {
79 $crate::Delimited::new($crate::Delimiter, $contents)
80 };
81 ($contents:ty) => {
82 $crate::Delimited<$contents, $crate::Delimiter![<| |>]>
83 };
84}
85
86#[macro_export]
90macro_rules! naked {
91 ($contents:expr, $span:expr $(,)?) => {
92 $crate::Delimited::new($crate::Delimiter, $contents)
93 };
94 ($contents:ty) => {
95 $crate::Delimited<$contents, $crate::Delimiter![]>
96 };
97}
98
99#[macro_export]
104macro_rules! semicolon {
105 ($contents:expr, $span:expr $(,)?) => {
106 $crate::Delimited::new($crate::Delimiter, $contents)
107 };
108 ($contents:ty) => {
109 $crate::Delimited<$contents, $crate::Delimiter![;]>
110 };
111}
112
113impl<S, D> Delimited<S, D> {
114 pub fn new(delimiter: D, contents: S) -> Self {
116 Self {
117 delimiter,
118 contents,
119 }
120 }
121
122 pub fn into_parts(self) -> (D, S) {
124 (self.delimiter, self.contents)
125 }
126}
127
128impl<S, D> Parse for Delimited<S, D>
129where
130 S: Parse,
131 D: DelimiterToken,
132{
133 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
134 if D::KIND == DelimiterKind::Empty {
135 let opening = input
136 .peek()
137 .map(|token| boundary_before(token.span()))
138 .unwrap_or_else(|| input.eof_span());
139 let contents = S::parse(input)?;
140 let delimiter = D::new(opening.join(input.eof_span()));
141 return Ok(Self::new(delimiter, contents));
142 }
143
144 if D::KIND == DelimiterKind::Semicolon {
145 if input
146 .peek()
147 .is_some_and(<Token![;] as crate::Token>::matches_token_tree)
148 {
149 let semicolon = input.peek().unwrap();
150 return Err(TokenParseError::UnexpectedToken {
151 expected: "nonempty syntax before `;`",
152 found: ";".to_owned(),
153 span: semicolon.span(),
154 });
155 }
156 let opening = input
157 .peek()
158 .map(|token| boundary_before(token.span()))
159 .unwrap_or_else(|| input.eof_span());
160 let contents = S::parse(input)?;
161 let semicolon = <Token![;]>::parse(input)?;
162 let delimiter = D::new(opening.join(semicolon.span()));
163 return Ok(Self::new(delimiter, contents));
164 }
165
166 let Some(token) = input.next_token() else {
167 return Err(TokenParseError::UnexpectedEnd {
168 expected: D::KIND.opening(),
169 span: input.eof_span(),
170 });
171 };
172 let span = token.span();
173 let TokenTree::Group(group) = token else {
174 return Err(TokenParseError::UnexpectedToken {
175 expected: D::KIND.opening(),
176 found: token.spelling().unwrap_or("trivia").to_owned(),
177 span,
178 });
179 };
180 if group.delim_kind() != D::KIND {
181 return Err(TokenParseError::UnexpectedToken {
182 expected: D::KIND.opening(),
183 found: group.delim_kind().to_string(),
184 span,
185 });
186 }
187
188 let delimiter = D::new(group.span());
189 let contents = parse1(group.into_stream())?;
190 Ok(Self::new(delimiter, contents))
191 }
192}
193
194fn boundary_before(span: Span) -> Span {
195 span.source()
196 .ok()
197 .zip(span.start_point().ok())
198 .map(|(source, point)| Span::new(source, TextRange::from_point(point)))
199 .unwrap_or_else(Span::detached)
200}
201
202impl<S, D> ToTokens for Delimited<S, D>
203where
204 S: ToTokens,
205 D: DelimiterToken,
206{
207 fn to_tokens(&self, output: &mut TokenStream) {
208 self.delimiter
209 .surround(output, self.contents.to_token_stream());
210 }
211}
212
213impl<S, D> ToCells for Delimited<S, D>
214where
215 S: ToCells,
216{
217 fn to_cells(&self, output: &mut CellStream) {
218 self.contents.to_cells(output);
219 }
220}