aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/macros/mbe.rs
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/macros/mbe.rs
parent9a043a163c59dd2625727f7ff5466d586625a423 (diff)
move macros to a separate crate
Diffstat (limited to 'crates/ra_hir/src/macros/mbe.rs')
-rw-r--r--crates/ra_hir/src/macros/mbe.rs249
1 files changed, 0 insertions, 249 deletions
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}