diff options
Diffstat (limited to 'crates/mbe/src/lib.rs')
-rw-r--r-- | crates/mbe/src/lib.rs | 130 |
1 files changed, 85 insertions, 45 deletions
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs index 19543d777..f3d2da55a 100644 --- a/crates/mbe/src/lib.rs +++ b/crates/mbe/src/lib.rs | |||
@@ -4,7 +4,7 @@ | |||
4 | //! `TokenTree`s as well! | 4 | //! `TokenTree`s as well! |
5 | 5 | ||
6 | mod parser; | 6 | mod parser; |
7 | mod mbe_expander; | 7 | mod expander; |
8 | mod syntax_bridge; | 8 | mod syntax_bridge; |
9 | mod tt_iter; | 9 | mod tt_iter; |
10 | mod subtree_source; | 10 | mod subtree_source; |
@@ -12,18 +12,24 @@ mod subtree_source; | |||
12 | #[cfg(test)] | 12 | #[cfg(test)] |
13 | mod tests; | 13 | mod tests; |
14 | 14 | ||
15 | #[cfg(test)] | ||
16 | mod benchmark; | ||
17 | |||
15 | use std::fmt; | 18 | use std::fmt; |
16 | 19 | ||
20 | use test_utils::mark; | ||
17 | pub use tt::{Delimiter, DelimiterKind, Punct}; | 21 | pub use tt::{Delimiter, DelimiterKind, Punct}; |
18 | 22 | ||
19 | use crate::{ | 23 | use crate::{ |
20 | parser::{parse_pattern, parse_template, Op}, | 24 | parser::{parse_pattern, parse_template, MetaTemplate, Op}, |
21 | tt_iter::TtIter, | 25 | tt_iter::TtIter, |
22 | }; | 26 | }; |
23 | 27 | ||
24 | #[derive(Debug, PartialEq, Eq)] | 28 | #[derive(Debug, PartialEq, Eq)] |
25 | pub enum ParseError { | 29 | pub enum ParseError { |
30 | UnexpectedToken(String), | ||
26 | Expected(String), | 31 | Expected(String), |
32 | InvalidRepeat, | ||
27 | RepetitionEmptyTokenTree, | 33 | RepetitionEmptyTokenTree, |
28 | } | 34 | } |
29 | 35 | ||
@@ -33,7 +39,6 @@ pub enum ExpandError { | |||
33 | UnexpectedToken, | 39 | UnexpectedToken, |
34 | BindingError(String), | 40 | BindingError(String), |
35 | ConversionError, | 41 | ConversionError, |
36 | InvalidRepeat, | ||
37 | ProcMacroError(tt::ExpansionError), | 42 | ProcMacroError(tt::ExpansionError), |
38 | UnresolvedProcMacro, | 43 | UnresolvedProcMacro, |
39 | Other(String), | 44 | Other(String), |
@@ -52,7 +57,6 @@ impl fmt::Display for ExpandError { | |||
52 | ExpandError::UnexpectedToken => f.write_str("unexpected token in input"), | 57 | ExpandError::UnexpectedToken => f.write_str("unexpected token in input"), |
53 | ExpandError::BindingError(e) => f.write_str(e), | 58 | ExpandError::BindingError(e) => f.write_str(e), |
54 | ExpandError::ConversionError => f.write_str("could not convert tokens"), | 59 | ExpandError::ConversionError => f.write_str("could not convert tokens"), |
55 | ExpandError::InvalidRepeat => f.write_str("invalid repeat expression"), | ||
56 | ExpandError::ProcMacroError(e) => e.fmt(f), | 60 | ExpandError::ProcMacroError(e) => e.fmt(f), |
57 | ExpandError::UnresolvedProcMacro => f.write_str("unresolved proc macro"), | 61 | ExpandError::UnresolvedProcMacro => f.write_str("unresolved proc macro"), |
58 | ExpandError::Other(e) => f.write_str(e), | 62 | ExpandError::Other(e) => f.write_str(e), |
@@ -61,8 +65,8 @@ impl fmt::Display for ExpandError { | |||
61 | } | 65 | } |
62 | 66 | ||
63 | pub use crate::syntax_bridge::{ | 67 | pub use crate::syntax_bridge::{ |
64 | ast_to_token_tree, parse_to_token_tree, syntax_node_to_token_tree, token_tree_to_syntax_node, | 68 | ast_to_token_tree, parse_exprs_with_sep, parse_to_token_tree, syntax_node_to_token_tree, |
65 | TokenMap, | 69 | token_tree_to_syntax_node, TokenMap, |
66 | }; | 70 | }; |
67 | 71 | ||
68 | /// This struct contains AST for a single `macro_rules` definition. What might | 72 | /// This struct contains AST for a single `macro_rules` definition. What might |
@@ -76,26 +80,18 @@ pub struct MacroRules { | |||
76 | shift: Shift, | 80 | shift: Shift, |
77 | } | 81 | } |
78 | 82 | ||
83 | /// For Macro 2.0 | ||
79 | #[derive(Clone, Debug, PartialEq, Eq)] | 84 | #[derive(Clone, Debug, PartialEq, Eq)] |
80 | struct Rule { | 85 | pub struct MacroDef { |
81 | lhs: MetaTemplate, | 86 | rules: Vec<Rule>, |
82 | rhs: MetaTemplate, | 87 | /// Highest id of the token we have in TokenMap |
88 | shift: Shift, | ||
83 | } | 89 | } |
84 | 90 | ||
85 | #[derive(Clone, Debug, PartialEq, Eq)] | 91 | #[derive(Clone, Debug, PartialEq, Eq)] |
86 | struct MetaTemplate { | 92 | struct Rule { |
87 | delimiter: Option<Delimiter>, | 93 | lhs: MetaTemplate, |
88 | tokens: Vec<Result<Op, ExpandError>>, | 94 | rhs: MetaTemplate, |
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 | } | ||
99 | } | 95 | } |
100 | 96 | ||
101 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | 97 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
@@ -179,7 +175,7 @@ impl MacroRules { | |||
179 | let mut src = TtIter::new(tt); | 175 | let mut src = TtIter::new(tt); |
180 | let mut rules = Vec::new(); | 176 | let mut rules = Vec::new(); |
181 | while src.len() > 0 { | 177 | while src.len() > 0 { |
182 | let rule = Rule::parse(&mut src)?; | 178 | let rule = Rule::parse(&mut src, true)?; |
183 | rules.push(rule); | 179 | rules.push(rule); |
184 | if let Err(()) = src.expect_char(';') { | 180 | if let Err(()) = src.expect_char(';') { |
185 | if src.len() > 0 { | 181 | if src.len() > 0 { |
@@ -200,7 +196,58 @@ impl MacroRules { | |||
200 | // apply shift | 196 | // apply shift |
201 | let mut tt = tt.clone(); | 197 | let mut tt = tt.clone(); |
202 | self.shift.shift_all(&mut tt); | 198 | self.shift.shift_all(&mut tt); |
203 | mbe_expander::expand(self, &tt) | 199 | expander::expand_rules(&self.rules, &tt) |
200 | } | ||
201 | |||
202 | pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId { | ||
203 | self.shift.shift(id) | ||
204 | } | ||
205 | |||
206 | pub fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, Origin) { | ||
207 | match self.shift.unshift(id) { | ||
208 | Some(id) => (id, Origin::Call), | ||
209 | None => (id, Origin::Def), | ||
210 | } | ||
211 | } | ||
212 | } | ||
213 | |||
214 | impl MacroDef { | ||
215 | pub fn parse(tt: &tt::Subtree) -> Result<MacroDef, ParseError> { | ||
216 | let mut src = TtIter::new(tt); | ||
217 | let mut rules = Vec::new(); | ||
218 | |||
219 | if Some(tt::DelimiterKind::Brace) == tt.delimiter_kind() { | ||
220 | mark::hit!(parse_macro_def_rules); | ||
221 | while src.len() > 0 { | ||
222 | let rule = Rule::parse(&mut src, true)?; | ||
223 | rules.push(rule); | ||
224 | if let Err(()) = src.expect_char(';') { | ||
225 | if src.len() > 0 { | ||
226 | return Err(ParseError::Expected("expected `;`".to_string())); | ||
227 | } | ||
228 | break; | ||
229 | } | ||
230 | } | ||
231 | } else { | ||
232 | mark::hit!(parse_macro_def_simple); | ||
233 | let rule = Rule::parse(&mut src, false)?; | ||
234 | if src.len() != 0 { | ||
235 | return Err(ParseError::Expected("remain tokens in macro def".to_string())); | ||
236 | } | ||
237 | rules.push(rule); | ||
238 | } | ||
239 | for rule in rules.iter() { | ||
240 | validate(&rule.lhs)?; | ||
241 | } | ||
242 | |||
243 | Ok(MacroDef { rules, shift: Shift::new(tt) }) | ||
244 | } | ||
245 | |||
246 | pub fn expand(&self, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> { | ||
247 | // apply shift | ||
248 | let mut tt = tt.clone(); | ||
249 | self.shift.shift_all(&mut tt); | ||
250 | expander::expand_rules(&self.rules, &tt) | ||
204 | } | 251 | } |
205 | 252 | ||
206 | pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId { | 253 | pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId { |
@@ -216,57 +263,50 @@ impl MacroRules { | |||
216 | } | 263 | } |
217 | 264 | ||
218 | impl Rule { | 265 | impl Rule { |
219 | fn parse(src: &mut TtIter) -> Result<Rule, ParseError> { | 266 | fn parse(src: &mut TtIter, expect_arrow: bool) -> Result<Rule, ParseError> { |
220 | let lhs = src | 267 | let lhs = src |
221 | .expect_subtree() | 268 | .expect_subtree() |
222 | .map_err(|()| ParseError::Expected("expected subtree".to_string()))?; | 269 | .map_err(|()| ParseError::Expected("expected subtree".to_string()))?; |
223 | src.expect_char('=').map_err(|()| ParseError::Expected("expected `=`".to_string()))?; | 270 | if expect_arrow { |
224 | src.expect_char('>').map_err(|()| ParseError::Expected("expected `>`".to_string()))?; | 271 | src.expect_char('=').map_err(|()| ParseError::Expected("expected `=`".to_string()))?; |
272 | src.expect_char('>').map_err(|()| ParseError::Expected("expected `>`".to_string()))?; | ||
273 | } | ||
225 | let rhs = src | 274 | let rhs = src |
226 | .expect_subtree() | 275 | .expect_subtree() |
227 | .map_err(|()| ParseError::Expected("expected subtree".to_string()))?; | 276 | .map_err(|()| ParseError::Expected("expected subtree".to_string()))?; |
228 | 277 | ||
229 | let lhs = MetaTemplate { tokens: parse_pattern(&lhs), delimiter: None }; | 278 | let lhs = MetaTemplate(parse_pattern(&lhs)?); |
230 | let rhs = MetaTemplate { tokens: parse_template(&rhs), delimiter: None }; | 279 | let rhs = MetaTemplate(parse_template(&rhs)?); |
231 | 280 | ||
232 | Ok(crate::Rule { lhs, rhs }) | 281 | Ok(crate::Rule { lhs, rhs }) |
233 | } | 282 | } |
234 | } | 283 | } |
235 | 284 | ||
236 | fn to_parse_error(e: &ExpandError) -> ParseError { | ||
237 | let msg = match e { | ||
238 | ExpandError::InvalidRepeat => "invalid repeat".to_string(), | ||
239 | _ => "invalid macro definition".to_string(), | ||
240 | }; | ||
241 | ParseError::Expected(msg) | ||
242 | } | ||
243 | |||
244 | fn validate(pattern: &MetaTemplate) -> Result<(), ParseError> { | 285 | fn validate(pattern: &MetaTemplate) -> Result<(), ParseError> { |
245 | for op in pattern.iter() { | 286 | for op in pattern.iter() { |
246 | let op = op.as_ref().map_err(|e| to_parse_error(&e))?; | ||
247 | |||
248 | match op { | 287 | match op { |
249 | Op::Subtree(subtree) => validate(&subtree)?, | 288 | Op::Subtree { tokens, .. } => validate(&tokens)?, |
250 | Op::Repeat { subtree, separator, .. } => { | 289 | Op::Repeat { tokens: subtree, separator, .. } => { |
251 | // Checks that no repetition which could match an empty token | 290 | // Checks that no repetition which could match an empty token |
252 | // https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558 | 291 | // https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558 |
253 | 292 | ||
254 | if separator.is_none() { | 293 | if separator.is_none() { |
255 | if subtree.iter().all(|child_op| { | 294 | if subtree.iter().all(|child_op| { |
256 | match child_op.as_ref().map_err(to_parse_error) { | 295 | match child_op { |
257 | Ok(Op::Var { kind, .. }) => { | 296 | Op::Var { kind, .. } => { |
258 | // vis is optional | 297 | // vis is optional |
259 | if kind.as_ref().map_or(false, |it| it == "vis") { | 298 | if kind.as_ref().map_or(false, |it| it == "vis") { |
260 | return true; | 299 | return true; |
261 | } | 300 | } |
262 | } | 301 | } |
263 | Ok(Op::Repeat { kind, .. }) => { | 302 | Op::Repeat { kind, .. } => { |
264 | return matches!( | 303 | return matches!( |
265 | kind, | 304 | kind, |
266 | parser::RepeatKind::ZeroOrMore | parser::RepeatKind::ZeroOrOne | 305 | parser::RepeatKind::ZeroOrMore | parser::RepeatKind::ZeroOrOne |
267 | ) | 306 | ) |
268 | } | 307 | } |
269 | _ => {} | 308 | Op::Leaf(_) => {} |
309 | Op::Subtree { .. } => {} | ||
270 | } | 310 | } |
271 | false | 311 | false |
272 | }) { | 312 | }) { |