aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_macros/src/lib.rs1
-rw-r--r--crates/ra_macros/src/mbe.rs225
-rw-r--r--crates/ra_macros/src/mbe_parser.rs184
3 files changed, 210 insertions, 200 deletions
diff --git a/crates/ra_macros/src/lib.rs b/crates/ra_macros/src/lib.rs
index 6063c06c2..8c284fa71 100644
--- a/crates/ra_macros/src/lib.rs
+++ b/crates/ra_macros/src/lib.rs
@@ -12,3 +12,4 @@ macro_rules! impl_froms {
12 12
13pub mod tt; 13pub mod tt;
14pub mod mbe; 14pub mod mbe;
15mod mbe_parser;
diff --git a/crates/ra_macros/src/mbe.rs b/crates/ra_macros/src/mbe.rs
index 1aa6be736..72d6707aa 100644
--- a/crates/ra_macros/src/mbe.rs
+++ b/crates/ra_macros/src/mbe.rs
@@ -2,19 +2,21 @@ use smol_str::SmolStr;
2 2
3use crate::tt::{self, Delimiter}; 3use crate::tt::{self, Delimiter};
4 4
5pub use crate::mbe_parser::parse;
6
5#[derive(Debug)] 7#[derive(Debug)]
6pub struct MacroRules { 8pub struct MacroRules {
7 rules: Vec<Rule>, 9 pub(crate) rules: Vec<Rule>,
8} 10}
9 11
10#[derive(Debug)] 12#[derive(Debug)]
11struct Rule { 13pub(crate) struct Rule {
12 lhs: Subtree, 14 pub(crate) lhs: Subtree,
13 rhs: Subtree, 15 pub(crate) rhs: Subtree,
14} 16}
15 17
16#[derive(Debug)] 18#[derive(Debug)]
17enum TokenTree { 19pub(crate) enum TokenTree {
18 Leaf(Leaf), 20 Leaf(Leaf),
19 Subtree(Subtree), 21 Subtree(Subtree),
20 Repeat(Repeat), 22 Repeat(Repeat),
@@ -22,7 +24,7 @@ enum TokenTree {
22impl_froms!(TokenTree: Leaf, Subtree, Repeat); 24impl_froms!(TokenTree: Leaf, Subtree, Repeat);
23 25
24#[derive(Debug)] 26#[derive(Debug)]
25enum Leaf { 27pub(crate) enum Leaf {
26 Literal(Literal), 28 Literal(Literal),
27 Punct(Punct), 29 Punct(Punct),
28 Ident(Ident), 30 Ident(Ident),
@@ -31,219 +33,42 @@ enum Leaf {
31impl_froms!(Leaf: Literal, Punct, Ident, Var); 33impl_froms!(Leaf: Literal, Punct, Ident, Var);
32 34
33#[derive(Debug)] 35#[derive(Debug)]
34struct Subtree { 36pub(crate) struct Subtree {
35 delimiter: Delimiter, 37 pub(crate) delimiter: Delimiter,
36 token_trees: Vec<TokenTree>, 38 pub(crate) token_trees: Vec<TokenTree>,
37} 39}
38 40
39#[derive(Debug)] 41#[derive(Debug)]
40struct Repeat { 42pub(crate) struct Repeat {
41 subtree: Subtree, 43 pub(crate) subtree: Subtree,
42 kind: RepeatKind, 44 pub(crate) kind: RepeatKind,
43 separator: Option<Punct>, 45 pub(crate) separator: Option<Punct>,
44} 46}
45 47
46#[derive(Debug)] 48#[derive(Debug)]
47enum RepeatKind { 49pub(crate) enum RepeatKind {
48 ZeroOrMore, 50 ZeroOrMore,
49 OneOrMore, 51 OneOrMore,
50 ZeroOrOne, 52 ZeroOrOne,
51} 53}
52 54
53#[derive(Debug)] 55#[derive(Debug)]
54struct Literal { 56pub(crate) struct Literal {
55 text: SmolStr, 57 pub(crate) text: SmolStr,
56} 58}
57 59
58#[derive(Debug)] 60#[derive(Debug)]
59struct Punct { 61pub(crate) struct Punct {
60 char: char, 62 pub(crate) char: char,
61} 63}
62 64
63#[derive(Debug)] 65#[derive(Debug)]
64struct Ident { 66pub(crate) struct Ident {
65 text: SmolStr, 67 pub(crate) text: SmolStr,
66} 68}
67 69
68#[derive(Debug)] 70#[derive(Debug)]
69struct Var { 71pub(crate) struct Var {
70 text: SmolStr, 72 pub(crate) text: SmolStr,
71 kind: Option<SmolStr>, 73 pub(crate) kind: Option<SmolStr>,
72}
73
74pub 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 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} 74}
diff --git a/crates/ra_macros/src/mbe_parser.rs b/crates/ra_macros/src/mbe_parser.rs
new file mode 100644
index 000000000..93c2d40b4
--- /dev/null
+++ b/crates/ra_macros/src/mbe_parser.rs
@@ -0,0 +1,184 @@
1use crate::{tt, mbe};
2
3/// This module parses a raw `tt::TokenStream` into macro-by-example token
4/// stream. This is a *mostly* identify function, expect for handling of
5/// `$var:tt_kind` and `$(repeat),*` constructs.
6
7struct RulesParser<'a> {
8 subtree: &'a tt::Subtree,
9 pos: usize,
10}
11
12impl<'a> RulesParser<'a> {
13 fn new(subtree: &'a tt::Subtree) -> RulesParser<'a> {
14 RulesParser { subtree, pos: 0 }
15 }
16
17 fn is_eof(&self) -> bool {
18 self.pos == self.subtree.token_trees.len()
19 }
20
21 fn current(&self) -> Option<&'a tt::TokenTree> {
22 self.subtree.token_trees.get(self.pos)
23 }
24
25 fn at_punct(&self) -> Option<&'a tt::Punct> {
26 match self.current() {
27 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(it))) => Some(it),
28 _ => None,
29 }
30 }
31
32 fn at_char(&self, char: char) -> bool {
33 match self.at_punct() {
34 Some(tt::Punct { char: c }) if *c == char => true,
35 _ => false,
36 }
37 }
38
39 fn at_ident(&mut self) -> Option<&'a tt::Ident> {
40 match self.current() {
41 Some(tt::TokenTree::Leaf(tt::Leaf::Ident(i))) => Some(i),
42 _ => None,
43 }
44 }
45
46 fn bump(&mut self) {
47 self.pos += 1;
48 }
49
50 fn eat(&mut self) -> Option<&'a tt::TokenTree> {
51 match self.current() {
52 Some(it) => {
53 self.bump();
54 Some(it)
55 }
56 None => None,
57 }
58 }
59
60 fn eat_subtree(&mut self) -> Option<&'a tt::Subtree> {
61 match self.current()? {
62 tt::TokenTree::Subtree(sub) => {
63 self.bump();
64 Some(sub)
65 }
66 _ => return None,
67 }
68 }
69
70 fn eat_punct(&mut self) -> Option<&'a tt::Punct> {
71 if let Some(it) = self.at_punct() {
72 self.bump();
73 return Some(it);
74 }
75 None
76 }
77
78 fn eat_ident(&mut self) -> Option<&'a tt::Ident> {
79 if let Some(i) = self.at_ident() {
80 self.bump();
81 return Some(i);
82 }
83 None
84 }
85
86 fn expect_char(&mut self, char: char) -> Option<()> {
87 if self.at_char(char) {
88 self.bump();
89 return Some(());
90 }
91 None
92 }
93}
94
95pub fn parse(tt: &tt::Subtree) -> Option<mbe::MacroRules> {
96 let mut parser = RulesParser::new(tt);
97 let mut rules = Vec::new();
98 while !parser.is_eof() {
99 rules.push(parse_rule(&mut parser)?)
100 }
101 Some(mbe::MacroRules { rules })
102}
103
104fn parse_rule(p: &mut RulesParser) -> Option<mbe::Rule> {
105 let lhs = parse_subtree(p.eat_subtree()?)?;
106 p.expect_char('=')?;
107 p.expect_char('>')?;
108 let rhs = parse_subtree(p.eat_subtree()?)?;
109 Some(mbe::Rule { lhs, rhs })
110}
111
112fn parse_subtree(tt: &tt::Subtree) -> Option<mbe::Subtree> {
113 let mut token_trees = Vec::new();
114 let mut p = RulesParser::new(tt);
115 while let Some(tt) = p.eat() {
116 let child: mbe::TokenTree = match tt {
117 tt::TokenTree::Leaf(leaf) => match leaf {
118 tt::Leaf::Punct(tt::Punct { char: '$' }) => {
119 if p.at_ident().is_some() {
120 mbe::Leaf::from(parse_var(&mut p)?).into()
121 } else {
122 parse_repeat(&mut p)?.into()
123 }
124 }
125 tt::Leaf::Punct(tt::Punct { char }) => {
126 mbe::Leaf::from(mbe::Punct { char: *char }).into()
127 }
128 tt::Leaf::Ident(tt::Ident { text }) => {
129 mbe::Leaf::from(mbe::Ident { text: text.clone() }).into()
130 }
131 tt::Leaf::Literal(tt::Literal { text }) => {
132 mbe::Leaf::from(mbe::Literal { text: text.clone() }).into()
133 }
134 },
135 tt::TokenTree::Subtree(subtree) => parse_subtree(subtree)?.into(),
136 };
137 token_trees.push(child);
138 }
139 Some(mbe::Subtree {
140 token_trees,
141 delimiter: tt.delimiter,
142 })
143}
144
145fn parse_var(p: &mut RulesParser) -> Option<mbe::Var> {
146 let ident = p.eat_ident().unwrap();
147 let text = ident.text.clone();
148 let kind = if p.at_char(':') {
149 p.bump();
150 if let Some(ident) = p.eat_ident() {
151 Some(ident.text.clone())
152 } else {
153 // ugly as hell :(
154 p.pos -= 1;
155 None
156 }
157 } else {
158 None
159 };
160 Some(mbe::Var { text, kind })
161}
162
163fn parse_repeat(p: &mut RulesParser) -> Option<mbe::Repeat> {
164 let subtree = p.eat_subtree().unwrap();
165 let subtree = parse_subtree(subtree)?;
166 let sep = p.eat_punct()?;
167 let (separator, rep) = match sep.char {
168 '*' | '+' | '?' => (None, sep.char),
169 char => (Some(mbe::Punct { char }), p.eat_punct()?.char),
170 };
171
172 let kind = match rep {
173 '*' => mbe::RepeatKind::ZeroOrMore,
174 '+' => mbe::RepeatKind::OneOrMore,
175 '?' => mbe::RepeatKind::ZeroOrMore,
176 _ => return None,
177 };
178 p.bump();
179 Some(mbe::Repeat {
180 subtree,
181 kind,
182 separator,
183 })
184}