diff options
Diffstat (limited to 'crates/mbe/src/lib.rs')
-rw-r--r-- | crates/mbe/src/lib.rs | 46 |
1 files changed, 33 insertions, 13 deletions
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs index 3ad609a00..7878faaa4 100644 --- a/crates/mbe/src/lib.rs +++ b/crates/mbe/src/lib.rs | |||
@@ -14,10 +14,10 @@ mod tests; | |||
14 | 14 | ||
15 | use std::fmt; | 15 | use std::fmt; |
16 | 16 | ||
17 | pub use tt::{Delimiter, Punct}; | 17 | pub use tt::{Delimiter, DelimiterKind, Punct}; |
18 | 18 | ||
19 | use crate::{ | 19 | use crate::{ |
20 | parser::{parse_pattern, Op}, | 20 | parser::{parse_pattern, parse_template, Op}, |
21 | tt_iter::TtIter, | 21 | tt_iter::TtIter, |
22 | }; | 22 | }; |
23 | 23 | ||
@@ -78,8 +78,24 @@ pub struct MacroRules { | |||
78 | 78 | ||
79 | #[derive(Clone, Debug, PartialEq, Eq)] | 79 | #[derive(Clone, Debug, PartialEq, Eq)] |
80 | struct Rule { | 80 | struct Rule { |
81 | lhs: tt::Subtree, | 81 | lhs: MetaTemplate, |
82 | rhs: tt::Subtree, | 82 | rhs: MetaTemplate, |
83 | } | ||
84 | |||
85 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
86 | struct MetaTemplate { | ||
87 | delimiter: Option<Delimiter>, | ||
88 | tokens: Vec<Result<Op, ExpandError>>, | ||
89 | } | ||
90 | |||
91 | impl<'a> MetaTemplate { | ||
92 | fn iter(&self) -> impl Iterator<Item = &Result<Op, ExpandError>> { | ||
93 | self.tokens.iter() | ||
94 | } | ||
95 | |||
96 | fn delimiter_kind(&self) -> Option<DelimiterKind> { | ||
97 | self.delimiter.map(|it| it.kind) | ||
98 | } | ||
83 | } | 99 | } |
84 | 100 | ||
85 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | 101 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
@@ -167,7 +183,7 @@ impl MacroRules { | |||
167 | rules.push(rule); | 183 | rules.push(rule); |
168 | if let Err(()) = src.expect_char(';') { | 184 | if let Err(()) = src.expect_char(';') { |
169 | if src.len() > 0 { | 185 | if src.len() > 0 { |
170 | return Err(ParseError::Expected("expected `:`".to_string())); | 186 | return Err(ParseError::Expected("expected `;`".to_string())); |
171 | } | 187 | } |
172 | break; | 188 | break; |
173 | } | 189 | } |
@@ -213,11 +229,15 @@ impl Rule { | |||
213 | .map_err(|()| ParseError::Expected("expected subtree".to_string()))? | 229 | .map_err(|()| ParseError::Expected("expected subtree".to_string()))? |
214 | .clone(); | 230 | .clone(); |
215 | rhs.delimiter = None; | 231 | rhs.delimiter = None; |
232 | |||
233 | let lhs = MetaTemplate { tokens: parse_pattern(&lhs), delimiter: None }; | ||
234 | let rhs = MetaTemplate { tokens: parse_template(&rhs), delimiter: None }; | ||
235 | |||
216 | Ok(crate::Rule { lhs, rhs }) | 236 | Ok(crate::Rule { lhs, rhs }) |
217 | } | 237 | } |
218 | } | 238 | } |
219 | 239 | ||
220 | fn to_parse_error(e: ExpandError) -> ParseError { | 240 | fn to_parse_error(e: &ExpandError) -> ParseError { |
221 | let msg = match e { | 241 | let msg = match e { |
222 | ExpandError::InvalidRepeat => "invalid repeat".to_string(), | 242 | ExpandError::InvalidRepeat => "invalid repeat".to_string(), |
223 | _ => "invalid macro definition".to_string(), | 243 | _ => "invalid macro definition".to_string(), |
@@ -225,22 +245,22 @@ fn to_parse_error(e: ExpandError) -> ParseError { | |||
225 | ParseError::Expected(msg) | 245 | ParseError::Expected(msg) |
226 | } | 246 | } |
227 | 247 | ||
228 | fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> { | 248 | fn validate(pattern: &MetaTemplate) -> Result<(), ParseError> { |
229 | for op in parse_pattern(pattern) { | 249 | for op in pattern.iter() { |
230 | let op = op.map_err(to_parse_error)?; | 250 | let op = op.as_ref().map_err(|e| to_parse_error(&e))?; |
231 | 251 | ||
232 | match op { | 252 | match op { |
233 | Op::TokenTree(tt::TokenTree::Subtree(subtree)) => validate(subtree)?, | 253 | Op::Subtree(subtree) => validate(&subtree)?, |
234 | Op::Repeat { subtree, separator, .. } => { | 254 | Op::Repeat { subtree, separator, .. } => { |
235 | // Checks that no repetition which could match an empty token | 255 | // Checks that no repetition which could match an empty token |
236 | // https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558 | 256 | // https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558 |
237 | 257 | ||
238 | if separator.is_none() { | 258 | if separator.is_none() { |
239 | if parse_pattern(subtree).all(|child_op| { | 259 | if subtree.iter().all(|child_op| { |
240 | match child_op.map_err(to_parse_error) { | 260 | match child_op.as_ref().map_err(to_parse_error) { |
241 | Ok(Op::Var { kind, .. }) => { | 261 | Ok(Op::Var { kind, .. }) => { |
242 | // vis is optional | 262 | // vis is optional |
243 | if kind.map_or(false, |it| it == "vis") { | 263 | if kind.as_ref().map_or(false, |it| it == "vis") { |
244 | return true; | 264 | return true; |
245 | } | 265 | } |
246 | } | 266 | } |