diff options
-rw-r--r-- | crates/ra_mbe/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_mbe/src/mbe_parser.rs | 58 | ||||
-rw-r--r-- | crates/ra_mbe/src/tt_cursor.rs | 4 |
3 files changed, 58 insertions, 6 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index 34840dfa1..2c75b7b4f 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs | |||
@@ -26,7 +26,7 @@ pub use tt::{Delimiter, Punct}; | |||
26 | 26 | ||
27 | #[derive(Debug, PartialEq, Eq)] | 27 | #[derive(Debug, PartialEq, Eq)] |
28 | pub enum ParseError { | 28 | pub enum ParseError { |
29 | ParseError, | 29 | Expected(String), |
30 | } | 30 | } |
31 | 31 | ||
32 | #[derive(Debug, PartialEq, Eq)] | 32 | #[derive(Debug, PartialEq, Eq)] |
diff --git a/crates/ra_mbe/src/mbe_parser.rs b/crates/ra_mbe/src/mbe_parser.rs index d067e5248..e3669f66c 100644 --- a/crates/ra_mbe/src/mbe_parser.rs +++ b/crates/ra_mbe/src/mbe_parser.rs | |||
@@ -77,18 +77,70 @@ fn parse_repeat(p: &mut TtCursor) -> Result<crate::Repeat, ParseError> { | |||
77 | let subtree = p.eat_subtree().unwrap(); | 77 | let subtree = p.eat_subtree().unwrap(); |
78 | let mut subtree = parse_subtree(subtree)?; | 78 | let mut subtree = parse_subtree(subtree)?; |
79 | subtree.delimiter = crate::Delimiter::None; | 79 | subtree.delimiter = crate::Delimiter::None; |
80 | let sep = p.eat_punct().ok_or(ParseError::ParseError)?; | 80 | let sep = p.eat_punct().ok_or(ParseError::Expected(String::from("separator")))?; |
81 | let (separator, rep) = match sep.char { | 81 | let (separator, rep) = match sep.char { |
82 | '*' | '+' | '?' => (None, sep.char), | 82 | '*' | '+' | '?' => (None, sep.char), |
83 | char => (Some(char), p.eat_punct().ok_or(ParseError::ParseError)?.char), | 83 | char => { |
84 | (Some(char), p.eat_punct().ok_or(ParseError::Expected(String::from("separator")))?.char) | ||
85 | } | ||
84 | }; | 86 | }; |
85 | 87 | ||
86 | let kind = match rep { | 88 | let kind = match rep { |
87 | '*' => crate::RepeatKind::ZeroOrMore, | 89 | '*' => crate::RepeatKind::ZeroOrMore, |
88 | '+' => crate::RepeatKind::OneOrMore, | 90 | '+' => crate::RepeatKind::OneOrMore, |
89 | '?' => crate::RepeatKind::ZeroOrOne, | 91 | '?' => crate::RepeatKind::ZeroOrOne, |
90 | _ => return Err(ParseError::ParseError), | 92 | _ => return Err(ParseError::Expected(String::from("repeat"))), |
91 | }; | 93 | }; |
92 | p.bump(); | 94 | p.bump(); |
93 | Ok(crate::Repeat { subtree, kind, separator }) | 95 | Ok(crate::Repeat { subtree, kind, separator }) |
94 | } | 96 | } |
97 | |||
98 | #[cfg(test)] | ||
99 | mod tests { | ||
100 | use ra_syntax::{ast, AstNode}; | ||
101 | |||
102 | use super::*; | ||
103 | use crate::ast_to_token_tree; | ||
104 | |||
105 | #[test] | ||
106 | fn test_invalid_parse() { | ||
107 | expect_err("invalid", "subtree"); | ||
108 | |||
109 | is_valid("($i:ident) => ()"); | ||
110 | expect_err("$i:ident => ()", "subtree"); | ||
111 | expect_err("($i:ident) ()", "`=`"); | ||
112 | expect_err("($($i:ident)_) => ()", "separator"); | ||
113 | } | ||
114 | |||
115 | fn expect_err(macro_body: &str, expected: &str) { | ||
116 | assert_eq!( | ||
117 | create_rules(&format_macro(macro_body)), | ||
118 | Err(ParseError::Expected(String::from(expected))) | ||
119 | ); | ||
120 | } | ||
121 | |||
122 | fn is_valid(macro_body: &str) { | ||
123 | assert!(create_rules(&format_macro(macro_body)).is_ok()); | ||
124 | } | ||
125 | |||
126 | fn format_macro(macro_body: &str) -> String { | ||
127 | format!( | ||
128 | " | ||
129 | macro_rules! foo {{ | ||
130 | {} | ||
131 | }} | ||
132 | ", | ||
133 | macro_body | ||
134 | ) | ||
135 | } | ||
136 | |||
137 | fn create_rules(macro_definition: &str) -> Result<crate::MacroRules, ParseError> { | ||
138 | let source_file = ast::SourceFile::parse(macro_definition); | ||
139 | let macro_definition = | ||
140 | source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); | ||
141 | |||
142 | let (definition_tt, _) = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap(); | ||
143 | parse(&definition_tt) | ||
144 | } | ||
145 | |||
146 | } | ||
diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs index d06bfbf9f..3128cb9ae 100644 --- a/crates/ra_mbe/src/tt_cursor.rs +++ b/crates/ra_mbe/src/tt_cursor.rs | |||
@@ -60,7 +60,7 @@ impl<'a> TtCursor<'a> { | |||
60 | self.bump(); | 60 | self.bump(); |
61 | Ok(sub) | 61 | Ok(sub) |
62 | } | 62 | } |
63 | _ => Err(ParseError::ParseError), | 63 | _ => Err(ParseError::Expected(String::from("subtree"))), |
64 | } | 64 | } |
65 | } | 65 | } |
66 | 66 | ||
@@ -83,7 +83,7 @@ impl<'a> TtCursor<'a> { | |||
83 | self.bump(); | 83 | self.bump(); |
84 | Ok(()) | 84 | Ok(()) |
85 | } else { | 85 | } else { |
86 | Err(ParseError::ParseError) | 86 | Err(ParseError::Expected(format!("`{}`", char))) |
87 | } | 87 | } |
88 | } | 88 | } |
89 | } | 89 | } |