diff options
Diffstat (limited to 'crates/mbe/src/lib.rs')
-rw-r--r-- | crates/mbe/src/lib.rs | 72 |
1 files changed, 67 insertions, 5 deletions
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs index 19543d777..35cde5f10 100644 --- a/crates/mbe/src/lib.rs +++ b/crates/mbe/src/lib.rs | |||
@@ -14,6 +14,7 @@ mod tests; | |||
14 | 14 | ||
15 | use std::fmt; | 15 | use std::fmt; |
16 | 16 | ||
17 | use test_utils::mark; | ||
17 | pub use tt::{Delimiter, DelimiterKind, Punct}; | 18 | pub use tt::{Delimiter, DelimiterKind, Punct}; |
18 | 19 | ||
19 | use crate::{ | 20 | use crate::{ |
@@ -76,6 +77,14 @@ pub struct MacroRules { | |||
76 | shift: Shift, | 77 | shift: Shift, |
77 | } | 78 | } |
78 | 79 | ||
80 | /// For Macro 2.0 | ||
81 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
82 | pub struct MacroDef { | ||
83 | rules: Vec<Rule>, | ||
84 | /// Highest id of the token we have in TokenMap | ||
85 | shift: Shift, | ||
86 | } | ||
87 | |||
79 | #[derive(Clone, Debug, PartialEq, Eq)] | 88 | #[derive(Clone, Debug, PartialEq, Eq)] |
80 | struct Rule { | 89 | struct Rule { |
81 | lhs: MetaTemplate, | 90 | lhs: MetaTemplate, |
@@ -179,7 +188,7 @@ impl MacroRules { | |||
179 | let mut src = TtIter::new(tt); | 188 | let mut src = TtIter::new(tt); |
180 | let mut rules = Vec::new(); | 189 | let mut rules = Vec::new(); |
181 | while src.len() > 0 { | 190 | while src.len() > 0 { |
182 | let rule = Rule::parse(&mut src)?; | 191 | let rule = Rule::parse(&mut src, true)?; |
183 | rules.push(rule); | 192 | rules.push(rule); |
184 | if let Err(()) = src.expect_char(';') { | 193 | if let Err(()) = src.expect_char(';') { |
185 | if src.len() > 0 { | 194 | if src.len() > 0 { |
@@ -200,7 +209,58 @@ impl MacroRules { | |||
200 | // apply shift | 209 | // apply shift |
201 | let mut tt = tt.clone(); | 210 | let mut tt = tt.clone(); |
202 | self.shift.shift_all(&mut tt); | 211 | self.shift.shift_all(&mut tt); |
203 | mbe_expander::expand(self, &tt) | 212 | mbe_expander::expand_rules(&self.rules, &tt) |
213 | } | ||
214 | |||
215 | pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId { | ||
216 | self.shift.shift(id) | ||
217 | } | ||
218 | |||
219 | pub fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, Origin) { | ||
220 | match self.shift.unshift(id) { | ||
221 | Some(id) => (id, Origin::Call), | ||
222 | None => (id, Origin::Def), | ||
223 | } | ||
224 | } | ||
225 | } | ||
226 | |||
227 | impl MacroDef { | ||
228 | pub fn parse(tt: &tt::Subtree) -> Result<MacroDef, ParseError> { | ||
229 | let mut src = TtIter::new(tt); | ||
230 | let mut rules = Vec::new(); | ||
231 | |||
232 | if Some(tt::DelimiterKind::Brace) == tt.delimiter_kind() { | ||
233 | mark::hit!(parse_macro_def_rules); | ||
234 | while src.len() > 0 { | ||
235 | let rule = Rule::parse(&mut src, true)?; | ||
236 | rules.push(rule); | ||
237 | if let Err(()) = src.expect_char(';') { | ||
238 | if src.len() > 0 { | ||
239 | return Err(ParseError::Expected("expected `;`".to_string())); | ||
240 | } | ||
241 | break; | ||
242 | } | ||
243 | } | ||
244 | } else { | ||
245 | mark::hit!(parse_macro_def_simple); | ||
246 | let rule = Rule::parse(&mut src, false)?; | ||
247 | if src.len() != 0 { | ||
248 | return Err(ParseError::Expected("remain tokens in macro def".to_string())); | ||
249 | } | ||
250 | rules.push(rule); | ||
251 | } | ||
252 | for rule in rules.iter() { | ||
253 | validate(&rule.lhs)?; | ||
254 | } | ||
255 | |||
256 | Ok(MacroDef { rules, shift: Shift::new(tt) }) | ||
257 | } | ||
258 | |||
259 | pub fn expand(&self, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> { | ||
260 | // apply shift | ||
261 | let mut tt = tt.clone(); | ||
262 | self.shift.shift_all(&mut tt); | ||
263 | mbe_expander::expand_rules(&self.rules, &tt) | ||
204 | } | 264 | } |
205 | 265 | ||
206 | pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId { | 266 | pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId { |
@@ -216,12 +276,14 @@ impl MacroRules { | |||
216 | } | 276 | } |
217 | 277 | ||
218 | impl Rule { | 278 | impl Rule { |
219 | fn parse(src: &mut TtIter) -> Result<Rule, ParseError> { | 279 | fn parse(src: &mut TtIter, expect_arrow: bool) -> Result<Rule, ParseError> { |
220 | let lhs = src | 280 | let lhs = src |
221 | .expect_subtree() | 281 | .expect_subtree() |
222 | .map_err(|()| ParseError::Expected("expected subtree".to_string()))?; | 282 | .map_err(|()| ParseError::Expected("expected subtree".to_string()))?; |
223 | src.expect_char('=').map_err(|()| ParseError::Expected("expected `=`".to_string()))?; | 283 | if expect_arrow { |
224 | src.expect_char('>').map_err(|()| ParseError::Expected("expected `>`".to_string()))?; | 284 | src.expect_char('=').map_err(|()| ParseError::Expected("expected `=`".to_string()))?; |
285 | src.expect_char('>').map_err(|()| ParseError::Expected("expected `>`".to_string()))?; | ||
286 | } | ||
225 | let rhs = src | 287 | let rhs = src |
226 | .expect_subtree() | 288 | .expect_subtree() |
227 | .map_err(|()| ParseError::Expected("expected subtree".to_string()))?; | 289 | .map_err(|()| ParseError::Expected("expected subtree".to_string()))?; |