diff options
-rw-r--r-- | crates/ra_mbe/src/mbe_expander.rs | 122 | ||||
-rw-r--r-- | crates/ra_mbe/src/subtree_parser.rs | 40 | ||||
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 32 | ||||
-rw-r--r-- | crates/ra_mbe/src/tt_cursor.rs | 46 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar.rs | 145 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/paths.rs | 2 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/patterns.rs | 2 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/types.rs | 2 | ||||
-rw-r--r-- | crates/ra_parser/src/lib.rs | 86 |
9 files changed, 188 insertions, 289 deletions
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs index f185aecb7..adee0cb42 100644 --- a/crates/ra_mbe/src/mbe_expander.rs +++ b/crates/ra_mbe/src/mbe_expander.rs | |||
@@ -1,7 +1,9 @@ | |||
1 | //! This module takes a (parsed) definition of `macro_rules` invocation, a | ||
2 | //! `tt::TokenTree` representing an argument of macro invocation, and produces a | ||
3 | //! `tt::TokenTree` for the result of the expansion. | ||
4 | |||
5 | use ra_parser::FragmentKind::*; | ||
1 | use ra_syntax::SmolStr; | 6 | use ra_syntax::SmolStr; |
2 | /// This module takes a (parsed) definition of `macro_rules` invocation, a | ||
3 | /// `tt::TokenTree` representing an argument of macro invocation, and produces a | ||
4 | /// `tt::TokenTree` for the result of the expansion. | ||
5 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::FxHashMap; |
6 | use tt::TokenId; | 8 | use tt::TokenId; |
7 | 9 | ||
@@ -192,81 +194,11 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings, | |||
192 | crate::TokenTree::Leaf(leaf) => match leaf { | 194 | crate::TokenTree::Leaf(leaf) => match leaf { |
193 | crate::Leaf::Var(crate::Var { text, kind }) => { | 195 | crate::Leaf::Var(crate::Var { text, kind }) => { |
194 | let kind = kind.clone().ok_or(ExpandError::UnexpectedToken)?; | 196 | let kind = kind.clone().ok_or(ExpandError::UnexpectedToken)?; |
195 | match kind.as_str() { | 197 | match match_meta_var(kind.as_str(), input)? { |
196 | "ident" => { | 198 | Some(tt) => { |
197 | let ident = | 199 | res.inner.insert(text.clone(), Binding::Simple(tt)); |
198 | input.eat_ident().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
199 | res.inner.insert( | ||
200 | text.clone(), | ||
201 | Binding::Simple(tt::Leaf::from(ident).into()), | ||
202 | ); | ||
203 | } | ||
204 | "path" => { | ||
205 | let path = | ||
206 | input.eat_path().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
207 | res.inner.insert(text.clone(), Binding::Simple(path)); | ||
208 | } | ||
209 | "expr" => { | ||
210 | let expr = | ||
211 | input.eat_expr().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
212 | res.inner.insert(text.clone(), Binding::Simple(expr)); | ||
213 | } | ||
214 | "ty" => { | ||
215 | let ty = input.eat_ty().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
216 | res.inner.insert(text.clone(), Binding::Simple(ty)); | ||
217 | } | ||
218 | "pat" => { | ||
219 | let pat = input.eat_pat().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
220 | res.inner.insert(text.clone(), Binding::Simple(pat)); | ||
221 | } | ||
222 | "stmt" => { | ||
223 | let pat = input.eat_stmt().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
224 | res.inner.insert(text.clone(), Binding::Simple(pat)); | ||
225 | } | ||
226 | "block" => { | ||
227 | let block = | ||
228 | input.eat_block().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
229 | res.inner.insert(text.clone(), Binding::Simple(block)); | ||
230 | } | ||
231 | "meta" => { | ||
232 | let meta = | ||
233 | input.eat_meta().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
234 | res.inner.insert(text.clone(), Binding::Simple(meta)); | ||
235 | } | ||
236 | "tt" => { | ||
237 | let token = input.eat().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
238 | res.inner.insert(text.clone(), Binding::Simple(token)); | ||
239 | } | ||
240 | "item" => { | ||
241 | let item = | ||
242 | input.eat_item().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
243 | res.inner.insert(text.clone(), Binding::Simple(item)); | ||
244 | } | ||
245 | "lifetime" => { | ||
246 | let lifetime = | ||
247 | input.eat_lifetime().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
248 | res.inner.insert(text.clone(), Binding::Simple(lifetime)); | ||
249 | } | 200 | } |
250 | "literal" => { | 201 | None => res.push_optional(text), |
251 | let literal = | ||
252 | input.eat_literal().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
253 | |||
254 | res.inner.insert( | ||
255 | text.clone(), | ||
256 | Binding::Simple(tt::Leaf::from(literal).into()), | ||
257 | ); | ||
258 | } | ||
259 | "vis" => { | ||
260 | // `vis` is optional | ||
261 | if let Some(vis) = input.try_eat_vis() { | ||
262 | let vis = vis.clone(); | ||
263 | res.inner.insert(text.clone(), Binding::Simple(vis)); | ||
264 | } else { | ||
265 | res.push_optional(&text); | ||
266 | } | ||
267 | } | ||
268 | |||
269 | _ => return Err(ExpandError::UnexpectedToken), | ||
270 | } | 202 | } |
271 | } | 203 | } |
272 | crate::Leaf::Punct(punct) => { | 204 | crate::Leaf::Punct(punct) => { |
@@ -360,6 +292,42 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings, | |||
360 | Ok(res) | 292 | Ok(res) |
361 | } | 293 | } |
362 | 294 | ||
295 | fn match_meta_var(kind: &str, input: &mut TtCursor) -> Result<Option<tt::TokenTree>, ExpandError> { | ||
296 | let fragment = match kind { | ||
297 | "path" => Path, | ||
298 | "expr" => Expr, | ||
299 | "ty" => Type, | ||
300 | "pat" => Pattern, | ||
301 | "stmt" => Statement, | ||
302 | "block" => Block, | ||
303 | "meta" => MetaItem, | ||
304 | "item" => Item, | ||
305 | _ => { | ||
306 | let binding = match kind { | ||
307 | "ident" => { | ||
308 | let ident = input.eat_ident().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
309 | tt::Leaf::from(ident).into() | ||
310 | } | ||
311 | "tt" => input.eat().ok_or(ExpandError::UnexpectedToken)?.clone(), | ||
312 | "lifetime" => input.eat_lifetime().ok_or(ExpandError::UnexpectedToken)?.clone(), | ||
313 | "literal" => { | ||
314 | let literal = input.eat_literal().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
315 | tt::Leaf::from(literal).into() | ||
316 | } | ||
317 | // `vis` is optional | ||
318 | "vis" => match input.try_eat_vis() { | ||
319 | Some(vis) => vis, | ||
320 | None => return Ok(None), | ||
321 | }, | ||
322 | _ => return Err(ExpandError::UnexpectedToken), | ||
323 | }; | ||
324 | return Ok(Some(binding)); | ||
325 | } | ||
326 | }; | ||
327 | let binding = input.eat_fragment(fragment).ok_or(ExpandError::UnexpectedToken)?; | ||
328 | Ok(Some(binding)) | ||
329 | } | ||
330 | |||
363 | #[derive(Debug)] | 331 | #[derive(Debug)] |
364 | struct ExpandCtx<'a> { | 332 | struct ExpandCtx<'a> { |
365 | bindings: &'a Bindings, | 333 | bindings: &'a Bindings, |
diff --git a/crates/ra_mbe/src/subtree_parser.rs b/crates/ra_mbe/src/subtree_parser.rs index 5688e7f7f..4440c69ff 100644 --- a/crates/ra_mbe/src/subtree_parser.rs +++ b/crates/ra_mbe/src/subtree_parser.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use crate::subtree_source::SubtreeTokenSource; | 1 | use crate::subtree_source::SubtreeTokenSource; |
2 | 2 | ||
3 | use ra_parser::{TokenSource, TreeSink}; | 3 | use ra_parser::{FragmentKind, TokenSource, TreeSink}; |
4 | use ra_syntax::SyntaxKind; | 4 | use ra_syntax::SyntaxKind; |
5 | use tt::buffer::{Cursor, TokenBuffer}; | 5 | use tt::buffer::{Cursor, TokenBuffer}; |
6 | 6 | ||
@@ -52,40 +52,10 @@ impl<'a> Parser<'a> { | |||
52 | Parser { cur_pos, subtree } | 52 | Parser { cur_pos, subtree } |
53 | } | 53 | } |
54 | 54 | ||
55 | pub fn parse_path(self) -> Option<tt::TokenTree> { | 55 | pub fn parse_fragment(self, fragment_kind: FragmentKind) -> Option<tt::TokenTree> { |
56 | self.parse(ra_parser::parse_path) | 56 | self.parse(|token_source, tree_skink| { |
57 | } | 57 | ra_parser::parse_fragment(token_source, tree_skink, fragment_kind) |
58 | 58 | }) | |
59 | pub fn parse_expr(self) -> Option<tt::TokenTree> { | ||
60 | self.parse(ra_parser::parse_expr) | ||
61 | } | ||
62 | |||
63 | pub fn parse_ty(self) -> Option<tt::TokenTree> { | ||
64 | self.parse(ra_parser::parse_ty) | ||
65 | } | ||
66 | |||
67 | pub fn parse_pat(self) -> Option<tt::TokenTree> { | ||
68 | self.parse(ra_parser::parse_pat) | ||
69 | } | ||
70 | |||
71 | pub fn parse_stmt(self) -> Option<tt::TokenTree> { | ||
72 | self.parse(|src, sink| ra_parser::parse_stmt(src, sink, false)) | ||
73 | } | ||
74 | |||
75 | pub fn parse_block(self) -> Option<tt::TokenTree> { | ||
76 | self.parse(ra_parser::parse_block) | ||
77 | } | ||
78 | |||
79 | pub fn parse_meta(self) -> Option<tt::TokenTree> { | ||
80 | self.parse(ra_parser::parse_meta) | ||
81 | } | ||
82 | |||
83 | pub fn parse_item(self) -> Option<tt::TokenTree> { | ||
84 | self.parse(ra_parser::parse_item) | ||
85 | } | ||
86 | |||
87 | pub fn parse_vis(self) -> Option<tt::TokenTree> { | ||
88 | self.parse(ra_parser::parse_vis) | ||
89 | } | 59 | } |
90 | 60 | ||
91 | fn parse<F>(self, f: F) -> Option<tt::TokenTree> | 61 | fn parse<F>(self, f: F) -> Option<tt::TokenTree> |
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 8225759e7..a380b1cfd 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -1,4 +1,7 @@ | |||
1 | use ra_parser::{ParseError, TreeSink}; | 1 | use ra_parser::{ |
2 | FragmentKind::{self, *}, | ||
3 | ParseError, TreeSink, | ||
4 | }; | ||
2 | use ra_syntax::{ | 5 | use ra_syntax::{ |
3 | ast, AstNode, AstToken, NodeOrToken, Parse, SmolStr, SyntaxKind, SyntaxKind::*, SyntaxNode, | 6 | ast, AstNode, AstToken, NodeOrToken, Parse, SmolStr, SyntaxKind, SyntaxKind::*, SyntaxNode, |
4 | SyntaxTreeBuilder, TextRange, TextUnit, T, | 7 | SyntaxTreeBuilder, TextRange, TextUnit, T, |
@@ -63,33 +66,50 @@ where | |||
63 | Ok(parse) | 66 | Ok(parse) |
64 | } | 67 | } |
65 | 68 | ||
69 | fn fragment_to_syntax_node( | ||
70 | tt: &tt::Subtree, | ||
71 | fragment_kind: FragmentKind, | ||
72 | ) -> Result<Parse<SyntaxNode>, ExpandError> { | ||
73 | let tokens = [tt.clone().into()]; | ||
74 | let buffer = TokenBuffer::new(&tokens); | ||
75 | let mut token_source = SubtreeTokenSource::new(&buffer); | ||
76 | let mut tree_sink = TtTreeSink::new(buffer.begin()); | ||
77 | ra_parser::parse_fragment(&mut token_source, &mut tree_sink, fragment_kind); | ||
78 | if tree_sink.roots.len() != 1 { | ||
79 | return Err(ExpandError::ConversionError); | ||
80 | } | ||
81 | //FIXME: would be cool to report errors | ||
82 | let parse = tree_sink.inner.finish(); | ||
83 | Ok(parse) | ||
84 | } | ||
85 | |||
66 | /// Parses the token tree (result of macro expansion) to an expression | 86 | /// Parses the token tree (result of macro expansion) to an expression |
67 | pub fn token_tree_to_expr(tt: &tt::Subtree) -> Result<Parse<ast::Expr>, ExpandError> { | 87 | pub fn token_tree_to_expr(tt: &tt::Subtree) -> Result<Parse<ast::Expr>, ExpandError> { |
68 | let parse = token_tree_to_syntax_node(tt, ra_parser::parse_expr)?; | 88 | let parse = fragment_to_syntax_node(tt, Expr)?; |
69 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 89 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) |
70 | } | 90 | } |
71 | 91 | ||
72 | /// Parses the token tree (result of macro expansion) to a Pattern | 92 | /// Parses the token tree (result of macro expansion) to a Pattern |
73 | pub fn token_tree_to_pat(tt: &tt::Subtree) -> Result<Parse<ast::Pat>, ExpandError> { | 93 | pub fn token_tree_to_pat(tt: &tt::Subtree) -> Result<Parse<ast::Pat>, ExpandError> { |
74 | let parse = token_tree_to_syntax_node(tt, ra_parser::parse_pat)?; | 94 | let parse = fragment_to_syntax_node(tt, Pattern)?; |
75 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 95 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) |
76 | } | 96 | } |
77 | 97 | ||
78 | /// Parses the token tree (result of macro expansion) to a Type | 98 | /// Parses the token tree (result of macro expansion) to a Type |
79 | pub fn token_tree_to_ty(tt: &tt::Subtree) -> Result<Parse<ast::TypeRef>, ExpandError> { | 99 | pub fn token_tree_to_ty(tt: &tt::Subtree) -> Result<Parse<ast::TypeRef>, ExpandError> { |
80 | let parse = token_tree_to_syntax_node(tt, ra_parser::parse_ty)?; | 100 | let parse = fragment_to_syntax_node(tt, Type)?; |
81 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 101 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) |
82 | } | 102 | } |
83 | 103 | ||
84 | /// Parses the token tree (result of macro expansion) as a sequence of stmts | 104 | /// Parses the token tree (result of macro expansion) as a sequence of stmts |
85 | pub fn token_tree_to_macro_stmts(tt: &tt::Subtree) -> Result<Parse<ast::MacroStmts>, ExpandError> { | 105 | pub fn token_tree_to_macro_stmts(tt: &tt::Subtree) -> Result<Parse<ast::MacroStmts>, ExpandError> { |
86 | let parse = token_tree_to_syntax_node(tt, ra_parser::parse_macro_stmts)?; | 106 | let parse = fragment_to_syntax_node(tt, Statements)?; |
87 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 107 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) |
88 | } | 108 | } |
89 | 109 | ||
90 | /// Parses the token tree (result of macro expansion) as a sequence of items | 110 | /// Parses the token tree (result of macro expansion) as a sequence of items |
91 | pub fn token_tree_to_macro_items(tt: &tt::Subtree) -> Result<Parse<ast::MacroItems>, ExpandError> { | 111 | pub fn token_tree_to_macro_items(tt: &tt::Subtree) -> Result<Parse<ast::MacroItems>, ExpandError> { |
92 | let parse = token_tree_to_syntax_node(tt, ra_parser::parse_macro_items)?; | 112 | let parse = fragment_to_syntax_node(tt, Items)?; |
93 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 113 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) |
94 | } | 114 | } |
95 | 115 | ||
diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs index 468276397..a69c006c7 100644 --- a/crates/ra_mbe/src/tt_cursor.rs +++ b/crates/ra_mbe/src/tt_cursor.rs | |||
@@ -1,5 +1,6 @@ | |||
1 | use crate::subtree_parser::Parser; | 1 | use crate::{subtree_parser::Parser, ParseError}; |
2 | use crate::ParseError; | 2 | |
3 | use ra_parser::FragmentKind; | ||
3 | use smallvec::{smallvec, SmallVec}; | 4 | use smallvec::{smallvec, SmallVec}; |
4 | 5 | ||
5 | #[derive(Debug, Clone)] | 6 | #[derive(Debug, Clone)] |
@@ -98,44 +99,9 @@ impl<'a> TtCursor<'a> { | |||
98 | }) | 99 | }) |
99 | } | 100 | } |
100 | 101 | ||
101 | pub(crate) fn eat_path(&mut self) -> Option<tt::TokenTree> { | 102 | pub(crate) fn eat_fragment(&mut self, fragment_kind: FragmentKind) -> Option<tt::TokenTree> { |
102 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
103 | parser.parse_path() | ||
104 | } | ||
105 | |||
106 | pub(crate) fn eat_expr(&mut self) -> Option<tt::TokenTree> { | ||
107 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
108 | parser.parse_expr() | ||
109 | } | ||
110 | |||
111 | pub(crate) fn eat_ty(&mut self) -> Option<tt::TokenTree> { | ||
112 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
113 | parser.parse_ty() | ||
114 | } | ||
115 | |||
116 | pub(crate) fn eat_pat(&mut self) -> Option<tt::TokenTree> { | ||
117 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
118 | parser.parse_pat() | ||
119 | } | ||
120 | |||
121 | pub(crate) fn eat_stmt(&mut self) -> Option<tt::TokenTree> { | ||
122 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
123 | parser.parse_stmt() | ||
124 | } | ||
125 | |||
126 | pub(crate) fn eat_block(&mut self) -> Option<tt::TokenTree> { | ||
127 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
128 | parser.parse_block() | ||
129 | } | ||
130 | |||
131 | pub(crate) fn eat_meta(&mut self) -> Option<tt::TokenTree> { | ||
132 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
133 | parser.parse_meta() | ||
134 | } | ||
135 | |||
136 | pub(crate) fn eat_item(&mut self) -> Option<tt::TokenTree> { | ||
137 | let parser = Parser::new(&mut self.pos, self.subtree); | 103 | let parser = Parser::new(&mut self.pos, self.subtree); |
138 | parser.parse_item() | 104 | parser.parse_fragment(fragment_kind) |
139 | } | 105 | } |
140 | 106 | ||
141 | pub(crate) fn eat_lifetime(&mut self) -> Option<tt::TokenTree> { | 107 | pub(crate) fn eat_lifetime(&mut self) -> Option<tt::TokenTree> { |
@@ -154,7 +120,7 @@ impl<'a> TtCursor<'a> { | |||
154 | let old_pos = self.pos; | 120 | let old_pos = self.pos; |
155 | let parser = Parser::new(&mut self.pos, self.subtree); | 121 | let parser = Parser::new(&mut self.pos, self.subtree); |
156 | 122 | ||
157 | let res = parser.parse_vis(); | 123 | let res = parser.parse_fragment(FragmentKind::Visibility); |
158 | if res.is_none() { | 124 | if res.is_none() { |
159 | self.pos = old_pos; | 125 | self.pos = old_pos; |
160 | } | 126 | } |
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index dee3a229d..d0f0dd4ac 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs | |||
@@ -49,98 +49,93 @@ pub(crate) fn root(p: &mut Parser) { | |||
49 | m.complete(p, SOURCE_FILE); | 49 | m.complete(p, SOURCE_FILE); |
50 | } | 50 | } |
51 | 51 | ||
52 | pub(crate) fn macro_items(p: &mut Parser) { | 52 | /// Various pieces of syntax that can be parsed by macros by example |
53 | let m = p.start(); | 53 | pub(crate) mod fragments { |
54 | items::mod_contents(p, false); | 54 | use super::*; |
55 | m.complete(p, MACRO_ITEMS); | ||
56 | } | ||
57 | 55 | ||
58 | pub(crate) fn macro_stmts(p: &mut Parser) { | 56 | pub(crate) use super::{ |
59 | let m = p.start(); | 57 | expressions::block, paths::type_path as path, patterns::pattern, types::type_, |
60 | 58 | }; | |
61 | while !p.at(EOF) { | ||
62 | if p.current() == T![;] { | ||
63 | p.bump(); | ||
64 | continue; | ||
65 | } | ||
66 | 59 | ||
67 | expressions::stmt(p, expressions::StmtWithSemi::Optional); | 60 | pub(crate) fn expr(p: &mut Parser) { |
61 | let _ = expressions::expr(p); | ||
68 | } | 62 | } |
69 | 63 | ||
70 | m.complete(p, MACRO_STMTS); | 64 | pub(crate) fn stmt(p: &mut Parser) { |
71 | } | 65 | expressions::stmt(p, expressions::StmtWithSemi::No) |
72 | 66 | } | |
73 | pub(crate) fn path(p: &mut Parser) { | ||
74 | paths::type_path(p); | ||
75 | } | ||
76 | |||
77 | pub(crate) fn expr(p: &mut Parser) { | ||
78 | expressions::expr(p); | ||
79 | } | ||
80 | 67 | ||
81 | pub(crate) fn type_(p: &mut Parser) { | 68 | pub(crate) fn opt_visibility(p: &mut Parser) { |
82 | types::type_(p) | 69 | let _ = super::opt_visibility(p); |
83 | } | 70 | } |
84 | 71 | ||
85 | pub(crate) fn pattern(p: &mut Parser) { | 72 | // Parse a meta item , which excluded [], e.g : #[ MetaItem ] |
86 | patterns::pattern(p) | 73 | pub(crate) fn meta_item(p: &mut Parser) { |
87 | } | 74 | fn is_delimiter(p: &mut Parser) -> bool { |
75 | match p.current() { | ||
76 | T!['{'] | T!['('] | T!['['] => true, | ||
77 | _ => false, | ||
78 | } | ||
79 | } | ||
88 | 80 | ||
89 | pub(crate) fn stmt(p: &mut Parser, with_semi: bool) { | 81 | if is_delimiter(p) { |
90 | let with_semi = | 82 | items::token_tree(p); |
91 | if with_semi { expressions::StmtWithSemi::Yes } else { expressions::StmtWithSemi::No }; | 83 | return; |
84 | } | ||
92 | 85 | ||
93 | expressions::stmt(p, with_semi) | 86 | let m = p.start(); |
94 | } | 87 | while !p.at(EOF) { |
88 | if is_delimiter(p) { | ||
89 | items::token_tree(p); | ||
90 | break; | ||
91 | } else { | ||
92 | // https://doc.rust-lang.org/reference/attributes.html | ||
93 | // https://doc.rust-lang.org/reference/paths.html#simple-paths | ||
94 | // The start of an meta must be a simple path | ||
95 | match p.current() { | ||
96 | IDENT | T![::] | T![super] | T![self] | T![crate] => p.bump(), | ||
97 | T![=] => { | ||
98 | p.bump(); | ||
99 | match p.current() { | ||
100 | c if c.is_literal() => p.bump(), | ||
101 | T![true] | T![false] => p.bump(), | ||
102 | _ => {} | ||
103 | } | ||
104 | break; | ||
105 | } | ||
106 | _ => break, | ||
107 | } | ||
108 | } | ||
109 | } | ||
95 | 110 | ||
96 | pub(crate) fn block(p: &mut Parser) { | 111 | m.complete(p, TOKEN_TREE); |
97 | expressions::block(p); | 112 | } |
98 | } | ||
99 | 113 | ||
100 | // Parse a meta item , which excluded [], e.g : #[ MetaItem ] | 114 | pub(crate) fn item(p: &mut Parser) { |
101 | pub(crate) fn meta_item(p: &mut Parser) { | 115 | items::item_or_macro(p, true, items::ItemFlavor::Mod) |
102 | fn is_delimiter(p: &mut Parser) -> bool { | ||
103 | match p.current() { | ||
104 | T!['{'] | T!['('] | T!['['] => true, | ||
105 | _ => false, | ||
106 | } | ||
107 | } | 116 | } |
108 | 117 | ||
109 | if is_delimiter(p) { | 118 | pub(crate) fn macro_items(p: &mut Parser) { |
110 | items::token_tree(p); | 119 | let m = p.start(); |
111 | return; | 120 | items::mod_contents(p, false); |
121 | m.complete(p, MACRO_ITEMS); | ||
112 | } | 122 | } |
113 | 123 | ||
114 | let m = p.start(); | 124 | pub(crate) fn macro_stmts(p: &mut Parser) { |
115 | while !p.at(EOF) { | 125 | let m = p.start(); |
116 | if is_delimiter(p) { | 126 | |
117 | items::token_tree(p); | 127 | while !p.at(EOF) { |
118 | break; | 128 | if p.current() == T![;] { |
119 | } else { | 129 | p.bump(); |
120 | // https://doc.rust-lang.org/reference/attributes.html | 130 | continue; |
121 | // https://doc.rust-lang.org/reference/paths.html#simple-paths | ||
122 | // The start of an meta must be a simple path | ||
123 | match p.current() { | ||
124 | IDENT | T![::] | T![super] | T![self] | T![crate] => p.bump(), | ||
125 | T![=] => { | ||
126 | p.bump(); | ||
127 | match p.current() { | ||
128 | c if c.is_literal() => p.bump(), | ||
129 | T![true] | T![false] => p.bump(), | ||
130 | _ => {} | ||
131 | } | ||
132 | break; | ||
133 | } | ||
134 | _ => break, | ||
135 | } | 131 | } |
132 | |||
133 | expressions::stmt(p, expressions::StmtWithSemi::Optional); | ||
136 | } | 134 | } |
137 | } | ||
138 | 135 | ||
139 | m.complete(p, TOKEN_TREE); | 136 | m.complete(p, MACRO_STMTS); |
140 | } | 137 | } |
141 | 138 | ||
142 | pub(crate) fn item(p: &mut Parser) { | ||
143 | items::item_or_macro(p, true, items::ItemFlavor::Mod) | ||
144 | } | 139 | } |
145 | 140 | ||
146 | pub(crate) fn reparser( | 141 | pub(crate) fn reparser( |
@@ -180,7 +175,7 @@ impl BlockLike { | |||
180 | } | 175 | } |
181 | } | 176 | } |
182 | 177 | ||
183 | pub(crate) fn opt_visibility(p: &mut Parser) -> bool { | 178 | fn opt_visibility(p: &mut Parser) -> bool { |
184 | match p.current() { | 179 | match p.current() { |
185 | T![pub] => { | 180 | T![pub] => { |
186 | let m = p.start(); | 181 | let m = p.start(); |
diff --git a/crates/ra_parser/src/grammar/paths.rs b/crates/ra_parser/src/grammar/paths.rs index 07eb53b0c..28c35a67d 100644 --- a/crates/ra_parser/src/grammar/paths.rs +++ b/crates/ra_parser/src/grammar/paths.rs | |||
@@ -18,7 +18,7 @@ pub(super) fn use_path(p: &mut Parser) { | |||
18 | path(p, Mode::Use) | 18 | path(p, Mode::Use) |
19 | } | 19 | } |
20 | 20 | ||
21 | pub(super) fn type_path(p: &mut Parser) { | 21 | pub(crate) fn type_path(p: &mut Parser) { |
22 | path(p, Mode::Type) | 22 | path(p, Mode::Type) |
23 | } | 23 | } |
24 | 24 | ||
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs index eae70ab85..32cde7de6 100644 --- a/crates/ra_parser/src/grammar/patterns.rs +++ b/crates/ra_parser/src/grammar/patterns.rs | |||
@@ -4,7 +4,7 @@ pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST | |||
4 | .union(paths::PATH_FIRST) | 4 | .union(paths::PATH_FIRST) |
5 | .union(token_set![BOX_KW, REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE, MINUS]); | 5 | .union(token_set![BOX_KW, REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE, MINUS]); |
6 | 6 | ||
7 | pub(super) fn pattern(p: &mut Parser) { | 7 | pub(crate) fn pattern(p: &mut Parser) { |
8 | pattern_r(p, PAT_RECOVERY_SET); | 8 | pattern_r(p, PAT_RECOVERY_SET); |
9 | } | 9 | } |
10 | 10 | ||
diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs index 29d173305..9e321b2a6 100644 --- a/crates/ra_parser/src/grammar/types.rs +++ b/crates/ra_parser/src/grammar/types.rs | |||
@@ -7,7 +7,7 @@ pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(token_set![ | |||
7 | 7 | ||
8 | const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA]; | 8 | const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA]; |
9 | 9 | ||
10 | pub(super) fn type_(p: &mut Parser) { | 10 | pub(crate) fn type_(p: &mut Parser) { |
11 | type_with_bounds_cond(p, true); | 11 | type_with_bounds_cond(p, true); |
12 | } | 12 | } |
13 | 13 | ||
diff --git a/crates/ra_parser/src/lib.rs b/crates/ra_parser/src/lib.rs index 3d88be642..45241e566 100644 --- a/crates/ra_parser/src/lib.rs +++ b/crates/ra_parser/src/lib.rs | |||
@@ -83,62 +83,42 @@ pub fn parse(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) { | |||
83 | parse_from_tokens(token_source, tree_sink, grammar::root); | 83 | parse_from_tokens(token_source, tree_sink, grammar::root); |
84 | } | 84 | } |
85 | 85 | ||
86 | /// Parse given tokens into the given sink as a path | 86 | pub enum FragmentKind { |
87 | pub fn parse_path(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) { | 87 | Path, |
88 | parse_from_tokens(token_source, tree_sink, grammar::path); | 88 | Expr, |
89 | } | 89 | Statement, |
90 | 90 | Type, | |
91 | /// Parse given tokens into the given sink as a expression | 91 | Pattern, |
92 | pub fn parse_expr(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) { | 92 | Item, |
93 | parse_from_tokens(token_source, tree_sink, grammar::expr); | 93 | Block, |
94 | } | 94 | Visibility, |
95 | 95 | MetaItem, | |
96 | /// Parse given tokens into the given sink as a ty | 96 | |
97 | pub fn parse_ty(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) { | 97 | // These kinds are used when parsing the result of expansion |
98 | parse_from_tokens(token_source, tree_sink, grammar::type_); | 98 | // FIXME: use separate fragment kinds for macro inputs and outputs? |
99 | } | 99 | Items, |
100 | 100 | Statements, | |
101 | /// Parse given tokens into the given sink as a pattern | 101 | } |
102 | pub fn parse_pat(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) { | 102 | |
103 | parse_from_tokens(token_source, tree_sink, grammar::pattern); | 103 | pub fn parse_fragment( |
104 | } | ||
105 | |||
106 | /// Parse given tokens into the given sink as a statement | ||
107 | pub fn parse_stmt( | ||
108 | token_source: &mut dyn TokenSource, | 104 | token_source: &mut dyn TokenSource, |
109 | tree_sink: &mut dyn TreeSink, | 105 | tree_sink: &mut dyn TreeSink, |
110 | with_semi: bool, | 106 | fragment_kind: FragmentKind, |
111 | ) { | 107 | ) { |
112 | parse_from_tokens(token_source, tree_sink, |p| grammar::stmt(p, with_semi)); | 108 | let parser: fn(&'_ mut parser::Parser) = match fragment_kind { |
113 | } | 109 | FragmentKind::Path => grammar::fragments::path, |
114 | 110 | FragmentKind::Expr => grammar::fragments::expr, | |
115 | /// Parse given tokens into the given sink as a block | 111 | FragmentKind::Type => grammar::fragments::type_, |
116 | pub fn parse_block(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) { | 112 | FragmentKind::Pattern => grammar::fragments::pattern, |
117 | parse_from_tokens(token_source, tree_sink, grammar::block); | 113 | FragmentKind::Item => grammar::fragments::item, |
118 | } | 114 | FragmentKind::Block => grammar::fragments::block, |
119 | 115 | FragmentKind::Visibility => grammar::fragments::opt_visibility, | |
120 | pub fn parse_meta(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) { | 116 | FragmentKind::MetaItem => grammar::fragments::meta_item, |
121 | parse_from_tokens(token_source, tree_sink, grammar::meta_item); | 117 | FragmentKind::Statement => grammar::fragments::stmt, |
122 | } | 118 | FragmentKind::Items => grammar::fragments::macro_items, |
123 | 119 | FragmentKind::Statements => grammar::fragments::macro_stmts, | |
124 | /// Parse given tokens into the given sink as an item | 120 | }; |
125 | pub fn parse_item(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) { | 121 | parse_from_tokens(token_source, tree_sink, parser) |
126 | parse_from_tokens(token_source, tree_sink, grammar::item); | ||
127 | } | ||
128 | |||
129 | /// Parse given tokens into the given sink as an visibility qualifier | ||
130 | pub fn parse_vis(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) { | ||
131 | parse_from_tokens(token_source, tree_sink, |p| { | ||
132 | grammar::opt_visibility(p); | ||
133 | }); | ||
134 | } | ||
135 | |||
136 | pub fn parse_macro_items(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) { | ||
137 | parse_from_tokens(token_source, tree_sink, grammar::macro_items); | ||
138 | } | ||
139 | |||
140 | pub fn parse_macro_stmts(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) { | ||
141 | parse_from_tokens(token_source, tree_sink, grammar::macro_stmts); | ||
142 | } | 122 | } |
143 | 123 | ||
144 | /// A parsing function for a specific braced-block. | 124 | /// A parsing function for a specific braced-block. |