diff options
Diffstat (limited to 'crates/ra_mbe/src/mbe_parser.rs')
-rw-r--r-- | crates/ra_mbe/src/mbe_parser.rs | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/crates/ra_mbe/src/mbe_parser.rs b/crates/ra_mbe/src/mbe_parser.rs index c7ab463e2..797c70bc7 100644 --- a/crates/ra_mbe/src/mbe_parser.rs +++ b/crates/ra_mbe/src/mbe_parser.rs | |||
@@ -28,17 +28,31 @@ 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); |
34 | while let Some(tt) = p.eat() { | 44 | while let Some(tt) = p.eat() { |
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: '$', .. }) => { | 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 { | 51 | } else if let Some(tt::TokenTree::Subtree(_)) = p.current() { |
41 | parse_repeat(&mut p, transcriber)?.into() | 52 | parse_repeat(&mut p, transcriber)?.into() |
53 | } else { | ||
54 | // Treat it as normal punct | ||
55 | crate::Leaf::from(tt::Punct { char: '$', spacing: *spacing }).into() | ||
42 | } | 56 | } |
43 | } | 57 | } |
44 | tt::Leaf::Punct(punct) => crate::Leaf::from(*punct).into(), | 58 | tt::Leaf::Punct(punct) => crate::Leaf::from(*punct).into(), |
@@ -57,8 +71,16 @@ fn parse_subtree(tt: &tt::Subtree, transcriber: bool) -> Result<crate::Subtree, | |||
57 | } | 71 | } |
58 | 72 | ||
59 | 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> { |
60 | let ident = p.eat_ident().unwrap(); | 74 | let text = { |
61 | 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 | |||
62 | let kind = if !transcriber && p.at_char(':') { | 84 | let kind = if !transcriber && p.at_char(':') { |
63 | p.bump(); | 85 | p.bump(); |
64 | if let Some(ident) = p.eat_ident() { | 86 | if let Some(ident) = p.eat_ident() { |
@@ -89,7 +111,7 @@ fn mk_repeat( | |||
89 | } | 111 | } |
90 | 112 | ||
91 | fn parse_repeat(p: &mut TtCursor, transcriber: bool) -> Result<crate::Repeat, ParseError> { | 113 | fn parse_repeat(p: &mut TtCursor, transcriber: bool) -> Result<crate::Repeat, ParseError> { |
92 | let subtree = p.eat_subtree().unwrap(); | 114 | let subtree = p.eat_subtree()?; |
93 | let mut subtree = parse_subtree(subtree, transcriber)?; | 115 | let mut subtree = parse_subtree(subtree, transcriber)?; |
94 | subtree.delimiter = crate::Delimiter::None; | 116 | subtree.delimiter = crate::Delimiter::None; |
95 | 117 | ||
@@ -121,6 +143,10 @@ mod tests { | |||
121 | expect_err("invalid", "subtree"); | 143 | expect_err("invalid", "subtree"); |
122 | 144 | ||
123 | is_valid("($i:ident) => ()"); | 145 | is_valid("($i:ident) => ()"); |
146 | is_valid("($($i:ident)*) => ($_)"); | ||
147 | is_valid("($($true:ident)*) => ($true)"); | ||
148 | is_valid("($($false:ident)*) => ($false)"); | ||
149 | |||
124 | expect_err("$i:ident => ()", "subtree"); | 150 | expect_err("$i:ident => ()", "subtree"); |
125 | expect_err("($i:ident) ()", "`=`"); | 151 | expect_err("($i:ident) ()", "`=`"); |
126 | expect_err("($($i:ident)_) => ()", "repeat"); | 152 | expect_err("($($i:ident)_) => ()", "repeat"); |