m2_syn/parser/
delimited.rs1use crate::{
4 Delimiter, DelimiterValue, Lex, Parse, ParseStream, Spanned, TokenParseError, TokenStream,
5 parse2, token_stream::delim::parse_any_group,
6};
7#[cfg(feature = "pretty")]
8use crate::{PrettyNode, PrettyTree};
9
10#[derive(Debug, Clone, PartialEq, Eq, Spanned)]
30pub struct Delimited<S, D = Delimiter> {
31 pub delimiter: D,
33 pub contents: S,
35}
36
37#[macro_export]
42macro_rules! paren {
43 ($contents:expr, $span:expr $(,)?) => {
44 $crate::Delimited::new($crate::Delimiter, $contents)
45 };
46 ($contents:ty) => {
47 $crate::Delimited<$contents, $crate::Delimiter![()]>
48 };
49}
50
51#[macro_export]
55macro_rules! braces {
56 ($contents:expr, $span:expr $(,)?) => {
57 $crate::Delimited::new($crate::Delimiter, $contents)
58 };
59 ($contents:ty) => {
60 $crate::Delimited<$contents, $crate::Delimiter![{}]>
61 };
62}
63
64#[macro_export]
68macro_rules! brackets {
69 ($contents:expr, $span:expr $(,)?) => {
70 $crate::Delimited::new($crate::Delimiter![[]]($span), $contents)
71 };
72 ($contents:ty) => {
73 $crate::Delimited<$contents, $crate::Delimiter![[]]>
74 };
75}
76
77#[macro_export]
82macro_rules! angle_bars {
83 ($contents:expr, $span:expr $(,)?) => {
84 $crate::Delimited::new($crate::Delimiter, $contents)
85 };
86 ($contents:ty) => {
87 $crate::Delimited<$contents, $crate::Delimiter![<| |>]>
88 };
89}
90
91impl<S, D> Delimited<S, D> {
92 pub fn new(delimiter: D, contents: S) -> Self {
94 Self {
95 delimiter,
96 contents,
97 }
98 }
99
100 pub fn into_parts(self) -> (D, S) {
102 (self.delimiter, self.contents)
103 }
104}
105
106impl<S, D> Parse for Delimited<S, D>
107where
108 S: Parse,
109 D: DelimiterValue,
110{
111 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
112 let group = parse_any_group(input, D::expected())?;
113 let raw_delimiter = group.delimiter().clone();
114 let delimiter = D::from_delimiter(raw_delimiter.clone()).ok_or_else(|| {
115 TokenParseError::unexpected(
116 D::expected(),
117 raw_delimiter.kind.opening(),
118 raw_delimiter.expect_span(),
119 )
120 })?;
121 let contents = parse2(group.into_stream())?;
122 Ok(Self::new(delimiter, contents))
123 }
124}
125
126impl<S, D> Lex for Delimited<S, D>
127where
128 S: Lex,
129 D: DelimiterValue,
130{
131 fn to_tokens(&self, output: &mut TokenStream) {
132 self.delimiter
133 .surround(output, self.contents.to_token_stream());
134 }
135}
136
137#[cfg(feature = "pretty")]
138impl<S, D> PrettyTree for Delimited<S, D>
139where
140 S: PrettyTree + Spanned,
141 D: DelimiterValue,
142{
143 fn pretty_tree(&self) -> PrettyNode {
144 let delimiter = self.delimiter.delimiter();
145 let mut node = PrettyNode::collection("Delimited", self.try_span());
146 node.push_node(
147 "opening",
148 PrettyNode::delimiter_boundary(delimiter.kind, true, delimiter.opening_span()),
149 );
150 node.push("contents", &self.contents);
151 if let Some(closing) = delimiter.closing_span() {
152 node.push_node(
153 "closing",
154 PrettyNode::delimiter_boundary(delimiter.kind, false, closing),
155 );
156 }
157 node
158 }
159}
160
161#[cfg(test)]
162mod tests {
163 use super::Delimited;
164 use crate::{DelimiterKind, Lex, lex_str, parse2};
165
166 #[test]
167 fn arbitrary_delimiter_retains_each_family() {
168 for (source, expected) in [
169 ("(+)", DelimiterKind::Parenthesis),
170 ("[+]", DelimiterKind::Bracket),
171 ("{+}", DelimiterKind::Brace),
172 ("<|+|>", DelimiterKind::AngleBar),
173 ] {
174 let parsed: Delimited<Token![+]> = parse2(lex_str(source).unwrap()).unwrap();
175 assert_eq!(parsed.delimiter.kind, expected);
176 assert_eq!(parsed.to_m2(), source);
177 }
178 }
179}