Skip to content

Generate event-based parser output APIs alongside typed parsers - #29

Draft
tomtau with Copilot wants to merge 4 commits into
masterfrom
copilot/refactor-parsing-output-events
Draft

Generate event-based parser output APIs alongside typed parsers#29
tomtau with Copilot wants to merge 4 commits into
masterfrom
copilot/refactor-parsing-output-events

Conversation

Copilot AI commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

This introduces a generated event layer for derived parsers so parsing can be separated from output construction without replacing the existing typed API. The derive macro now exposes rule-level start/end callbacks and an owned-processor flow, while continuing to honor configurable rule module names.

  • Generated event traits

    • Emit <ParserName>EventObserver<'i> with default no-op callbacks for each matched rule:
      • on_<rule>_start(...)
      • on_<rule>_end(...)
    • Emit <ParserName>EventProcessor<'i> for owned processors with type Output and finalize(self).
  • Parser entrypoints for event-driven consumers

    • Add inherent parser methods:
      • parse_into(rule, &mut observer, input) for in-place consumers
      • parse(rule, processor, input) for owned processors finalized by the parser
    • This enables alternate outputs to be built from parser events instead of being coupled to the generated typed tree shape.
  • Event dispatch over generated rules

    • Generate rule-aware dispatch for top-level and imported grammars.
    • Preserve #[rules_mod = "..."] behavior so event-capable parsers continue to work when multiple derives coexist in one module.
  • Boundary behavior

    • Event parsing is driven from pair-producing matches; rules that do not emit pair events directly return an explicit error instructing callers to parse a containing rule instead.
  • Docs / generated API clarity

    • Document callback parameters and clarify finalize() semantics in the generated processor trait.

Example:

#[derive(Parser)]
#[grammar_inline = r#"
main = lhs - rhs
lhs = "a"
rhs = "b"
"#]
struct Parser;

#[derive(Default)]
struct Builder(Vec<&'static str>);

impl<'i> ParserEventObserver<'i> for Builder {
    fn on_main_start(&mut self, _pair: &pest3_core::token::Pair<Rule>, _input: &'i str) {
        self.0.push("main:start");
    }

    fn on_rhs_end(&mut self, _pair: &pest3_core::token::Pair<Rule>, _input: &'i str) {
        self.0.push("rhs:end");
    }
}

impl<'i> ParserEventProcessor<'i> for Builder {
    type Output = Vec<&'static str>;

    fn finalize(self) -> Self::Output {
        self.0
    }
}

let events = Parser::parse(Rule::r#main, Builder::default(), "ab")?;

Copilot AI changed the title [WIP] Refactor to separate parsing and output generation via events Generate event-based parser output APIs alongside typed parsers Apr 30, 2026
Copilot AI requested a review from tomtau April 30, 2026 00:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refactor: separate parsing and output generation via events

2 participants