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