aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/macros/mbe.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/macros/mbe.rs')
-rw-r--r--crates/ra_hir/src/macros/mbe.rs148
1 files changed, 128 insertions, 20 deletions
diff --git a/crates/ra_hir/src/macros/mbe.rs b/crates/ra_hir/src/macros/mbe.rs
index 62b7fa24c..6c93ae5e3 100644
--- a/crates/ra_hir/src/macros/mbe.rs
+++ b/crates/ra_hir/src/macros/mbe.rs
@@ -1,6 +1,6 @@
1use ra_syntax::SmolStr; 1use ra_syntax::SmolStr;
2 2
3use crate::macros::tt; 3use crate::macros::tt::{self, Delimiter};
4 4
5#[derive(Debug)] 5#[derive(Debug)]
6pub(crate) struct MacroRules { 6pub(crate) struct MacroRules {
@@ -19,6 +19,7 @@ enum TokenTree {
19 Subtree(Subtree), 19 Subtree(Subtree),
20 Repeat(Repeat), 20 Repeat(Repeat),
21} 21}
22impl_froms!(TokenTree: Leaf, Subtree, Repeat);
22 23
23#[derive(Debug)] 24#[derive(Debug)]
24enum Leaf { 25enum Leaf {
@@ -27,6 +28,7 @@ enum Leaf {
27 Ident(Ident), 28 Ident(Ident),
28 Var(Var), 29 Var(Var),
29} 30}
31impl_froms!(Leaf: Literal, Punct, Ident, Var);
30 32
31#[derive(Debug)] 33#[derive(Debug)]
32struct Subtree { 34struct Subtree {
@@ -35,17 +37,10 @@ struct Subtree {
35} 37}
36 38
37#[derive(Debug)] 39#[derive(Debug)]
38enum Delimiter {
39 Parenthesis,
40 Brace,
41 Bracket,
42 None,
43}
44
45#[derive(Debug)]
46struct Repeat { 40struct Repeat {
47 subtree: Subtree, 41 subtree: Subtree,
48 kind: RepeatKind, 42 kind: RepeatKind,
43 separator: Option<Punct>,
49} 44}
50 45
51#[derive(Debug)] 46#[derive(Debug)]
@@ -73,6 +68,7 @@ struct Ident {
73#[derive(Debug)] 68#[derive(Debug)]
74struct Var { 69struct Var {
75 text: SmolStr, 70 text: SmolStr,
71 kind: Option<SmolStr>,
76} 72}
77 73
78pub(crate) fn parse(tt: &tt::Subtree) -> Option<MacroRules> { 74pub(crate) fn parse(tt: &tt::Subtree) -> Option<MacroRules> {
@@ -86,16 +82,81 @@ pub(crate) fn parse(tt: &tt::Subtree) -> Option<MacroRules> {
86 82
87fn parse_rule(p: &mut RulesParser) -> Option<Rule> { 83fn parse_rule(p: &mut RulesParser) -> Option<Rule> {
88 let lhs = parse_subtree(p.eat_subtree()?)?; 84 let lhs = parse_subtree(p.eat_subtree()?)?;
89 p.eat_punct('=')?; 85 p.expect_char('=')?;
90 p.eat_punct('>')?; 86 p.expect_char('>')?;
91 let rhs = parse_subtree(p.eat_subtree()?)?; 87 let rhs = parse_subtree(p.eat_subtree()?)?;
92 Some(Rule { lhs, rhs }) 88 Some(Rule { lhs, rhs })
93} 89}
94 90
95fn parse_subtree(tt: &tt::Subtree) -> Option<Subtree> { 91fn parse_subtree(tt: &tt::Subtree) -> Option<Subtree> {
92 let mut token_trees = Vec::new();
93 let mut p = RulesParser::new(tt);
94 while let Some(tt) = p.eat() {
95 let child: TokenTree = match tt {
96 tt::TokenTree::Leaf(leaf) => match leaf {
97 tt::Leaf::Punct(tt::Punct { char: '$' }) => {
98 if p.at_ident().is_some() {
99 Leaf::from(parse_var(&mut p)?).into()
100 } else {
101 parse_repeat(&mut p)?.into()
102 }
103 }
104 tt::Leaf::Punct(tt::Punct { char }) => Leaf::from(Punct { char: *char }).into(),
105 tt::Leaf::Ident(tt::Ident { text }) => {
106 Leaf::from(Ident { text: text.clone() }).into()
107 }
108 tt::Leaf::Literal(tt::Literal { text }) => {
109 Leaf::from(Literal { text: text.clone() }).into()
110 }
111 },
112 tt::TokenTree::Subtree(subtree) => parse_subtree(subtree)?.into(),
113 };
114 token_trees.push(child);
115 }
96 Some(Subtree { 116 Some(Subtree {
97 token_trees: Vec::new(), 117 token_trees,
98 delimiter: Delimiter::None, 118 delimiter: tt.delimiter,
119 })
120}
121
122fn parse_var(p: &mut RulesParser) -> Option<Var> {
123 let ident = p.eat_ident().unwrap();
124 let text = ident.text.clone();
125 let kind = if p.at_char(':') {
126 p.bump();
127 if let Some(ident) = p.eat_ident() {
128 Some(ident.text.clone())
129 } else {
130 // ugly as hell :(
131 p.pos -= 1;
132 None
133 }
134 } else {
135 None
136 };
137 Some(Var { text, kind })
138}
139
140fn parse_repeat(p: &mut RulesParser) -> Option<Repeat> {
141 let subtree = p.eat_subtree().unwrap();
142 let subtree = parse_subtree(subtree)?;
143 let mut sep = p.eat_punct()?;
144 let (separator, rep) = match sep.char {
145 '*' | '+' | '?' => (None, sep.char),
146 char => (Some(Punct { char }), p.eat_punct()?.char),
147 };
148
149 let kind = match rep {
150 '*' => RepeatKind::ZeroOrMore,
151 '+' => RepeatKind::OneOrMore,
152 '?' => RepeatKind::ZeroOrMore,
153 _ => return None,
154 };
155 p.bump();
156 Some(Repeat {
157 subtree,
158 kind,
159 separator,
99 }) 160 })
100} 161}
101 162
@@ -117,9 +178,41 @@ impl<'a> RulesParser<'a> {
117 self.subtree.token_trees.get(self.pos) 178 self.subtree.token_trees.get(self.pos)
118 } 179 }
119 180
181 fn at_punct(&self) -> Option<&'a tt::Punct> {
182 match self.current() {
183 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(it))) => Some(it),
184 _ => None,
185 }
186 }
187
188 fn at_char(&self, char: char) -> bool {
189 match self.at_punct() {
190 Some(tt::Punct { char: c }) if *c == char => true,
191 _ => false,
192 }
193 }
194
195 fn at_ident(&mut self) -> Option<&'a tt::Ident> {
196 match self.current() {
197 Some(tt::TokenTree::Leaf(tt::Leaf::Ident(i))) => Some(i),
198 _ => None,
199 }
200 }
201
120 fn bump(&mut self) { 202 fn bump(&mut self) {
121 self.pos += 1; 203 self.pos += 1;
122 } 204 }
205
206 fn eat(&mut self) -> Option<&'a tt::TokenTree> {
207 match self.current() {
208 Some(it) => {
209 self.bump();
210 Some(it)
211 }
212 None => None,
213 }
214 }
215
123 fn eat_subtree(&mut self) -> Option<&'a tt::Subtree> { 216 fn eat_subtree(&mut self) -> Option<&'a tt::Subtree> {
124 match self.current()? { 217 match self.current()? {
125 tt::TokenTree::Subtree(sub) => { 218 tt::TokenTree::Subtree(sub) => {
@@ -129,13 +222,28 @@ impl<'a> RulesParser<'a> {
129 _ => return None, 222 _ => return None,
130 } 223 }
131 } 224 }
132 fn eat_punct(&mut self, char: char) -> Option<()> { 225
133 match self.current()? { 226 fn eat_punct(&mut self) -> Option<&'a tt::Punct> {
134 tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: c })) if *c == char => { 227 if let Some(it) = self.at_punct() {
135 self.bump(); 228 self.bump();
136 Some(()) 229 return Some(it);
137 } 230 }
138 _ => None, 231 None
232 }
233
234 fn eat_ident(&mut self) -> Option<&'a tt::Ident> {
235 if let Some(i) = self.at_ident() {
236 self.bump();
237 return Some(i);
238 }
239 None
240 }
241
242 fn expect_char(&mut self, char: char) -> Option<()> {
243 if self.at_char(char) {
244 self.bump();
245 return Some(());
139 } 246 }
247 None
140 } 248 }
141} 249}