diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-04 15:35:52 +0100 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-04 15:35:52 +0100 |
commit | fcdb387f0d7e76f325a858e4463efd5d7ed3efc3 (patch) | |
tree | e30057667232f29d867dcf1432831e686a686b08 | |
parent | b1febf2e6d4606a7e0eb422cdeba5dd286b10794 (diff) | |
parent | 50f288db925c5473f45d43d355e6819032298d37 (diff) |
Merge #1237
1237: Improve $ Handling in mbe parser r=matklad a=edwin0cheng
This PR improve the $ handling in mbe parser. In some rare case, the `$` may not be following an `ident` or a `Subtree`. ( For example, a macro_rules inside a macro rules).
Related issue: #1236
Co-authored-by: Edwin Cheng <[email protected]>
-rw-r--r-- | crates/ra_mbe/src/mbe_parser.rs | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/crates/ra_mbe/src/mbe_parser.rs b/crates/ra_mbe/src/mbe_parser.rs index c7ab463e2..8e1e31e7d 100644 --- a/crates/ra_mbe/src/mbe_parser.rs +++ b/crates/ra_mbe/src/mbe_parser.rs | |||
@@ -34,11 +34,14 @@ fn parse_subtree(tt: &tt::Subtree, transcriber: bool) -> Result<crate::Subtree, | |||
34 | while let Some(tt) = p.eat() { | 34 | while let Some(tt) = p.eat() { |
35 | let child: crate::TokenTree = match tt { | 35 | let child: crate::TokenTree = match tt { |
36 | tt::TokenTree::Leaf(leaf) => match leaf { | 36 | tt::TokenTree::Leaf(leaf) => match leaf { |
37 | tt::Leaf::Punct(tt::Punct { char: '$', .. }) => { | 37 | tt::Leaf::Punct(tt::Punct { char: '$', spacing }) => { |
38 | if p.at_ident().is_some() { | 38 | if p.at_ident().is_some() { |
39 | crate::Leaf::from(parse_var(&mut p, transcriber)?).into() | 39 | crate::Leaf::from(parse_var(&mut p, transcriber)?).into() |
40 | } else { | 40 | } else if let Some(tt::TokenTree::Subtree(_)) = p.current() { |
41 | parse_repeat(&mut p, transcriber)?.into() | 41 | parse_repeat(&mut p, transcriber)?.into() |
42 | } else { | ||
43 | // Treat it as normal punct | ||
44 | crate::Leaf::from(tt::Punct { char: '$', spacing: *spacing }).into() | ||
42 | } | 45 | } |
43 | } | 46 | } |
44 | tt::Leaf::Punct(punct) => crate::Leaf::from(*punct).into(), | 47 | tt::Leaf::Punct(punct) => crate::Leaf::from(*punct).into(), |
@@ -89,7 +92,7 @@ fn mk_repeat( | |||
89 | } | 92 | } |
90 | 93 | ||
91 | fn parse_repeat(p: &mut TtCursor, transcriber: bool) -> Result<crate::Repeat, ParseError> { | 94 | fn parse_repeat(p: &mut TtCursor, transcriber: bool) -> Result<crate::Repeat, ParseError> { |
92 | let subtree = p.eat_subtree().unwrap(); | 95 | let subtree = p.eat_subtree()?; |
93 | let mut subtree = parse_subtree(subtree, transcriber)?; | 96 | let mut subtree = parse_subtree(subtree, transcriber)?; |
94 | subtree.delimiter = crate::Delimiter::None; | 97 | subtree.delimiter = crate::Delimiter::None; |
95 | 98 | ||
@@ -121,6 +124,8 @@ mod tests { | |||
121 | expect_err("invalid", "subtree"); | 124 | expect_err("invalid", "subtree"); |
122 | 125 | ||
123 | is_valid("($i:ident) => ()"); | 126 | is_valid("($i:ident) => ()"); |
127 | is_valid("($($i:ident)*) => ($_)"); | ||
128 | |||
124 | expect_err("$i:ident => ()", "subtree"); | 129 | expect_err("$i:ident => ()", "subtree"); |
125 | expect_err("($i:ident) ()", "`=`"); | 130 | expect_err("($i:ident) ()", "`=`"); |
126 | expect_err("($($i:ident)_) => ()", "repeat"); | 131 | expect_err("($($i:ident)_) => ()", "repeat"); |