aboutsummaryrefslogtreecommitdiff
path: root/crates/mbe/src/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/mbe/src/parser.rs')
-rw-r--r--crates/mbe/src/parser.rs130
1 files changed, 104 insertions, 26 deletions
diff --git a/crates/mbe/src/parser.rs b/crates/mbe/src/parser.rs
index f3047972d..8671322e1 100644
--- a/crates/mbe/src/parser.rs
+++ b/crates/mbe/src/parser.rs
@@ -3,15 +3,84 @@
3 3
4use smallvec::SmallVec; 4use smallvec::SmallVec;
5use syntax::SmolStr; 5use syntax::SmolStr;
6use tt::Delimiter;
6 7
7use crate::{tt_iter::TtIter, ExpandError, MetaTemplate}; 8use crate::{tt_iter::TtIter, ParseError};
9
10#[derive(Clone, Debug, PartialEq, Eq)]
11pub(crate) struct MetaTemplate(pub(crate) Vec<Op>);
12
13#[derive(Debug, Clone, Copy)]
14pub(crate) enum OpDelimited<'a> {
15 Op(&'a Op),
16 Open,
17 Close,
18}
19
20#[derive(Debug, Clone, Copy)]
21pub(crate) struct OpDelimitedIter<'a> {
22 inner: &'a Vec<Op>,
23 delimited: Option<&'a Delimiter>,
24 idx: usize,
25}
26
27impl<'a> OpDelimitedIter<'a> {
28 pub(crate) fn is_eof(&self) -> bool {
29 let len = self.inner.len() + if self.delimited.is_some() { 2 } else { 0 };
30 self.idx >= len
31 }
32
33 pub(crate) fn peek(&self) -> Option<OpDelimited<'a>> {
34 match self.delimited {
35 None => self.inner.get(self.idx).map(OpDelimited::Op),
36 Some(_) => match self.idx {
37 0 => Some(OpDelimited::Open),
38 i if i == self.inner.len() + 1 => Some(OpDelimited::Close),
39 i => self.inner.get(i - 1).map(OpDelimited::Op),
40 },
41 }
42 }
43
44 pub(crate) fn reset(&self) -> Self {
45 Self { inner: &self.inner, idx: 0, delimited: self.delimited }
46 }
47}
48
49impl<'a> Iterator for OpDelimitedIter<'a> {
50 type Item = OpDelimited<'a>;
51
52 fn next(&mut self) -> Option<Self::Item> {
53 let res = self.peek();
54 self.idx += 1;
55 res
56 }
57
58 fn size_hint(&self) -> (usize, Option<usize>) {
59 let len = self.inner.len() + if self.delimited.is_some() { 2 } else { 0 };
60 let remain = len.checked_sub(self.idx).unwrap_or(0);
61 (remain, Some(remain))
62 }
63}
64
65impl<'a> MetaTemplate {
66 pub(crate) fn iter(&self) -> impl Iterator<Item = &Op> {
67 self.0.iter()
68 }
69
70 pub(crate) fn iter_delimited(
71 &'a self,
72 delimited: Option<&'a Delimiter>,
73 ) -> OpDelimitedIter<'a> {
74 OpDelimitedIter { inner: &self.0, idx: 0, delimited }
75 }
76}
8 77
9#[derive(Clone, Debug, PartialEq, Eq)] 78#[derive(Clone, Debug, PartialEq, Eq)]
10pub(crate) enum Op { 79pub(crate) enum Op {
11 Var { name: SmolStr, kind: Option<SmolStr>, id: tt::TokenId }, 80 Var { name: SmolStr, kind: Option<SmolStr>, id: tt::TokenId },
12 Repeat { subtree: MetaTemplate, kind: RepeatKind, separator: Option<Separator> }, 81 Repeat { tokens: MetaTemplate, kind: RepeatKind, separator: Option<Separator> },
13 Leaf(tt::Leaf), 82 Leaf(tt::Leaf),
14 Subtree(MetaTemplate), 83 Subtree { tokens: MetaTemplate, delimiter: Option<Delimiter> },
15} 84}
16 85
17#[derive(Copy, Clone, Debug, PartialEq, Eq)] 86#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -46,12 +115,22 @@ impl PartialEq for Separator {
46 } 115 }
47} 116}
48 117
49pub(crate) fn parse_template(template: &tt::Subtree) -> Vec<Result<Op, ExpandError>> { 118impl Separator {
50 parse_inner(&template, Mode::Template) 119 pub(crate) fn tt_count(&self) -> usize {
120 match self {
121 Separator::Literal(_) => 1,
122 Separator::Ident(_) => 1,
123 Separator::Puncts(it) => it.len(),
124 }
125 }
126}
127
128pub(crate) fn parse_template(template: &tt::Subtree) -> Result<Vec<Op>, ParseError> {
129 parse_inner(&template, Mode::Template).into_iter().collect()
51} 130}
52 131
53pub(crate) fn parse_pattern(pattern: &tt::Subtree) -> Vec<Result<Op, ExpandError>> { 132pub(crate) fn parse_pattern(pattern: &tt::Subtree) -> Result<Vec<Op>, ParseError> {
54 parse_inner(&pattern, Mode::Pattern) 133 parse_inner(&pattern, Mode::Pattern).into_iter().collect()
55} 134}
56 135
57#[derive(Clone, Copy)] 136#[derive(Clone, Copy)]
@@ -60,7 +139,7 @@ enum Mode {
60 Template, 139 Template,
61} 140}
62 141
63fn parse_inner(tt: &tt::Subtree, mode: Mode) -> Vec<Result<Op, ExpandError>> { 142fn parse_inner(tt: &tt::Subtree, mode: Mode) -> Vec<Result<Op, ParseError>> {
64 let mut src = TtIter::new(&tt); 143 let mut src = TtIter::new(&tt);
65 std::iter::from_fn(move || { 144 std::iter::from_fn(move || {
66 let first = src.next()?; 145 let first = src.next()?;
@@ -71,7 +150,7 @@ fn parse_inner(tt: &tt::Subtree, mode: Mode) -> Vec<Result<Op, ExpandError>> {
71 150
72macro_rules! err { 151macro_rules! err {
73 ($($tt:tt)*) => { 152 ($($tt:tt)*) => {
74 ExpandError::UnexpectedToken 153 ParseError::UnexpectedToken(($($tt)*).to_string())
75 }; 154 };
76} 155}
77 156
@@ -81,7 +160,7 @@ macro_rules! bail {
81 }; 160 };
82} 161}
83 162
84fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Result<Op, ExpandError> { 163fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Result<Op, ParseError> {
85 let res = match first { 164 let res = match first {
86 tt::TokenTree::Leaf(leaf @ tt::Leaf::Punct(tt::Punct { char: '$', .. })) => { 165 tt::TokenTree::Leaf(leaf @ tt::Leaf::Punct(tt::Punct { char: '$', .. })) => {
87 // Note that the '$' itself is a valid token inside macro_rules. 166 // Note that the '$' itself is a valid token inside macro_rules.
@@ -92,17 +171,17 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
92 match second { 171 match second {
93 tt::TokenTree::Subtree(subtree) => { 172 tt::TokenTree::Subtree(subtree) => {
94 let (separator, kind) = parse_repeat(src)?; 173 let (separator, kind) = parse_repeat(src)?;
95 let delimiter = subtree.delimiter; 174 let tokens = parse_inner(&subtree, mode)
96 let tokens = parse_inner(&subtree, mode); 175 .into_iter()
97 let subtree = MetaTemplate { tokens, delimiter }; 176 .collect::<Result<Vec<Op>, ParseError>>()?;
98 Op::Repeat { subtree, separator, kind } 177 Op::Repeat { tokens: MetaTemplate(tokens), separator, kind }
99 } 178 }
100 tt::TokenTree::Leaf(leaf) => match leaf { 179 tt::TokenTree::Leaf(leaf) => match leaf {
101 tt::Leaf::Punct(punct) => { 180 tt::Leaf::Punct(punct) => {
102 static UNDERSCORE: SmolStr = SmolStr::new_inline("_"); 181 static UNDERSCORE: SmolStr = SmolStr::new_inline("_");
103 182
104 if punct.char != '_' { 183 if punct.char != '_' {
105 return Err(ExpandError::UnexpectedToken); 184 return Err(ParseError::Expected("_".to_string()));
106 } 185 }
107 let name = UNDERSCORE.clone(); 186 let name = UNDERSCORE.clone();
108 let kind = eat_fragment_kind(src, mode)?; 187 let kind = eat_fragment_kind(src, mode)?;
@@ -134,16 +213,15 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
134 } 213 }
135 tt::TokenTree::Leaf(tt) => Op::Leaf(tt.clone()), 214 tt::TokenTree::Leaf(tt) => Op::Leaf(tt.clone()),
136 tt::TokenTree::Subtree(subtree) => { 215 tt::TokenTree::Subtree(subtree) => {
137 let delimiter = subtree.delimiter; 216 let tokens =
138 let tokens = parse_inner(&subtree, mode); 217 parse_inner(&subtree, mode).into_iter().collect::<Result<Vec<Op>, ParseError>>()?;
139 let subtree = MetaTemplate { tokens, delimiter }; 218 Op::Subtree { tokens: MetaTemplate(tokens), delimiter: subtree.delimiter }
140 Op::Subtree(subtree)
141 } 219 }
142 }; 220 };
143 Ok(res) 221 Ok(res)
144} 222}
145 223
146fn eat_fragment_kind<'a>(src: &mut TtIter<'a>, mode: Mode) -> Result<Option<SmolStr>, ExpandError> { 224fn eat_fragment_kind<'a>(src: &mut TtIter<'a>, mode: Mode) -> Result<Option<SmolStr>, ParseError> {
147 if let Mode::Pattern = mode { 225 if let Mode::Pattern = mode {
148 src.expect_char(':').map_err(|()| err!("bad fragment specifier 1"))?; 226 src.expect_char(':').map_err(|()| err!("bad fragment specifier 1"))?;
149 let ident = src.expect_ident().map_err(|()| err!("bad fragment specifier 1"))?; 227 let ident = src.expect_ident().map_err(|()| err!("bad fragment specifier 1"))?;
@@ -156,12 +234,12 @@ fn is_boolean_literal(lit: &tt::Literal) -> bool {
156 matches!(lit.text.as_str(), "true" | "false") 234 matches!(lit.text.as_str(), "true" | "false")
157} 235}
158 236
159fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), ExpandError> { 237fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), ParseError> {
160 let mut separator = Separator::Puncts(SmallVec::new()); 238 let mut separator = Separator::Puncts(SmallVec::new());
161 for tt in src { 239 for tt in src {
162 let tt = match tt { 240 let tt = match tt {
163 tt::TokenTree::Leaf(leaf) => leaf, 241 tt::TokenTree::Leaf(leaf) => leaf,
164 tt::TokenTree::Subtree(_) => return Err(ExpandError::InvalidRepeat), 242 tt::TokenTree::Subtree(_) => return Err(ParseError::InvalidRepeat),
165 }; 243 };
166 let has_sep = match &separator { 244 let has_sep = match &separator {
167 Separator::Puncts(puncts) => !puncts.is_empty(), 245 Separator::Puncts(puncts) => !puncts.is_empty(),
@@ -169,7 +247,7 @@ fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), Exp
169 }; 247 };
170 match tt { 248 match tt {
171 tt::Leaf::Ident(_) | tt::Leaf::Literal(_) if has_sep => { 249 tt::Leaf::Ident(_) | tt::Leaf::Literal(_) if has_sep => {
172 return Err(ExpandError::InvalidRepeat) 250 return Err(ParseError::InvalidRepeat)
173 } 251 }
174 tt::Leaf::Ident(ident) => separator = Separator::Ident(ident.clone()), 252 tt::Leaf::Ident(ident) => separator = Separator::Ident(ident.clone()),
175 tt::Leaf::Literal(lit) => separator = Separator::Literal(lit.clone()), 253 tt::Leaf::Literal(lit) => separator = Separator::Literal(lit.clone()),
@@ -182,11 +260,11 @@ fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), Exp
182 match &mut separator { 260 match &mut separator {
183 Separator::Puncts(puncts) => { 261 Separator::Puncts(puncts) => {
184 if puncts.len() == 3 { 262 if puncts.len() == 3 {
185 return Err(ExpandError::InvalidRepeat); 263 return Err(ParseError::InvalidRepeat);
186 } 264 }
187 puncts.push(punct.clone()) 265 puncts.push(punct.clone())
188 } 266 }
189 _ => return Err(ExpandError::InvalidRepeat), 267 _ => return Err(ParseError::InvalidRepeat),
190 } 268 }
191 continue; 269 continue;
192 } 270 }
@@ -196,5 +274,5 @@ fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), Exp
196 } 274 }
197 } 275 }
198 } 276 }
199 Err(ExpandError::InvalidRepeat) 277 Err(ParseError::InvalidRepeat)
200} 278}