aboutsummaryrefslogtreecommitdiff
path: root/crates/mbe/src/lib.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-12-30 00:39:29 +0000
committerGitHub <[email protected]>2020-12-30 00:39:29 +0000
commit848e817f603ed12e065bc3057d12e04b481fb5bb (patch)
treec4dd3ba17b56e25995e2ee14eabac1a4659b41e7 /crates/mbe/src/lib.rs
parent386c447038166687b9403bec71d5924b8e2d3fbc (diff)
parent266b14d4b5b44d1491e50c7aa2ed4b85020796e1 (diff)
Merge #7083
7083: Refactor mbe parsing code r=edwin0cheng a=edwin0cheng Inspire by #5426 , this PR refactor out the parsing code such that it only parsed on `mbe::Rule`, but not on invocations. However, it just improve the overall performance unnoticeablely :( Co-authored-by: Edwin Cheng <[email protected]>
Diffstat (limited to 'crates/mbe/src/lib.rs')
-rw-r--r--crates/mbe/src/lib.rs46
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
15use std::fmt; 15use std::fmt;
16 16
17pub use tt::{Delimiter, Punct}; 17pub use tt::{Delimiter, DelimiterKind, Punct};
18 18
19use crate::{ 19use 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)]
80struct Rule { 80struct Rule {
81 lhs: tt::Subtree, 81 lhs: MetaTemplate,
82 rhs: tt::Subtree, 82 rhs: MetaTemplate,
83}
84
85#[derive(Clone, Debug, PartialEq, Eq)]
86struct MetaTemplate {
87 delimiter: Option<Delimiter>,
88 tokens: Vec<Result<Op, ExpandError>>,
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 }
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
220fn to_parse_error(e: ExpandError) -> ParseError { 240fn 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
228fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> { 248fn 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 }