about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_def/src/attr.rs3
-rw-r--r--crates/hir_expand/src/builtin_derive_macro.rs2
-rw-r--r--crates/hir_expand/src/db.rs10
-rw-r--r--crates/hir_expand/src/eager.rs2
-rw-r--r--crates/mbe/src/lib.rs2
-rw-r--r--crates/mbe/src/syntax_bridge.rs8
-rw-r--r--crates/parser/src/grammar.rs56
-rw-r--r--crates/parser/src/lib.rs61
8 files changed, 94 insertions, 50 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 36e46a103c1..383ad7f0c83 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -714,8 +714,7 @@ impl Attr {
         hygiene: &Hygiene,
         id: AttrId,
     ) -> Option<Attr> {
-        let (parse, _) =
-            mbe::token_tree_to_syntax_node(tt, mbe::ParserEntryPoint::MetaItem).ok()?;
+        let (parse, _) = mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MetaItem).ok()?;
         let ast = ast::Meta::cast(parse.syntax_node())?;
 
         Self::from_src(db, ast, hygiene, id)
diff --git a/crates/hir_expand/src/builtin_derive_macro.rs b/crates/hir_expand/src/builtin_derive_macro.rs
index c20dae8e6f7..c1542f48f0e 100644
--- a/crates/hir_expand/src/builtin_derive_macro.rs
+++ b/crates/hir_expand/src/builtin_derive_macro.rs
@@ -72,7 +72,7 @@ struct BasicAdtInfo {
 }
 
 fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, mbe::ExpandError> {
-    let (parsed, token_map) = mbe::token_tree_to_syntax_node(tt, mbe::ParserEntryPoint::Items)?; // FragmentKind::Items doesn't parse attrs?
+    let (parsed, token_map) = mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MacroItems)?; // FragmentKind::Items doesn't parse attrs?
     let macro_items = ast::MacroItems::cast(parsed.syntax_node()).ok_or_else(|| {
         debug!("derive node didn't parse");
         mbe::ExpandError::UnexpectedToken
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index 747a19a5092..3369e3e5fed 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -497,11 +497,11 @@ fn token_tree_to_syntax_node(
     expand_to: ExpandTo,
 ) -> Result<(Parse<SyntaxNode>, mbe::TokenMap), ExpandError> {
     let entry_point = match expand_to {
-        ExpandTo::Statements => mbe::ParserEntryPoint::Statements,
-        ExpandTo::Items => mbe::ParserEntryPoint::Items,
-        ExpandTo::Pattern => mbe::ParserEntryPoint::Pattern,
-        ExpandTo::Type => mbe::ParserEntryPoint::Type,
-        ExpandTo::Expr => mbe::ParserEntryPoint::Expr,
+        ExpandTo::Statements => mbe::TopEntryPoint::MacroStmts,
+        ExpandTo::Items => mbe::TopEntryPoint::MacroItems,
+        ExpandTo::Pattern => mbe::TopEntryPoint::Pattern,
+        ExpandTo::Type => mbe::TopEntryPoint::Type,
+        ExpandTo::Expr => mbe::TopEntryPoint::Expr,
     };
     mbe::token_tree_to_syntax_node(tt, entry_point)
 }
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index ea57c2c4101..1d29ad26307 100644
--- a/crates/hir_expand/src/eager.rs
+++ b/crates/hir_expand/src/eager.rs
@@ -131,7 +131,7 @@ pub fn expand_eager_macro(
     let arg_file_id = arg_id;
 
     let parsed_args = diagnostic_sink
-        .result(mbe::token_tree_to_syntax_node(&parsed_args, mbe::ParserEntryPoint::Expr))?
+        .result(mbe::token_tree_to_syntax_node(&parsed_args, mbe::TopEntryPoint::Expr))?
         .0;
     let result = eager_macro_recur(
         db,
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs
index 5e14a3fb590..62e7509eb37 100644
--- a/crates/mbe/src/lib.rs
+++ b/crates/mbe/src/lib.rs
@@ -24,7 +24,7 @@ use crate::{
 };
 
 // FIXME: we probably should re-think  `token_tree_to_syntax_node` interfaces
-pub use ::parser::ParserEntryPoint;
+pub use ::parser::TopEntryPoint;
 pub use tt::{Delimiter, DelimiterKind, Punct};
 
 #[derive(Debug, PartialEq, Eq, Clone)]
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs
index 896e33663ef..8bdc5e6e946 100644
--- a/crates/mbe/src/syntax_bridge.rs
+++ b/crates/mbe/src/syntax_bridge.rs
@@ -9,9 +9,7 @@ use syntax::{
 };
 use tt::buffer::{Cursor, TokenBuffer};
 
-use crate::{
-    to_parser_input::to_parser_input, tt_iter::TtIter, ExpandError, ParserEntryPoint, TokenMap,
-};
+use crate::{to_parser_input::to_parser_input, tt_iter::TtIter, ExpandError, TokenMap};
 
 /// Convert the syntax node to a `TokenTree` (what macro
 /// will consume).
@@ -46,7 +44,7 @@ pub fn syntax_node_to_token_tree_censored(
 
 pub fn token_tree_to_syntax_node(
     tt: &tt::Subtree,
-    entry_point: ParserEntryPoint,
+    entry_point: parser::TopEntryPoint,
 ) -> Result<(Parse<SyntaxNode>, TokenMap), ExpandError> {
     let buffer = match tt {
         tt::Subtree { delimiter: None, token_trees } => {
@@ -55,7 +53,7 @@ pub fn token_tree_to_syntax_node(
         _ => TokenBuffer::from_subtree(tt),
     };
     let parser_input = to_parser_input(&buffer);
-    let parser_output = parser::parse(&parser_input, entry_point);
+    let parser_output = entry_point.parse(&parser_input);
     let mut tree_sink = TtTreeSink::new(buffer.begin());
     for event in parser_output.iter() {
         match event {
diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs
index 0e663b9ac01..5fbeca44323 100644
--- a/crates/parser/src/grammar.rs
+++ b/crates/parser/src/grammar.rs
@@ -83,41 +83,45 @@ pub(crate) mod entry {
             attributes::meta(p);
         }
     }
-}
-
-pub(crate) mod entry_points {
-    use super::*;
 
-    pub(crate) fn source_file(p: &mut Parser) {
-        let m = p.start();
-        p.eat(SHEBANG);
-        items::mod_contents(p, false);
-        m.complete(p, SOURCE_FILE);
-    }
+    pub(crate) mod top {
+        use super::*;
 
-    pub(crate) fn stmt_optional_semi(p: &mut Parser) {
-        expressions::stmt(p, expressions::StmtWithSemi::Optional, false);
-    }
+        pub(crate) fn source_file(p: &mut Parser) {
+            let m = p.start();
+            p.eat(SHEBANG);
+            items::mod_contents(p, false);
+            m.complete(p, SOURCE_FILE);
+        }
 
-    pub(crate) fn macro_items(p: &mut Parser) {
-        let m = p.start();
-        items::mod_contents(p, false);
-        m.complete(p, MACRO_ITEMS);
-    }
+        pub(crate) fn macro_stmts(p: &mut Parser) {
+            let m = p.start();
 
-    pub(crate) fn macro_stmts(p: &mut Parser) {
-        let m = p.start();
+            while !p.at(EOF) {
+                if p.at(T![;]) {
+                    p.bump(T![;]);
+                    continue;
+                }
 
-        while !p.at(EOF) {
-            if p.at(T![;]) {
-                p.bump(T![;]);
-                continue;
+                expressions::stmt(p, expressions::StmtWithSemi::Optional, true);
             }
 
-            expressions::stmt(p, expressions::StmtWithSemi::Optional, true);
+            m.complete(p, MACRO_STMTS);
         }
 
-        m.complete(p, MACRO_STMTS);
+        pub(crate) fn macro_items(p: &mut Parser) {
+            let m = p.start();
+            items::mod_contents(p, false);
+            m.complete(p, MACRO_ITEMS);
+        }
+    }
+}
+
+pub(crate) mod entry_points {
+    use super::*;
+
+    pub(crate) fn stmt_optional_semi(p: &mut Parser) {
+        expressions::stmt(p, expressions::StmtWithSemi::Optional, false);
     }
 
     pub(crate) fn attr(p: &mut Parser) {
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index 9039985da2b..23ce233dfd4 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -41,7 +41,7 @@ pub use crate::{
     syntax_kind::SyntaxKind,
 };
 
-/// Parse a syntactic construct at the *start* of the input.
+/// Parse a prefix of the input as a given syntactic construct.
 ///
 /// This is used by macro-by-example parser to implement things like `$i:item`
 /// and the naming of variants follows the naming of macro fragments.
@@ -83,13 +83,61 @@ impl PrefixEntryPoint {
     }
 }
 
+/// Parse the whole of the input as a given syntactic construct.
+///
+/// This covers two main use-cases:
+///
+///   * Parsing a Rust file.
+///   * Parsing a result of macro expansion.
+///
+/// That is, for something like
+///
+/// ```
+/// quick_check! {
+///    fn prop() {}
+/// }
+/// ```
+///
+/// the input to the macro will be parsed with [`PrefixEntryPoint::Item`], and
+/// the result will be [`TopEntryPoint::Items`].
+///
+/// This *should* (but currently doesn't) guarantee that all input is consumed.
+#[derive(Debug)]
+pub enum TopEntryPoint {
+    SourceFile,
+    MacroStmts,
+    MacroItems,
+    Pattern,
+    Type,
+    Expr,
+    MetaItem,
+}
+
+impl TopEntryPoint {
+    pub fn parse(&self, input: &Input) -> Output {
+        let entry_point: fn(&'_ mut parser::Parser) = match self {
+            TopEntryPoint::SourceFile => grammar::entry::top::source_file,
+            TopEntryPoint::MacroStmts => grammar::entry::top::macro_stmts,
+            TopEntryPoint::MacroItems => grammar::entry::top::macro_items,
+            // FIXME
+            TopEntryPoint::Pattern => grammar::entry::prefix::pat,
+            TopEntryPoint::Type => grammar::entry::prefix::ty,
+            TopEntryPoint::Expr => grammar::entry::prefix::expr,
+            TopEntryPoint::MetaItem => grammar::entry::prefix::meta_item,
+        };
+        let mut p = parser::Parser::new(input);
+        entry_point(&mut p);
+        let events = p.finish();
+        event::process(events)
+    }
+}
+
 /// rust-analyzer parser allows you to choose one of the possible entry points.
 ///
 /// The primary consumer of this API are declarative macros, `$x:expr` matchers
 /// are implemented by calling into the parser with non-standard entry point.
 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
 pub enum ParserEntryPoint {
-    SourceFile,
     Path,
     Expr,
     StatementOptionalSemi,
@@ -97,14 +145,12 @@ pub enum ParserEntryPoint {
     Pattern,
     Item,
     MetaItem,
-    Items,
-    Statements,
     Attr,
 }
 
 /// Parse given tokens into the given sink as a rust file.
-pub fn parse_source_file(inp: &Input) -> Output {
-    parse(inp, ParserEntryPoint::SourceFile)
+pub fn parse_source_file(input: &Input) -> Output {
+    TopEntryPoint::SourceFile.parse(input)
 }
 
 /// Parses the given [`Input`] into [`Output`] assuming that the top-level
@@ -117,7 +163,6 @@ pub fn parse_source_file(inp: &Input) -> Output {
 /// indices between the four stages.
 pub fn parse(inp: &Input, entry_point: ParserEntryPoint) -> Output {
     let entry_point: fn(&'_ mut parser::Parser) = match entry_point {
-        ParserEntryPoint::SourceFile => grammar::entry_points::source_file,
         ParserEntryPoint::Path => grammar::entry::prefix::path,
         ParserEntryPoint::Expr => grammar::entry::prefix::expr,
         ParserEntryPoint::Type => grammar::entry::prefix::ty,
@@ -125,8 +170,6 @@ pub fn parse(inp: &Input, entry_point: ParserEntryPoint) -> Output {
         ParserEntryPoint::Item => grammar::entry::prefix::item,
         ParserEntryPoint::MetaItem => grammar::entry::prefix::meta_item,
         ParserEntryPoint::StatementOptionalSemi => grammar::entry_points::stmt_optional_semi,
-        ParserEntryPoint::Items => grammar::entry_points::macro_items,
-        ParserEntryPoint::Statements => grammar::entry_points::macro_stmts,
         ParserEntryPoint::Attr => grammar::entry_points::attr,
     };