aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs122
-rw-r--r--crates/ra_mbe/src/subtree_parser.rs40
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs32
-rw-r--r--crates/ra_mbe/src/tt_cursor.rs46
-rw-r--r--crates/ra_parser/src/grammar.rs145
-rw-r--r--crates/ra_parser/src/grammar/paths.rs2
-rw-r--r--crates/ra_parser/src/grammar/patterns.rs2
-rw-r--r--crates/ra_parser/src/grammar/types.rs2
-rw-r--r--crates/ra_parser/src/lib.rs86
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
5use ra_parser::FragmentKind::*;
1use ra_syntax::SmolStr; 6use 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.
5use rustc_hash::FxHashMap; 7use rustc_hash::FxHashMap;
6use tt::TokenId; 8use 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
295fn 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)]
364struct ExpandCtx<'a> { 332struct 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 @@
1use crate::subtree_source::SubtreeTokenSource; 1use crate::subtree_source::SubtreeTokenSource;
2 2
3use ra_parser::{TokenSource, TreeSink}; 3use ra_parser::{FragmentKind, TokenSource, TreeSink};
4use ra_syntax::SyntaxKind; 4use ra_syntax::SyntaxKind;
5use tt::buffer::{Cursor, TokenBuffer}; 5use 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 @@
1use ra_parser::{ParseError, TreeSink}; 1use ra_parser::{
2 FragmentKind::{self, *},
3 ParseError, TreeSink,
4};
2use ra_syntax::{ 5use 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
69fn 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
67pub fn token_tree_to_expr(tt: &tt::Subtree) -> Result<Parse<ast::Expr>, ExpandError> { 87pub 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
73pub fn token_tree_to_pat(tt: &tt::Subtree) -> Result<Parse<ast::Pat>, ExpandError> { 93pub 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
79pub fn token_tree_to_ty(tt: &tt::Subtree) -> Result<Parse<ast::TypeRef>, ExpandError> { 99pub 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
85pub fn token_tree_to_macro_stmts(tt: &tt::Subtree) -> Result<Parse<ast::MacroStmts>, ExpandError> { 105pub 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
91pub fn token_tree_to_macro_items(tt: &tt::Subtree) -> Result<Parse<ast::MacroItems>, ExpandError> { 111pub 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 @@
1use crate::subtree_parser::Parser; 1use crate::{subtree_parser::Parser, ParseError};
2use crate::ParseError; 2
3use ra_parser::FragmentKind;
3use smallvec::{smallvec, SmallVec}; 4use 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
52pub(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(); 53pub(crate) mod fragments {
54 items::mod_contents(p, false); 54 use super::*;
55 m.complete(p, MACRO_ITEMS);
56}
57 55
58pub(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 }
73pub(crate) fn path(p: &mut Parser) {
74 paths::type_path(p);
75}
76
77pub(crate) fn expr(p: &mut Parser) {
78 expressions::expr(p);
79}
80 67
81pub(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
85pub(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
89pub(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
96pub(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) {
101pub(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
142pub(crate) fn item(p: &mut Parser) {
143 items::item_or_macro(p, true, items::ItemFlavor::Mod)
144} 139}
145 140
146pub(crate) fn reparser( 141pub(crate) fn reparser(
@@ -180,7 +175,7 @@ impl BlockLike {
180 } 175 }
181} 176}
182 177
183pub(crate) fn opt_visibility(p: &mut Parser) -> bool { 178fn 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
21pub(super) fn type_path(p: &mut Parser) { 21pub(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
7pub(super) fn pattern(p: &mut Parser) { 7pub(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
8const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA]; 8const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA];
9 9
10pub(super) fn type_(p: &mut Parser) { 10pub(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 86pub enum FragmentKind {
87pub 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,
92pub 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
97pub 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}
102pub fn parse_pat(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) { 102
103 parse_from_tokens(token_source, tree_sink, grammar::pattern); 103pub fn parse_fragment(
104}
105
106/// Parse given tokens into the given sink as a statement
107pub 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_,
116pub 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,
120pub 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 };
125pub 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
130pub 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
136pub 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
140pub 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.