diff options
-rw-r--r-- | crates/ra_macros/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_macros/src/mbe.rs | 2 | ||||
-rw-r--r-- | crates/ra_macros/src/mbe_parser.rs | 102 | ||||
-rw-r--r-- | crates/ra_macros/src/tt_cursor.rs | 92 |
4 files changed, 101 insertions, 96 deletions
diff --git a/crates/ra_macros/src/lib.rs b/crates/ra_macros/src/lib.rs index 9485b1c3d..e35a056cc 100644 --- a/crates/ra_macros/src/lib.rs +++ b/crates/ra_macros/src/lib.rs | |||
@@ -12,5 +12,6 @@ macro_rules! impl_froms { | |||
12 | 12 | ||
13 | pub mod tt; | 13 | pub mod tt; |
14 | pub mod mbe; | 14 | pub mod mbe; |
15 | mod tt_cursor; | ||
15 | mod mbe_parser; | 16 | mod mbe_parser; |
16 | mod mbe_expander; | 17 | mod mbe_expander; |
diff --git a/crates/ra_macros/src/mbe.rs b/crates/ra_macros/src/mbe.rs index ec811c5f0..6a168a1b5 100644 --- a/crates/ra_macros/src/mbe.rs +++ b/crates/ra_macros/src/mbe.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use smol_str::SmolStr; | 1 | use smol_str::SmolStr; |
2 | 2 | ||
3 | use crate::tt::{self, Delimiter}; | 3 | use crate::tt::Delimiter; |
4 | 4 | ||
5 | pub use crate::{ | 5 | pub use crate::{ |
6 | mbe_parser::parse, | 6 | mbe_parser::parse, |
diff --git a/crates/ra_macros/src/mbe_parser.rs b/crates/ra_macros/src/mbe_parser.rs index 93c2d40b4..024d3a040 100644 --- a/crates/ra_macros/src/mbe_parser.rs +++ b/crates/ra_macros/src/mbe_parser.rs | |||
@@ -1,99 +1,12 @@ | |||
1 | use crate::{tt, mbe}; | 1 | use crate::{tt, mbe}; |
2 | use crate::tt_cursor::TtCursor; | ||
2 | 3 | ||
3 | /// This module parses a raw `tt::TokenStream` into macro-by-example token | 4 | /// 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 | /// stream. This is a *mostly* identify function, expect for handling of |
5 | /// `$var:tt_kind` and `$(repeat),*` constructs. | 6 | /// `$var:tt_kind` and `$(repeat),*` constructs. |
6 | 7 | ||
7 | struct RulesParser<'a> { | ||
8 | subtree: &'a tt::Subtree, | ||
9 | pos: usize, | ||
10 | } | ||
11 | |||
12 | impl<'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 | |||
95 | pub fn parse(tt: &tt::Subtree) -> Option<mbe::MacroRules> { | 8 | pub fn parse(tt: &tt::Subtree) -> Option<mbe::MacroRules> { |
96 | let mut parser = RulesParser::new(tt); | 9 | let mut parser = TtCursor::new(tt); |
97 | let mut rules = Vec::new(); | 10 | let mut rules = Vec::new(); |
98 | while !parser.is_eof() { | 11 | while !parser.is_eof() { |
99 | rules.push(parse_rule(&mut parser)?) | 12 | rules.push(parse_rule(&mut parser)?) |
@@ -101,7 +14,7 @@ pub fn parse(tt: &tt::Subtree) -> Option<mbe::MacroRules> { | |||
101 | Some(mbe::MacroRules { rules }) | 14 | Some(mbe::MacroRules { rules }) |
102 | } | 15 | } |
103 | 16 | ||
104 | fn parse_rule(p: &mut RulesParser) -> Option<mbe::Rule> { | 17 | fn parse_rule(p: &mut TtCursor) -> Option<mbe::Rule> { |
105 | let lhs = parse_subtree(p.eat_subtree()?)?; | 18 | let lhs = parse_subtree(p.eat_subtree()?)?; |
106 | p.expect_char('=')?; | 19 | p.expect_char('=')?; |
107 | p.expect_char('>')?; | 20 | p.expect_char('>')?; |
@@ -111,7 +24,7 @@ fn parse_rule(p: &mut RulesParser) -> Option<mbe::Rule> { | |||
111 | 24 | ||
112 | fn parse_subtree(tt: &tt::Subtree) -> Option<mbe::Subtree> { | 25 | fn parse_subtree(tt: &tt::Subtree) -> Option<mbe::Subtree> { |
113 | let mut token_trees = Vec::new(); | 26 | let mut token_trees = Vec::new(); |
114 | let mut p = RulesParser::new(tt); | 27 | let mut p = TtCursor::new(tt); |
115 | while let Some(tt) = p.eat() { | 28 | while let Some(tt) = p.eat() { |
116 | let child: mbe::TokenTree = match tt { | 29 | let child: mbe::TokenTree = match tt { |
117 | tt::TokenTree::Leaf(leaf) => match leaf { | 30 | tt::TokenTree::Leaf(leaf) => match leaf { |
@@ -142,7 +55,7 @@ fn parse_subtree(tt: &tt::Subtree) -> Option<mbe::Subtree> { | |||
142 | }) | 55 | }) |
143 | } | 56 | } |
144 | 57 | ||
145 | fn parse_var(p: &mut RulesParser) -> Option<mbe::Var> { | 58 | fn parse_var(p: &mut TtCursor) -> Option<mbe::Var> { |
146 | let ident = p.eat_ident().unwrap(); | 59 | let ident = p.eat_ident().unwrap(); |
147 | let text = ident.text.clone(); | 60 | let text = ident.text.clone(); |
148 | let kind = if p.at_char(':') { | 61 | let kind = if p.at_char(':') { |
@@ -150,8 +63,7 @@ fn parse_var(p: &mut RulesParser) -> Option<mbe::Var> { | |||
150 | if let Some(ident) = p.eat_ident() { | 63 | if let Some(ident) = p.eat_ident() { |
151 | Some(ident.text.clone()) | 64 | Some(ident.text.clone()) |
152 | } else { | 65 | } else { |
153 | // ugly as hell :( | 66 | p.rev_bump(); |
154 | p.pos -= 1; | ||
155 | None | 67 | None |
156 | } | 68 | } |
157 | } else { | 69 | } else { |
@@ -160,7 +72,7 @@ fn parse_var(p: &mut RulesParser) -> Option<mbe::Var> { | |||
160 | Some(mbe::Var { text, kind }) | 72 | Some(mbe::Var { text, kind }) |
161 | } | 73 | } |
162 | 74 | ||
163 | fn parse_repeat(p: &mut RulesParser) -> Option<mbe::Repeat> { | 75 | fn parse_repeat(p: &mut TtCursor) -> Option<mbe::Repeat> { |
164 | let subtree = p.eat_subtree().unwrap(); | 76 | let subtree = p.eat_subtree().unwrap(); |
165 | let subtree = parse_subtree(subtree)?; | 77 | let subtree = parse_subtree(subtree)?; |
166 | let sep = p.eat_punct()?; | 78 | let sep = p.eat_punct()?; |
diff --git a/crates/ra_macros/src/tt_cursor.rs b/crates/ra_macros/src/tt_cursor.rs new file mode 100644 index 000000000..380c60b40 --- /dev/null +++ b/crates/ra_macros/src/tt_cursor.rs | |||
@@ -0,0 +1,92 @@ | |||
1 | use crate::tt; | ||
2 | |||
3 | pub(crate) struct TtCursor<'a> { | ||
4 | subtree: &'a tt::Subtree, | ||
5 | pos: usize, | ||
6 | } | ||
7 | |||
8 | impl<'a> TtCursor<'a> { | ||
9 | pub(crate) fn new(subtree: &'a tt::Subtree) -> TtCursor<'a> { | ||
10 | TtCursor { subtree, pos: 0 } | ||
11 | } | ||
12 | |||
13 | pub(crate) fn is_eof(&self) -> bool { | ||
14 | self.pos == self.subtree.token_trees.len() | ||
15 | } | ||
16 | |||
17 | pub(crate) fn current(&self) -> Option<&'a tt::TokenTree> { | ||
18 | self.subtree.token_trees.get(self.pos) | ||
19 | } | ||
20 | |||
21 | pub(crate) fn at_punct(&self) -> Option<&'a tt::Punct> { | ||
22 | match self.current() { | ||
23 | Some(tt::TokenTree::Leaf(tt::Leaf::Punct(it))) => Some(it), | ||
24 | _ => None, | ||
25 | } | ||
26 | } | ||
27 | |||
28 | pub(crate) fn at_char(&self, char: char) -> bool { | ||
29 | match self.at_punct() { | ||
30 | Some(tt::Punct { char: c }) if *c == char => true, | ||
31 | _ => false, | ||
32 | } | ||
33 | } | ||
34 | |||
35 | pub(crate) fn at_ident(&mut self) -> Option<&'a tt::Ident> { | ||
36 | match self.current() { | ||
37 | Some(tt::TokenTree::Leaf(tt::Leaf::Ident(i))) => Some(i), | ||
38 | _ => None, | ||
39 | } | ||
40 | } | ||
41 | |||
42 | pub(crate) fn bump(&mut self) { | ||
43 | self.pos += 1; | ||
44 | } | ||
45 | pub(crate) fn rev_bump(&mut self) { | ||
46 | self.pos -= 1; | ||
47 | } | ||
48 | |||
49 | pub(crate) fn eat(&mut self) -> Option<&'a tt::TokenTree> { | ||
50 | match self.current() { | ||
51 | Some(it) => { | ||
52 | self.bump(); | ||
53 | Some(it) | ||
54 | } | ||
55 | None => None, | ||
56 | } | ||
57 | } | ||
58 | |||
59 | pub(crate) fn eat_subtree(&mut self) -> Option<&'a tt::Subtree> { | ||
60 | match self.current()? { | ||
61 | tt::TokenTree::Subtree(sub) => { | ||
62 | self.bump(); | ||
63 | Some(sub) | ||
64 | } | ||
65 | _ => return None, | ||
66 | } | ||
67 | } | ||
68 | |||
69 | pub(crate) fn eat_punct(&mut self) -> Option<&'a tt::Punct> { | ||
70 | if let Some(it) = self.at_punct() { | ||
71 | self.bump(); | ||
72 | return Some(it); | ||
73 | } | ||
74 | None | ||
75 | } | ||
76 | |||
77 | pub(crate) fn eat_ident(&mut self) -> Option<&'a tt::Ident> { | ||
78 | if let Some(i) = self.at_ident() { | ||
79 | self.bump(); | ||
80 | return Some(i); | ||
81 | } | ||
82 | None | ||
83 | } | ||
84 | |||
85 | pub(crate) fn expect_char(&mut self, char: char) -> Option<()> { | ||
86 | if self.at_char(char) { | ||
87 | self.bump(); | ||
88 | return Some(()); | ||
89 | } | ||
90 | None | ||
91 | } | ||
92 | } | ||