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("contents", &self.contents);
147 node.push_node(
148 "delimiter",
149 PrettyNode::delimiter(delimiter.kind, delimiter.spans),
150 );
151 node
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::Delimited;
158 use crate::{DelimiterKind, Lex, lex_str, parse2};
159
160 #[test]
161 fn arbitrary_delimiter_retains_each_family() {
162 for (source, expected) in [
163 ("(+)", DelimiterKind::Parenthesis),
164 ("[+]", DelimiterKind::Bracket),
165 ("{+}", DelimiterKind::Brace),
166 ("<|+|>", DelimiterKind::AngleBar),
167 ] {
168 let parsed: Delimited<Token![+]> = parse2(lex_str(source).unwrap()).unwrap();
169 assert_eq!(parsed.delimiter.kind, expected);
170 assert_eq!(parsed.to_m2(), source);
171 }
172 }
173}