aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe/src/lib.rs')
-rw-r--r--crates/ra_mbe/src/lib.rs50
1 files changed, 39 insertions, 11 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index 535b7daa0..1a020398e 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -19,6 +19,7 @@ use crate::{
19#[derive(Debug, PartialEq, Eq)] 19#[derive(Debug, PartialEq, Eq)]
20pub enum ParseError { 20pub enum ParseError {
21 Expected(String), 21 Expected(String),
22 RepetitionEmtpyTokenTree,
22} 23}
23 24
24#[derive(Debug, PartialEq, Eq)] 25#[derive(Debug, PartialEq, Eq)]
@@ -194,20 +195,46 @@ impl Rule {
194 } 195 }
195} 196}
196 197
198fn to_parse_error(e: ExpandError) -> ParseError {
199 let msg = match e {
200 ExpandError::InvalidRepeat => "invalid repeat".to_string(),
201 _ => "invalid macro definition".to_string(),
202 };
203 ParseError::Expected(msg)
204}
205
197fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> { 206fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> {
198 for op in parse_pattern(pattern) { 207 for op in parse_pattern(pattern) {
199 let op = match op { 208 let op = op.map_err(to_parse_error)?;
200 Ok(it) => it, 209
201 Err(e) => {
202 let msg = match e {
203 ExpandError::InvalidRepeat => "invalid repeat".to_string(),
204 _ => "invalid macro definition".to_string(),
205 };
206 return Err(ParseError::Expected(msg));
207 }
208 };
209 match op { 210 match op {
210 Op::TokenTree(tt::TokenTree::Subtree(subtree)) | Op::Repeat { subtree, .. } => { 211 Op::TokenTree(tt::TokenTree::Subtree(subtree)) => validate(subtree)?,
212 Op::Repeat { subtree, separator, .. } => {
213 // Checks that no repetition which could match an empty token
214 // https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558
215
216 if separator.is_none() {
217 if parse_pattern(subtree).all(|child_op| {
218 match child_op.map_err(to_parse_error) {
219 Ok(Op::Var { kind, .. }) => {
220 // vis is optional
221 if kind.map_or(false, |it| it == "vis") {
222 return true;
223 }
224 }
225 Ok(Op::Repeat { kind, .. }) => {
226 return matches!(
227 kind,
228 parser::RepeatKind::ZeroOrMore | parser::RepeatKind::ZeroOrOne
229 )
230 }
231 _ => {}
232 }
233 false
234 }) {
235 return Err(ParseError::RepetitionEmtpyTokenTree);
236 }
237 }
211 validate(subtree)? 238 validate(subtree)?
212 } 239 }
213 _ => (), 240 _ => (),
@@ -216,6 +243,7 @@ fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> {
216 Ok(()) 243 Ok(())
217} 244}
218 245
246#[derive(Debug)]
219pub struct ExpandResult<T>(pub T, pub Option<ExpandError>); 247pub struct ExpandResult<T>(pub T, pub Option<ExpandError>);
220 248
221impl<T> ExpandResult<T> { 249impl<T> ExpandResult<T> {