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.rs | 112 |
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); |