Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/parser/src/lib.rs')
-rw-r--r--crates/parser/src/lib.rs112
1 files changed, 65 insertions, 47 deletions
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index 72d529d6cf..cff4ca4ba2 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -41,48 +41,6 @@ pub use crate::{
syntax_kind::SyntaxKind,
};
-/// 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.
-///
-/// Note that this is generally non-optional -- the result is intentionally not
-/// `Option<Output>`. The way MBE work, by the time we *try* to parse `$e:expr`
-/// we already commit to expression. In other words, this API by design can't be
-/// used to implement "rollback and try another alternative" logic.
-#[derive(Debug)]
-pub enum PrefixEntryPoint {
- Vis,
- Block,
- Stmt,
- Pat,
- Ty,
- Expr,
- Path,
- Item,
- MetaItem,
-}
-
-impl PrefixEntryPoint {
- pub fn parse(&self, input: &Input) -> Output {
- let entry_point: fn(&'_ mut parser::Parser) = match self {
- PrefixEntryPoint::Vis => grammar::entry::prefix::vis,
- PrefixEntryPoint::Block => grammar::entry::prefix::block,
- PrefixEntryPoint::Stmt => grammar::entry::prefix::stmt,
- PrefixEntryPoint::Pat => grammar::entry::prefix::pat,
- PrefixEntryPoint::Ty => grammar::entry::prefix::ty,
- PrefixEntryPoint::Expr => grammar::entry::prefix::expr,
- PrefixEntryPoint::Path => grammar::entry::prefix::path,
- PrefixEntryPoint::Item => grammar::entry::prefix::item,
- PrefixEntryPoint::MetaItem => grammar::entry::prefix::meta_item,
- };
- let mut p = parser::Parser::new(input);
- entry_point(&mut p);
- let events = p.finish();
- event::process(events)
- }
-}
-
/// Parse the whole of the input as a given syntactic construct.
///
/// This covers two main use-cases:
@@ -99,9 +57,11 @@ impl PrefixEntryPoint {
/// ```
///
/// the input to the macro will be parsed with [`PrefixEntryPoint::Item`], and
-/// the result will be [`TopEntryPoint::Items`].
+/// the result will be [`TopEntryPoint::MacroItems`].
///
-/// This *should* (but currently doesn't) guarantee that all input is consumed.
+/// [`TopEntryPoint::parse`] makes a guarantee that
+/// * all input is consumed
+/// * the result is a valid tree (there's one root node)
#[derive(Debug)]
pub enum TopEntryPoint {
SourceFile,
@@ -123,9 +83,67 @@ impl TopEntryPoint {
TopEntryPoint::MacroItems => grammar::entry::top::macro_items,
TopEntryPoint::Pattern => grammar::entry::top::pattern,
TopEntryPoint::Type => grammar::entry::top::type_,
- // FIXME
- TopEntryPoint::Expr => grammar::entry::prefix::expr,
- TopEntryPoint::MetaItem => grammar::entry::prefix::meta_item,
+ TopEntryPoint::Expr => grammar::entry::top::expr,
+ TopEntryPoint::MetaItem => grammar::entry::top::meta_item,
+ };
+ let mut p = parser::Parser::new(input);
+ entry_point(&mut p);
+ let events = p.finish();
+ let res = event::process(events);
+
+ if cfg!(debug_assertions) {
+ let mut depth = 0;
+ let mut first = true;
+ for step in res.iter() {
+ assert!(depth > 0 || first);
+ first = false;
+ match step {
+ Step::Enter { .. } => depth += 1,
+ Step::Exit => depth -= 1,
+ Step::Token { .. } | Step::Error { .. } => (),
+ }
+ }
+ assert!(!first, "no tree at all");
+ }
+
+ res
+ }
+}
+
+/// 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.
+///
+/// Note that this is generally non-optional -- the result is intentionally not
+/// `Option<Output>`. The way MBE work, by the time we *try* to parse `$e:expr`
+/// we already commit to expression. In other words, this API by design can't be
+/// used to implement "rollback and try another alternative" logic.
+#[derive(Debug)]
+pub enum PrefixEntryPoint {
+ Vis,
+ Block,
+ Stmt,
+ Pat,
+ Ty,
+ Expr,
+ Path,
+ Item,
+ MetaItem,
+}
+
+impl PrefixEntryPoint {
+ pub fn parse(&self, input: &Input) -> Output {
+ let entry_point: fn(&'_ mut parser::Parser) = match self {
+ PrefixEntryPoint::Vis => grammar::entry::prefix::vis,
+ PrefixEntryPoint::Block => grammar::entry::prefix::block,
+ PrefixEntryPoint::Stmt => grammar::entry::prefix::stmt,
+ PrefixEntryPoint::Pat => grammar::entry::prefix::pat,
+ PrefixEntryPoint::Ty => grammar::entry::prefix::ty,
+ PrefixEntryPoint::Expr => grammar::entry::prefix::expr,
+ PrefixEntryPoint::Path => grammar::entry::prefix::path,
+ PrefixEntryPoint::Item => grammar::entry::prefix::item,
+ PrefixEntryPoint::MetaItem => grammar::entry::prefix::meta_item,
};
let mut p = parser::Parser::new(input);
entry_point(&mut p);