diff options
author | Edwin Cheng <[email protected]> | 2019-05-04 17:49:50 +0100 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2019-05-04 17:49:50 +0100 |
commit | 1a3800df60ca789f858dcf40edff4aee01b53188 (patch) | |
tree | 71841463e340082843d15adefbcd52c29dea73dc | |
parent | e1ea2500fcc5e136fbe6a14c488f558e28519c45 (diff) |
Fix `$true` and `$false` as $var name error
-rw-r--r-- | crates/ra_mbe/src/mbe_parser.rs | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/crates/ra_mbe/src/mbe_parser.rs b/crates/ra_mbe/src/mbe_parser.rs index 8e1e31e7d..797c70bc7 100644 --- a/crates/ra_mbe/src/mbe_parser.rs +++ b/crates/ra_mbe/src/mbe_parser.rs | |||
@@ -28,6 +28,16 @@ fn parse_rule(p: &mut TtCursor) -> Result<crate::Rule, ParseError> { | |||
28 | Ok(crate::Rule { lhs, rhs }) | 28 | Ok(crate::Rule { lhs, rhs }) |
29 | } | 29 | } |
30 | 30 | ||
31 | fn is_boolean_literal(lit: Option<&tt::TokenTree>) -> bool { | ||
32 | if let Some(tt::TokenTree::Leaf(tt::Leaf::Literal(lit))) = lit { | ||
33 | if lit.text == "true" || lit.text == "false" { | ||
34 | return true; | ||
35 | } | ||
36 | } | ||
37 | |||
38 | false | ||
39 | } | ||
40 | |||
31 | fn parse_subtree(tt: &tt::Subtree, transcriber: bool) -> Result<crate::Subtree, ParseError> { | 41 | fn parse_subtree(tt: &tt::Subtree, transcriber: bool) -> Result<crate::Subtree, ParseError> { |
32 | let mut token_trees = Vec::new(); | 42 | let mut token_trees = Vec::new(); |
33 | let mut p = TtCursor::new(tt); | 43 | let mut p = TtCursor::new(tt); |
@@ -35,7 +45,8 @@ fn parse_subtree(tt: &tt::Subtree, transcriber: bool) -> Result<crate::Subtree, | |||
35 | let child: crate::TokenTree = match tt { | 45 | let child: crate::TokenTree = match tt { |
36 | tt::TokenTree::Leaf(leaf) => match leaf { | 46 | tt::TokenTree::Leaf(leaf) => match leaf { |
37 | tt::Leaf::Punct(tt::Punct { char: '$', spacing }) => { | 47 | tt::Leaf::Punct(tt::Punct { char: '$', spacing }) => { |
38 | if p.at_ident().is_some() { | 48 | // mbe var can be an ident or keyword, including `true` and `false` |
49 | if p.at_ident().is_some() || is_boolean_literal(p.current()) { | ||
39 | crate::Leaf::from(parse_var(&mut p, transcriber)?).into() | 50 | crate::Leaf::from(parse_var(&mut p, transcriber)?).into() |
40 | } else if let Some(tt::TokenTree::Subtree(_)) = p.current() { | 51 | } else if let Some(tt::TokenTree::Subtree(_)) = p.current() { |
41 | parse_repeat(&mut p, transcriber)?.into() | 52 | parse_repeat(&mut p, transcriber)?.into() |
@@ -60,8 +71,16 @@ fn parse_subtree(tt: &tt::Subtree, transcriber: bool) -> Result<crate::Subtree, | |||
60 | } | 71 | } |
61 | 72 | ||
62 | fn parse_var(p: &mut TtCursor, transcriber: bool) -> Result<crate::Var, ParseError> { | 73 | fn parse_var(p: &mut TtCursor, transcriber: bool) -> Result<crate::Var, ParseError> { |
63 | let ident = p.eat_ident().unwrap(); | 74 | let text = { |
64 | let text = ident.text.clone(); | 75 | if is_boolean_literal(p.current()) { |
76 | let lit = p.eat_literal().unwrap(); | ||
77 | lit.text.clone() | ||
78 | } else { | ||
79 | let ident = p.eat_ident().unwrap(); | ||
80 | ident.text.clone() | ||
81 | } | ||
82 | }; | ||
83 | |||
65 | let kind = if !transcriber && p.at_char(':') { | 84 | let kind = if !transcriber && p.at_char(':') { |
66 | p.bump(); | 85 | p.bump(); |
67 | if let Some(ident) = p.eat_ident() { | 86 | if let Some(ident) = p.eat_ident() { |
@@ -125,6 +144,8 @@ mod tests { | |||
125 | 144 | ||
126 | is_valid("($i:ident) => ()"); | 145 | is_valid("($i:ident) => ()"); |
127 | is_valid("($($i:ident)*) => ($_)"); | 146 | is_valid("($($i:ident)*) => ($_)"); |
147 | is_valid("($($true:ident)*) => ($true)"); | ||
148 | is_valid("($($false:ident)*) => ($false)"); | ||
128 | 149 | ||
129 | expect_err("$i:ident => ()", "subtree"); | 150 | expect_err("$i:ident => ()", "subtree"); |
130 | expect_err("($i:ident) ()", "`=`"); | 151 | expect_err("($i:ident) ()", "`=`"); |