aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-01-31 10:40:05 +0000
committerAleksey Kladov <[email protected]>2019-01-31 20:23:30 +0000
commitce3636798bc9481ec712b84b5cad9973b7844425 (patch)
tree0f252e18492e50ce8eff8c0aacb249a763601dd0 /crates/ra_hir/src
parent9a043a163c59dd2625727f7ff5466d586625a423 (diff)
move macros to a separate crate
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/macros.rs6
-rw-r--r--crates/ra_hir/src/macros/mbe.rs249
-rw-r--r--crates/ra_hir/src/macros/tt.rs45
3 files changed, 1 insertions, 299 deletions
diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs
index dc016a704..7e9aba3f2 100644
--- a/crates/ra_hir/src/macros.rs
+++ b/crates/ra_hir/src/macros.rs
@@ -1,8 +1,3 @@
1#[allow(unused)]
2mod tt;
3#[allow(unused)]
4mod mbe;
5
6/// Machinery for macro expansion. 1/// Machinery for macro expansion.
7/// 2///
8/// One of the more complicated things about macros is managing the source code 3/// One of the more complicated things about macros is managing the source code
@@ -19,6 +14,7 @@ use ra_syntax::{
19 SyntaxKind::*, 14 SyntaxKind::*,
20 ast::{self, NameOwner}, 15 ast::{self, NameOwner},
21}; 16};
17use ra_macros::{tt, mbe};
22 18
23use crate::{HirDatabase, MacroCallId}; 19use crate::{HirDatabase, MacroCallId};
24 20
diff --git a/crates/ra_hir/src/macros/mbe.rs b/crates/ra_hir/src/macros/mbe.rs
deleted file mode 100644
index 6c93ae5e3..000000000
--- a/crates/ra_hir/src/macros/mbe.rs
+++ /dev/null
@@ -1,249 +0,0 @@
1use ra_syntax::SmolStr;
2
3use crate::macros::tt::{self, Delimiter};
4
5#[derive(Debug)]
6pub(crate) struct MacroRules {
7 rules: Vec<Rule>,
8}
9
10#[derive(Debug)]
11struct Rule {
12 lhs: Subtree,
13 rhs: Subtree,
14}
15
16#[derive(Debug)]
17enum TokenTree {
18 Leaf(Leaf),
19 Subtree(Subtree),
20 Repeat(Repeat),
21}
22impl_froms!(TokenTree: Leaf, Subtree, Repeat);
23
24#[derive(Debug)]
25enum Leaf {
26 Literal(Literal),
27 Punct(Punct),
28 Ident(Ident),
29 Var(Var),
30}
31impl_froms!(Leaf: Literal, Punct, Ident, Var);
32
33#[derive(Debug)]
34struct Subtree {
35 delimiter: Delimiter,
36 token_trees: Vec<TokenTree>,
37}
38
39#[derive(Debug)]
40struct Repeat {
41 subtree: Subtree,
42 kind: RepeatKind,
43 separator: Option<Punct>,
44}
45
46#[derive(Debug)]
47enum RepeatKind {
48 ZeroOrMore,
49 OneOrMore,
50 ZeroOrOne,
51}
52
53#[derive(Debug)]
54struct Literal {
55 text: SmolStr,
56}
57
58#[derive(Debug)]
59struct Punct {
60 char: char,
61}
62
63#[derive(Debug)]
64struct Ident {
65 text: SmolStr,
66}
67
68#[derive(Debug)]
69struct Var {
70 text: SmolStr,
71 kind: Option<SmolStr>,
72}
73
74pub(crate) fn parse(tt: &tt::Subtree) -> Option<MacroRules> {
75 let mut parser = RulesParser::new(tt);
76 let mut rules = Vec::new();
77 while !parser.is_eof() {
78 rules.push(parse_rule(&mut parser)?)
79 }
80 Some(MacroRules { rules })
81}
82
83fn parse_rule(p: &mut RulesParser) -> Option<Rule> {
84 let lhs = parse_subtree(p.eat_subtree()?)?;
85 p.expect_char('=')?;
86 p.expect_char('>')?;
87 let rhs = parse_subtree(p.eat_subtree()?)?;
88 Some(Rule { lhs, rhs })
89}
90
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 }
116 Some(Subtree {
117 token_trees,
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,
160 })
161}
162
163struct RulesParser<'a> {
164 subtree: &'a tt::Subtree,
165 pos: usize,
166}
167
168impl<'a> RulesParser<'a> {
169 fn new(subtree: &'a tt::Subtree) -> RulesParser<'a> {
170 RulesParser { subtree, pos: 0 }
171 }
172
173 fn is_eof(&self) -> bool {
174 self.pos == self.subtree.token_trees.len()
175 }
176
177 fn current(&self) -> Option<&'a tt::TokenTree> {
178 self.subtree.token_trees.get(self.pos)
179 }
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
202 fn bump(&mut self) {
203 self.pos += 1;
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
216 fn eat_subtree(&mut self) -> Option<&'a tt::Subtree> {
217 match self.current()? {
218 tt::TokenTree::Subtree(sub) => {
219 self.bump();
220 Some(sub)
221 }
222 _ => return None,
223 }
224 }
225
226 fn eat_punct(&mut self) -> Option<&'a tt::Punct> {
227 if let Some(it) = self.at_punct() {
228 self.bump();
229 return Some(it);
230 }
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(());
246 }
247 None
248 }
249}
diff --git a/crates/ra_hir/src/macros/tt.rs b/crates/ra_hir/src/macros/tt.rs
deleted file mode 100644
index 64e88ddc5..000000000
--- a/crates/ra_hir/src/macros/tt.rs
+++ /dev/null
@@ -1,45 +0,0 @@
1use ra_syntax::SmolStr;
2
3#[derive(Debug)]
4pub(crate) enum TokenTree {
5 Leaf(Leaf),
6 Subtree(Subtree),
7}
8impl_froms!(TokenTree: Leaf, Subtree);
9
10#[derive(Debug)]
11pub(crate) enum Leaf {
12 Literal(Literal),
13 Punct(Punct),
14 Ident(Ident),
15}
16impl_froms!(Leaf: Literal, Punct, Ident);
17
18#[derive(Debug)]
19pub(crate) struct Subtree {
20 pub(crate) delimiter: Delimiter,
21 pub(crate) token_trees: Vec<TokenTree>,
22}
23
24#[derive(Clone, Copy, Debug)]
25pub(crate) enum Delimiter {
26 Parenthesis,
27 Brace,
28 Bracket,
29 None,
30}
31
32#[derive(Debug)]
33pub(crate) struct Literal {
34 pub(crate) text: SmolStr,
35}
36
37#[derive(Debug)]
38pub(crate) struct Punct {
39 pub(crate) char: char,
40}
41
42#[derive(Debug)]
43pub(crate) struct Ident {
44 pub(crate) text: SmolStr,
45}