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