aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilco Kusee <[email protected]>2019-03-03 09:40:03 +0000
committerWilco Kusee <[email protected]>2019-03-03 09:40:03 +0000
commit725805dc795159399c90a5c9b6f11ffeadec2e0f (patch)
treeddc799a626c1b46d67bb274c87b4cfdaa22cd1ec
parentdffe318701dcbd7da2b241cd8f623be9d4744ee3 (diff)
Split parse and expand errors
-rw-r--r--crates/ra_mbe/src/lib.rs13
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs65
-rw-r--r--crates/ra_mbe/src/mbe_parser.rs24
-rw-r--r--crates/ra_mbe/src/tt_cursor.rs44
4 files changed, 74 insertions, 72 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index 8a2d6ff63..34840dfa1 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -25,14 +25,17 @@ use ra_syntax::SmolStr;
25pub use tt::{Delimiter, Punct}; 25pub use tt::{Delimiter, Punct};
26 26
27#[derive(Debug, PartialEq, Eq)] 27#[derive(Debug, PartialEq, Eq)]
28pub enum MacroRulesError { 28pub enum ParseError {
29 ParseError,
30}
31
32#[derive(Debug, PartialEq, Eq)]
33pub enum ExpandError {
29 NoMatchingRule, 34 NoMatchingRule,
30 UnexpectedToken, 35 UnexpectedToken,
31 BindingError(String), 36 BindingError(String),
32 ParseError,
33} 37}
34 38
35pub type Result<T> = ::std::result::Result<T, MacroRulesError>;
36pub use crate::syntax_bridge::{ast_to_token_tree, token_tree_to_ast_item_list}; 39pub use crate::syntax_bridge::{ast_to_token_tree, token_tree_to_ast_item_list};
37 40
38/// This struct contains AST for a single `macro_rules` definition. What might 41/// This struct contains AST for a single `macro_rules` definition. What might
@@ -45,10 +48,10 @@ pub struct MacroRules {
45} 48}
46 49
47impl MacroRules { 50impl MacroRules {
48 pub fn parse(tt: &tt::Subtree) -> Result<MacroRules> { 51 pub fn parse(tt: &tt::Subtree) -> Result<MacroRules, ParseError> {
49 mbe_parser::parse(tt) 52 mbe_parser::parse(tt)
50 } 53 }
51 pub fn expand(&self, tt: &tt::Subtree) -> Result<tt::Subtree> { 54 pub fn expand(&self, tt: &tt::Subtree) -> Result<tt::Subtree, ExpandError> {
52 mbe_expander::expand(self, tt) 55 mbe_expander::expand(self, tt)
53 } 56 }
54} 57}
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs
index 0a5bbf6b1..d4ce3bfe3 100644
--- a/crates/ra_mbe/src/mbe_expander.rs
+++ b/crates/ra_mbe/src/mbe_expander.rs
@@ -5,22 +5,21 @@ use rustc_hash::FxHashMap;
5use ra_syntax::SmolStr; 5use ra_syntax::SmolStr;
6use tt::TokenId; 6use tt::TokenId;
7 7
8use crate::{MacroRulesError, Result}; 8use crate::ExpandError;
9use crate::tt_cursor::TtCursor; 9use crate::tt_cursor::TtCursor;
10 10
11pub(crate) fn expand(rules: &crate::MacroRules, input: &tt::Subtree) -> Result<tt::Subtree> { 11pub(crate) fn expand(
12 rules 12 rules: &crate::MacroRules,
13 .rules 13 input: &tt::Subtree,
14 .iter() 14) -> Result<tt::Subtree, ExpandError> {
15 .find_map(|it| expand_rule(it, input).ok()) 15 rules.rules.iter().find_map(|it| expand_rule(it, input).ok()).ok_or(ExpandError::NoMatchingRule)
16 .ok_or(MacroRulesError::NoMatchingRule)
17} 16}
18 17
19fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> Result<tt::Subtree> { 18fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> Result<tt::Subtree, ExpandError> {
20 let mut input = TtCursor::new(input); 19 let mut input = TtCursor::new(input);
21 let bindings = match_lhs(&rule.lhs, &mut input)?; 20 let bindings = match_lhs(&rule.lhs, &mut input)?;
22 if !input.is_eof() { 21 if !input.is_eof() {
23 return Err(MacroRulesError::UnexpectedToken); 22 return Err(ExpandError::UnexpectedToken);
24 } 23 }
25 expand_subtree(&rule.rhs, &bindings, &mut Vec::new()) 24 expand_subtree(&rule.rhs, &bindings, &mut Vec::new())
26} 25}
@@ -82,29 +81,30 @@ enum Binding {
82} 81}
83 82
84impl Bindings { 83impl Bindings {
85 fn get(&self, name: &SmolStr, nesting: &[usize]) -> Result<&tt::TokenTree> { 84 fn get(&self, name: &SmolStr, nesting: &[usize]) -> Result<&tt::TokenTree, ExpandError> {
86 let mut b = self 85 let mut b = self
87 .inner 86 .inner
88 .get(name) 87 .get(name)
89 .ok_or(MacroRulesError::BindingError(format!("could not find binding {}", name)))?; 88 .ok_or(ExpandError::BindingError(format!("could not find binding {}", name)))?;
90 for &idx in nesting.iter() { 89 for &idx in nesting.iter() {
91 b = match b { 90 b = match b {
92 Binding::Simple(_) => break, 91 Binding::Simple(_) => break,
93 Binding::Nested(bs) => bs.get(idx).ok_or(MacroRulesError::BindingError( 92 Binding::Nested(bs) => bs.get(idx).ok_or(ExpandError::BindingError(format!(
94 format!("could not find nested binding {}", name), 93 "could not find nested binding {}",
95 ))?, 94 name
95 )))?,
96 }; 96 };
97 } 97 }
98 match b { 98 match b {
99 Binding::Simple(it) => Ok(it), 99 Binding::Simple(it) => Ok(it),
100 Binding::Nested(_) => Err(MacroRulesError::BindingError(format!( 100 Binding::Nested(_) => Err(ExpandError::BindingError(format!(
101 "expected simple binding, found nested binding {}", 101 "expected simple binding, found nested binding {}",
102 name 102 name
103 ))), 103 ))),
104 } 104 }
105 } 105 }
106 106
107 fn push_nested(&mut self, nested: Bindings) -> Result<()> { 107 fn push_nested(&mut self, nested: Bindings) -> Result<(), ExpandError> {
108 for (key, value) in nested.inner { 108 for (key, value) in nested.inner {
109 if !self.inner.contains_key(&key) { 109 if !self.inner.contains_key(&key) {
110 self.inner.insert(key.clone(), Binding::Nested(Vec::new())); 110 self.inner.insert(key.clone(), Binding::Nested(Vec::new()));
@@ -112,10 +112,10 @@ impl Bindings {
112 match self.inner.get_mut(&key) { 112 match self.inner.get_mut(&key) {
113 Some(Binding::Nested(it)) => it.push(value), 113 Some(Binding::Nested(it)) => it.push(value),
114 _ => { 114 _ => {
115 return Err(MacroRulesError::BindingError(format!( 115 return Err(ExpandError::BindingError(format!(
116 "nested binding for {} not found", 116 "nested binding for {} not found",
117 key 117 key
118 ))) 118 )));
119 } 119 }
120 } 120 }
121 } 121 }
@@ -123,43 +123,44 @@ impl Bindings {
123 } 123 }
124} 124}
125 125
126fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings> { 126fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings, ExpandError> {
127 let mut res = Bindings::default(); 127 let mut res = Bindings::default();
128 for pat in pattern.token_trees.iter() { 128 for pat in pattern.token_trees.iter() {
129 match pat { 129 match pat {
130 crate::TokenTree::Leaf(leaf) => match leaf { 130 crate::TokenTree::Leaf(leaf) => match leaf {
131 crate::Leaf::Var(crate::Var { text, kind }) => { 131 crate::Leaf::Var(crate::Var { text, kind }) => {
132 let kind = kind.clone().ok_or(MacroRulesError::ParseError)?; 132 let kind = kind.clone().ok_or(ExpandError::UnexpectedToken)?;
133 match kind.as_str() { 133 match kind.as_str() {
134 "ident" => { 134 "ident" => {
135 let ident = input.eat_ident()?.clone(); 135 let ident =
136 input.eat_ident().ok_or(ExpandError::UnexpectedToken)?.clone();
136 res.inner.insert( 137 res.inner.insert(
137 text.clone(), 138 text.clone(),
138 Binding::Simple(tt::Leaf::from(ident).into()), 139 Binding::Simple(tt::Leaf::from(ident).into()),
139 ); 140 );
140 } 141 }
141 _ => return Err(MacroRulesError::UnexpectedToken), 142 _ => return Err(ExpandError::UnexpectedToken),
142 } 143 }
143 } 144 }
144 crate::Leaf::Punct(punct) => { 145 crate::Leaf::Punct(punct) => {
145 if input.eat_punct()? != punct { 146 if input.eat_punct() != Some(punct) {
146 return Err(MacroRulesError::UnexpectedToken); 147 return Err(ExpandError::UnexpectedToken);
147 } 148 }
148 } 149 }
149 crate::Leaf::Ident(ident) => { 150 crate::Leaf::Ident(ident) => {
150 if input.eat_ident()?.text != ident.text { 151 if input.eat_ident().map(|i| &i.text) != Some(&ident.text) {
151 return Err(MacroRulesError::UnexpectedToken); 152 return Err(ExpandError::UnexpectedToken);
152 } 153 }
153 } 154 }
154 _ => return Err(MacroRulesError::UnexpectedToken), 155 _ => return Err(ExpandError::UnexpectedToken),
155 }, 156 },
156 crate::TokenTree::Repeat(crate::Repeat { subtree, kind: _, separator }) => { 157 crate::TokenTree::Repeat(crate::Repeat { subtree, kind: _, separator }) => {
157 while let Ok(nested) = match_lhs(subtree, input) { 158 while let Ok(nested) = match_lhs(subtree, input) {
158 res.push_nested(nested)?; 159 res.push_nested(nested)?;
159 if let Some(separator) = *separator { 160 if let Some(separator) = *separator {
160 if !input.is_eof() { 161 if !input.is_eof() {
161 if input.eat_punct()?.char != separator { 162 if input.eat_punct().map(|p| p.char) != Some(separator) {
162 return Err(MacroRulesError::UnexpectedToken); 163 return Err(ExpandError::UnexpectedToken);
163 } 164 }
164 } 165 }
165 } 166 }
@@ -175,12 +176,12 @@ fn expand_subtree(
175 template: &crate::Subtree, 176 template: &crate::Subtree,
176 bindings: &Bindings, 177 bindings: &Bindings,
177 nesting: &mut Vec<usize>, 178 nesting: &mut Vec<usize>,
178) -> Result<tt::Subtree> { 179) -> Result<tt::Subtree, ExpandError> {
179 let token_trees = template 180 let token_trees = template
180 .token_trees 181 .token_trees
181 .iter() 182 .iter()
182 .map(|it| expand_tt(it, bindings, nesting)) 183 .map(|it| expand_tt(it, bindings, nesting))
183 .collect::<Result<Vec<_>>>()?; 184 .collect::<Result<Vec<_>, ExpandError>>()?;
184 185
185 Ok(tt::Subtree { token_trees, delimiter: template.delimiter }) 186 Ok(tt::Subtree { token_trees, delimiter: template.delimiter })
186} 187}
@@ -189,7 +190,7 @@ fn expand_tt(
189 template: &crate::TokenTree, 190 template: &crate::TokenTree,
190 bindings: &Bindings, 191 bindings: &Bindings,
191 nesting: &mut Vec<usize>, 192 nesting: &mut Vec<usize>,
192) -> Result<tt::TokenTree> { 193) -> Result<tt::TokenTree, ExpandError> {
193 let res: tt::TokenTree = match template { 194 let res: tt::TokenTree = match template {
194 crate::TokenTree::Subtree(subtree) => expand_subtree(subtree, bindings, nesting)?.into(), 195 crate::TokenTree::Subtree(subtree) => expand_subtree(subtree, bindings, nesting)?.into(),
195 crate::TokenTree::Repeat(repeat) => { 196 crate::TokenTree::Repeat(repeat) => {
diff --git a/crates/ra_mbe/src/mbe_parser.rs b/crates/ra_mbe/src/mbe_parser.rs
index ee1b11091..d067e5248 100644
--- a/crates/ra_mbe/src/mbe_parser.rs
+++ b/crates/ra_mbe/src/mbe_parser.rs
@@ -1,10 +1,10 @@
1/// This module parses a raw `tt::TokenStream` into macro-by-example token 1/// This module parses a raw `tt::TokenStream` into macro-by-example token
2/// stream. This is a *mostly* identify function, expect for handling of 2/// stream. This is a *mostly* identify function, expect for handling of
3/// `$var:tt_kind` and `$(repeat),*` constructs. 3/// `$var:tt_kind` and `$(repeat),*` constructs.
4use crate::{MacroRulesError, Result}; 4use crate::ParseError;
5use crate::tt_cursor::TtCursor; 5use crate::tt_cursor::TtCursor;
6 6
7pub(crate) fn parse(tt: &tt::Subtree) -> Result<crate::MacroRules> { 7pub(crate) fn parse(tt: &tt::Subtree) -> Result<crate::MacroRules, ParseError> {
8 let mut parser = TtCursor::new(tt); 8 let mut parser = TtCursor::new(tt);
9 let mut rules = Vec::new(); 9 let mut rules = Vec::new();
10 while !parser.is_eof() { 10 while !parser.is_eof() {
@@ -19,7 +19,7 @@ pub(crate) fn parse(tt: &tt::Subtree) -> Result<crate::MacroRules> {
19 Ok(crate::MacroRules { rules }) 19 Ok(crate::MacroRules { rules })
20} 20}
21 21
22fn parse_rule(p: &mut TtCursor) -> Result<crate::Rule> { 22fn parse_rule(p: &mut TtCursor) -> Result<crate::Rule, ParseError> {
23 let lhs = parse_subtree(p.eat_subtree()?)?; 23 let lhs = parse_subtree(p.eat_subtree()?)?;
24 p.expect_char('=')?; 24 p.expect_char('=')?;
25 p.expect_char('>')?; 25 p.expect_char('>')?;
@@ -28,14 +28,14 @@ fn parse_rule(p: &mut TtCursor) -> Result<crate::Rule> {
28 Ok(crate::Rule { lhs, rhs }) 28 Ok(crate::Rule { lhs, rhs })
29} 29}
30 30
31fn parse_subtree(tt: &tt::Subtree) -> Result<crate::Subtree> { 31fn parse_subtree(tt: &tt::Subtree) -> Result<crate::Subtree, ParseError> {
32 let mut token_trees = Vec::new(); 32 let mut token_trees = Vec::new();
33 let mut p = TtCursor::new(tt); 33 let mut p = TtCursor::new(tt);
34 while let Ok(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: '$', .. }) => {
38 if p.at_ident().is_ok() { 38 if p.at_ident().is_some() {
39 crate::Leaf::from(parse_var(&mut p)?).into() 39 crate::Leaf::from(parse_var(&mut p)?).into()
40 } else { 40 } else {
41 parse_repeat(&mut p)?.into() 41 parse_repeat(&mut p)?.into()
@@ -56,12 +56,12 @@ fn parse_subtree(tt: &tt::Subtree) -> Result<crate::Subtree> {
56 Ok(crate::Subtree { token_trees, delimiter: tt.delimiter }) 56 Ok(crate::Subtree { token_trees, delimiter: tt.delimiter })
57} 57}
58 58
59fn parse_var(p: &mut TtCursor) -> Result<crate::Var> { 59fn parse_var(p: &mut TtCursor) -> Result<crate::Var, ParseError> {
60 let ident = p.eat_ident().unwrap(); 60 let ident = p.eat_ident().unwrap();
61 let text = ident.text.clone(); 61 let text = ident.text.clone();
62 let kind = if p.at_char(':') { 62 let kind = if p.at_char(':') {
63 p.bump(); 63 p.bump();
64 if let Ok(ident) = p.eat_ident() { 64 if let Some(ident) = p.eat_ident() {
65 Some(ident.text.clone()) 65 Some(ident.text.clone())
66 } else { 66 } else {
67 p.rev_bump(); 67 p.rev_bump();
@@ -73,21 +73,21 @@ fn parse_var(p: &mut TtCursor) -> Result<crate::Var> {
73 Ok(crate::Var { text, kind }) 73 Ok(crate::Var { text, kind })
74} 74}
75 75
76fn parse_repeat(p: &mut TtCursor) -> Result<crate::Repeat> { 76fn 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()?; 80 let sep = p.eat_punct().ok_or(ParseError::ParseError)?;
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()?.char), 83 char => (Some(char), p.eat_punct().ok_or(ParseError::ParseError)?.char),
84 }; 84 };
85 85
86 let kind = match rep { 86 let kind = match rep {
87 '*' => crate::RepeatKind::ZeroOrMore, 87 '*' => crate::RepeatKind::ZeroOrMore,
88 '+' => crate::RepeatKind::OneOrMore, 88 '+' => crate::RepeatKind::OneOrMore,
89 '?' => crate::RepeatKind::ZeroOrOne, 89 '?' => crate::RepeatKind::ZeroOrOne,
90 _ => return Err(MacroRulesError::ParseError), 90 _ => return Err(ParseError::ParseError),
91 }; 91 };
92 p.bump(); 92 p.bump();
93 Ok(crate::Repeat { subtree, kind, separator }) 93 Ok(crate::Repeat { subtree, kind, separator })
diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs
index 117471841..d06bfbf9f 100644
--- a/crates/ra_mbe/src/tt_cursor.rs
+++ b/crates/ra_mbe/src/tt_cursor.rs
@@ -1,4 +1,4 @@
1use crate::{MacroRulesError, Result}; 1use crate::ParseError;
2 2
3#[derive(Clone)] 3#[derive(Clone)]
4pub(crate) struct TtCursor<'a> { 4pub(crate) struct TtCursor<'a> {
@@ -19,24 +19,24 @@ impl<'a> TtCursor<'a> {
19 self.subtree.token_trees.get(self.pos) 19 self.subtree.token_trees.get(self.pos)
20 } 20 }
21 21
22 pub(crate) fn at_punct(&self) -> Result<&'a tt::Punct> { 22 pub(crate) fn at_punct(&self) -> Option<&'a tt::Punct> {
23 match self.current() { 23 match self.current() {
24 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(it))) => Ok(it), 24 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(it))) => Some(it),
25 _ => Err(MacroRulesError::ParseError), 25 _ => None,
26 } 26 }
27 } 27 }
28 28
29 pub(crate) fn at_char(&self, char: char) -> bool { 29 pub(crate) fn at_char(&self, char: char) -> bool {
30 match self.at_punct() { 30 match self.at_punct() {
31 Ok(tt::Punct { char: c, .. }) if *c == char => true, 31 Some(tt::Punct { char: c, .. }) if *c == char => true,
32 _ => false, 32 _ => false,
33 } 33 }
34 } 34 }
35 35
36 pub(crate) fn at_ident(&mut self) -> Result<&'a tt::Ident> { 36 pub(crate) fn at_ident(&mut self) -> Option<&'a tt::Ident> {
37 match self.current() { 37 match self.current() {
38 Some(tt::TokenTree::Leaf(tt::Leaf::Ident(i))) => Ok(i), 38 Some(tt::TokenTree::Leaf(tt::Leaf::Ident(i))) => Some(i),
39 _ => Err(MacroRulesError::ParseError), 39 _ => None,
40 } 40 }
41 } 41 }
42 42
@@ -47,45 +47,43 @@ impl<'a> TtCursor<'a> {
47 self.pos -= 1; 47 self.pos -= 1;
48 } 48 }
49 49
50 pub(crate) fn eat(&mut self) -> Result<&'a tt::TokenTree> { 50 pub(crate) fn eat(&mut self) -> Option<&'a tt::TokenTree> {
51 match self.current() { 51 self.current().map(|it| {
52 Some(it) => { 52 self.bump();
53 self.bump(); 53 it
54 Ok(it) 54 })
55 }
56 None => Err(MacroRulesError::ParseError),
57 }
58 } 55 }
59 56
60 pub(crate) fn eat_subtree(&mut self) -> Result<&'a tt::Subtree> { 57 pub(crate) fn eat_subtree(&mut self) -> Result<&'a tt::Subtree, ParseError> {
61 match self.current() { 58 match self.current() {
62 Some(tt::TokenTree::Subtree(sub)) => { 59 Some(tt::TokenTree::Subtree(sub)) => {
63 self.bump(); 60 self.bump();
64 Ok(sub) 61 Ok(sub)
65 } 62 }
66 _ => Err(MacroRulesError::ParseError), 63 _ => Err(ParseError::ParseError),
67 } 64 }
68 } 65 }
69 66
70 pub(crate) fn eat_punct(&mut self) -> Result<&'a tt::Punct> { 67 pub(crate) fn eat_punct(&mut self) -> Option<&'a tt::Punct> {
71 self.at_punct().map(|it| { 68 self.at_punct().map(|it| {
72 self.bump(); 69 self.bump();
73 it 70 it
74 }) 71 })
75 } 72 }
76 73
77 pub(crate) fn eat_ident(&mut self) -> Result<&'a tt::Ident> { 74 pub(crate) fn eat_ident(&mut self) -> Option<&'a tt::Ident> {
78 self.at_ident().map(|i| { 75 self.at_ident().map(|i| {
79 self.bump(); 76 self.bump();
80 i 77 i
81 }) 78 })
82 } 79 }
83 80
84 pub(crate) fn expect_char(&mut self, char: char) -> Result<()> { 81 pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> {
85 if self.at_char(char) { 82 if self.at_char(char) {
86 self.bump(); 83 self.bump();
87 return Ok(()); 84 Ok(())
85 } else {
86 Err(ParseError::ParseError)
88 } 87 }
89 Err(MacroRulesError::ParseError)
90 } 88 }
91} 89}