Conversation
Implements error recovery inspired by Chumsky's recovery system in Rust, addressing GitHub issue alecthomas#342. New features: - RecoveryStrategy interface with multiple implementations: - SkipUntil/SkipPast: classic panic-mode recovery - SkipThenRetryUntil: skip and retry parsing - NestedDelimiters: balanced delimiter recovery - TokenSyncStrategy: sync on token types - CompositeStrategy: try multiple strategies in order - RecoveryError type for multi-error reporting - ParseOptions: Recover(strategies...) and MaxRecoveryErrors(n) Integration points: - parseContext with tryRecover(), recoveryEnabled(), addRecoveryError() - Recovery hooks in strct.Parse and group.Parse (nodes.go) - Error aggregation in parser.go The implementation allows parsers to continue after errors, collecting multiple errors and producing partial ASTs - useful for IDE integration, linters, and comprehensive error messages. Includes comprehensive test coverage (100% on new code) and example at _examples/recovery/. Amp-Thread-ID: https://ampcode.com/threads/T-b95d5ac9-6023-4947-a477-53364956f203 Co-authored-by: Amp <amp@ampcode.com>
Extends the error recovery system with Chumsky-inspired features: Per-Node Recovery (via struct tags): - Add 'recover' struct tag for per-field recovery strategies - Syntax: \`parser:"@Ident" recover:"skip_until(;)"\` - Supports: skip_until(), skip_past(), nested(), retry_until() - Multiple strategies via pipe: \`recover:"nested((,))|skip_until(;)"\` - Labels for error messages: \`recover:"label:expression|skip_until(;)"\` Recovery Metadata Fields: - Recovered bool - set to true when struct was recovered - RecoveredSpan lexer.Position - position where recovery started - Auto-injected like Pos/EndPos fields Implementation: - recoveryNode wrapper applies recovery to any node - Handles both errors AND 'no match' cases (nil, nil) - Creates meaningful error messages for recovery reporting - Updated visit.go, ebnf.go for recoveryNode support This brings participle closer to Chumsky's recovery capabilities, enabling fine-grained recovery control per grammar rule. Amp-Thread-ID: https://ampcode.com/threads/T-b95d5ac9-6023-4947-a477-53364956f203 Co-authored-by: Amp <amp@ampcode.com>
alecthomas
left a comment
There was a problem hiding this comment.
This is awesome! I'll try to take a comprehensive look on the weekend.
alecthomas
left a comment
There was a problem hiding this comment.
Apologies for the delay, this is a great idea!
I've left a few comments, but I'll do a full pass in a bit.
| if strings.HasPrefix(tag, "label:") { | ||
| parts := strings.SplitN(tag[6:], "|", 2) | ||
| config.label = strings.TrimSpace(parts[0]) | ||
| if len(parts) > 1 { | ||
| tag = parts[1] | ||
| } else { | ||
| return config, nil | ||
| } | ||
| } |
There was a problem hiding this comment.
This seems redundant given that the strategy loop also checks for the label?
|
|
||
| // recoveryNode wraps another node with recovery configuration. | ||
| // This allows any node to have per-node recovery without modifying all node types. | ||
| type recoveryNode struct { |
There was a problem hiding this comment.
There are a few locations where the code type switches on the node type that will need to be updated. You're probably going to have to make this public, and add a method that "unwraps" the underlying node for introspection.
| // ============================================================================= | ||
| // Field Recovery Tag Extraction | ||
| // ============================================================================= |
There was a problem hiding this comment.
Can you get rid of these section markers please?
|
Apologies for the delay BTW, I've been absolutely swamped at work. |
Implements error recovery inspired by Chumsky's recovery system in Rust, addressing GitHub issue #342.
Features:
The implementation allows parsers to continue after errors, collecting
multiple errors and producing partial ASTs - useful for IDE integration,
linters, and comprehensive error messages.
Includes comprehensive test coverage (100% on new code) and example at
_examples/recovery/.