aboutsummaryrefslogtreecommitdiff
path: root/crates/mbe/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/mbe/src/lib.rs')
-rw-r--r--crates/mbe/src/lib.rs130
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
6mod parser; 6mod parser;
7mod mbe_expander; 7mod expander;
8mod syntax_bridge; 8mod syntax_bridge;
9mod tt_iter; 9mod tt_iter;
10mod subtree_source; 10mod subtree_source;
@@ -12,18 +12,24 @@ mod subtree_source;
12#[cfg(test)] 12#[cfg(test)]
13mod tests; 13mod tests;
14 14
15#[cfg(test)]
16mod benchmark;
17
15use std::fmt; 18use std::fmt;
16 19
20use test_utils::mark;
17pub use tt::{Delimiter, DelimiterKind, Punct}; 21pub use tt::{Delimiter, DelimiterKind, Punct};
18 22
19use crate::{ 23use 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)]
25pub enum ParseError { 29pub 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
63pub use crate::syntax_bridge::{ 67pub 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)]
80struct Rule { 85pub 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)]
86struct MetaTemplate { 92struct Rule {
87 delimiter: Option<Delimiter>, 93 lhs: MetaTemplate,
88 tokens: Vec<Result<Op, ExpandError>>, 94 rhs: MetaTemplate,
89}
90
91impl<'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
214impl 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
218impl Rule { 265impl 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
236fn 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
244fn validate(pattern: &MetaTemplate) -> Result<(), ParseError> { 285fn 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 }) {