aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/mbe_parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe/src/mbe_parser.rs')
-rw-r--r--crates/ra_mbe/src/mbe_parser.rs38
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
31fn 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
31fn parse_subtree(tt: &tt::Subtree, transcriber: bool) -> Result<crate::Subtree, ParseError> { 41fn 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
59fn parse_var(p: &mut TtCursor, transcriber: bool) -> Result<crate::Var, ParseError> { 73fn 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
91fn parse_repeat(p: &mut TtCursor, transcriber: bool) -> Result<crate::Repeat, ParseError> { 113fn 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");