m2_syn/lex/token_stream/
delim.rs1use std::fmt::{Display, Formatter};
8
9use crate::{
10 Lex, Offset, Parse, ParseStream, Span, Spanned, TokenGroup, TokenParseError, TokenStream,
11 TokenTree,
12};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15pub enum DelimiterKind {
22 Parenthesis,
24 Bracket,
26 Brace,
28 AngleBar,
30}
31
32impl DelimiterKind {
33 pub const fn expression_name(self) -> &'static str {
35 match self {
36 Self::Parenthesis => "parenthesized expression",
37 Self::Bracket => "array expression",
38 Self::Brace => "list expression",
39 Self::AngleBar => "angle-bar list expression",
40 }
41 }
42}
43
44pub trait DelimiterValue: Spanned + Lex + Sized {
49 fn from_delimiter(delimiter: Delimiter) -> Option<Self>;
51
52 fn delimiter(&self) -> Delimiter;
54
55 fn expected() -> &'static str;
57
58 fn surround(&self, output: &mut TokenStream, contents: TokenStream) {
60 output.extend([TokenGroup::new(self.delimiter(), contents)]);
61 }
62}
63
64pub trait DelimiterToken: Parse + DelimiterValue {
70 const KIND: DelimiterKind;
72
73 fn new(spans: DoubleSpan) -> Self;
75
76 fn spans(&self) -> DoubleSpan;
79}
80
81#[derive(Debug, Clone, PartialEq, Eq, Default)]
89pub struct DoubleSpan(pub Span, pub Span);
90
91impl DoubleSpan {
92 pub fn new(open: Span, close: Span) -> Self {
94 Self(open, close)
95 }
96
97 pub fn detached() -> Self {
100 Self(Span::detached(), Span::detached())
101 }
102
103 pub fn unclosed(open: Span, eof: Offset) -> Self {
105 Self(open, Span::from_offset(eof))
106 }
107
108 pub fn open(&self) -> Span {
110 self.0.clone()
111 }
112
113 pub fn close(&self) -> Span {
115 self.1.clone()
116 }
117
118 pub fn is_closed(&self) -> bool {
120 self.1.bounds().is_none_or(|(start, end)| start != end)
121 }
122}
123
124impl Spanned for DoubleSpan {
125 fn span(&self) -> Span {
126 self.0.join(self.1.clone())
127 }
128}
129
130#[derive(Debug, Clone, PartialEq, Eq)]
131pub struct Delimiter {
133 pub kind: DelimiterKind,
135 pub spans: DoubleSpan,
137}
138
139impl Delimiter {
140 pub fn new(kind: DelimiterKind, spans: DoubleSpan) -> Self {
142 Self { kind, spans }
143 }
144
145 pub fn opening_span(&self) -> Span {
147 self.spans.open()
148 }
149
150 pub fn closing_span(&self) -> Span {
152 self.spans.close()
153 }
154
155 pub fn is_closed(&self) -> bool {
157 self.spans.is_closed()
158 }
159}
160
161impl Spanned for Delimiter {
162 fn span(&self) -> Span {
163 self.spans.span()
164 }
165}
166
167impl DelimiterValue for Delimiter {
168 fn from_delimiter(delimiter: Delimiter) -> Option<Self> {
169 Some(delimiter)
170 }
171
172 fn delimiter(&self) -> Delimiter {
173 self.clone()
174 }
175
176 fn expected() -> &'static str {
177 "a delimited group"
178 }
179}
180
181impl Parse for Delimiter {
182 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
183 let group = parse_any_group(input, Self::expected())?;
184 if !group.stream().is_empty() {
185 return Err(TokenParseError::unexpected(
186 "an empty delimited group",
187 group.delim_kind().opening(),
188 group.span(),
189 ));
190 }
191 Ok(group.delimiter().clone())
192 }
193}
194
195impl Lex for Delimiter {
196 fn to_tokens(&self, output: &mut TokenStream) {
197 self.surround(output, TokenStream::new());
198 }
199}
200
201#[doc(hidden)]
203pub fn parse_delimiter<D: DelimiterToken>(input: &mut ParseStream) -> Result<D, TokenParseError> {
204 let kind = D::KIND;
205 let group = parse_group(input, kind)?;
206 if !group.stream().is_empty() {
207 return Err(TokenParseError::unexpected(
208 kind.opening(),
209 kind.opening(),
210 group.span(),
211 ));
212 }
213 Ok(D::new(group.delimiter().spans.clone()))
214}
215
216pub(crate) fn parse_group(
217 input: &mut ParseStream,
218 kind: DelimiterKind,
219) -> Result<TokenGroup, TokenParseError> {
220 let group = parse_any_group(input, kind.opening())?;
221 if group.delim_kind() != kind {
222 return Err(TokenParseError::unexpected(
223 kind.opening(),
224 group.delim_kind().opening(),
225 group.span(),
226 ));
227 }
228 Ok(group)
229}
230
231pub(crate) fn parse_any_group(
232 input: &mut ParseStream,
233 expected: &'static str,
234) -> Result<TokenGroup, TokenParseError> {
235 let Some(token) = input.next_token() else {
236 return Err(TokenParseError::unexpected_end(expected, input.eof_span()));
237 };
238 let TokenTree::Group(group) = token else {
239 return Err(TokenParseError::unexpected_token(expected, &token));
240 };
241 Ok(group)
242}
243
244impl Display for Delimiter {
245 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
246 formatter.write_str(self.kind.opening())
247 }
248}
249impl Display for DelimiterKind {
250 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
251 formatter.write_str(self.opening())
252 }
253}
254
255impl DelimiterKind {
256 pub fn opening(self) -> &'static str {
258 match self {
259 Self::Parenthesis => "(",
260 Self::Bracket => "[",
261 Self::Brace => "{",
262 Self::AngleBar => "<|",
263 }
264 }
265
266 pub fn closing(self) -> &'static str {
268 match self {
269 Self::Parenthesis => ")",
270 Self::Bracket => "]",
271 Self::Brace => "}",
272 Self::AngleBar => "|>",
273 }
274 }
275}