Problem
The parser currently uses exceptions for error handling:
throw runtime_error("expected 'or' handler (return, fail, match, block, continue, or break) at line " + to_string(or_line));
This approach has issues:
- Control flow is hard to follow - exceptions can propagate unexpectedly
- No recovery possible - the parser stops at first error
- Inconsistent with codegen - which uses C++ exceptions but typechecker collects errors
Current State
- Lexer: Throws `runtime_error` on invalid input
- Parser: Throws `runtime_error` on syntax errors
- Typechecker: Collects errors in `TypeCheckerState.errors` vector (good pattern!)
- Codegen: Returns strings, no explicit error handling
Suggested Solution
Adopt a Result pattern similar to what typechecker does:
// Option 1: Use expected-like type
template<typename T>
using ParseResult = std::expected<T, ParseError>;
// Option 2: Follow typechecker pattern
struct ParserState {
vector<ParseError> errors;
// ...
};
// Continue parsing after errors
void report_error(ParserState& state, const string& msg, int line) {
state.errors.push_back({msg, line, state.filename});
synchronize(state); // Skip to next statement
}
This would allow:
- Collecting multiple errors in a single parse
- Better error recovery
- Consistent error handling across the compiler
Implementation Notes
- Start with parser, extend to lexer later
- Add synchronization points to recover from errors
- Follow the existing typechecker pattern
Priority
Medium - Current exception-based approach works but limits error reporting quality.
Problem
The parser currently uses exceptions for error handling:
This approach has issues:
Current State
Suggested Solution
Adopt a Result pattern similar to what typechecker does:
This would allow:
Implementation Notes
Priority
Medium - Current exception-based approach works but limits error reporting quality.