Error Types
Sipha defines several error types to represent different kinds of problems that can occur during parsing and lexing.
ParseError
ParseError represents errors that occur during parsing. It’s an enum with four variants:
use sipha::error::ParseError;
use sipha::syntax::{TextRange, TextSize};
// Unexpected token error
let error = ParseError::UnexpectedToken {
span: TextRange::new(TextSize::from(10), TextSize::from(15)),
expected: vec!["identifier".to_string(), "number".to_string()],
};
// Invalid syntax error
let error = ParseError::InvalidSyntax {
span: TextRange::new(TextSize::from(0), TextSize::from(5)),
message: "Invalid expression syntax".to_string(),
};
// Unexpected end of file
let error = ParseError::UnexpectedEof {
span: TextRange::new(TextSize::from(100), TextSize::from(100)),
expected: vec!["}".to_string(), ";".to_string()],
};
// Ambiguity error (GLR parser)
let error = ParseError::Ambiguity {
span: TextRange::new(TextSize::from(20), TextSize::from(25)),
alternatives: vec!["expression1".to_string(), "expression2".to_string()],
};
ParseError Variants
UnexpectedToken
Occurs when the parser encounters a token that doesn’t match any expected production.
- Most common parse error
- Contains a list of expected token types
- Parser can often recover by skipping the unexpected token
Example:
// Input: "let x = 42 +"
// Error: UnexpectedToken with expected: ["number", "identifier", "("]
InvalidSyntax
Occurs when the input violates grammar rules in a way that can’t be attributed to a single unexpected token.
- Contains a descriptive error message
- Used for complex syntax violations
- May require more context to understand
Example:
// Input: "function() { return }"
// Error: InvalidSyntax with message: "Missing return value"
UnexpectedEof
Occurs when the parser reaches the end of input but expects more tokens.
- Contains a list of expected tokens
- Common when delimiters are missing (e.g., unclosed parentheses)
- Indicates incomplete input
Example:
// Input: "if (condition { ... }"
// Error: UnexpectedEof with expected: [")"]
Ambiguity (GLR backend only)
Occurs when the GLR parser finds multiple valid parse trees.
- Contains a list of alternative interpretations
- Requires disambiguation to resolve
- Only occurs with GLR parser backend
Example:
// Input: "1 + 2 * 3" (ambiguous without precedence)
// Error: Ambiguity with alternatives: ["(1 + 2) * 3", "1 + (2 * 3)"]
LexerError
LexerError represents errors that occur during tokenization (lexing):
use sipha::error::{LexerError, LexerErrorKind};
use sipha::syntax::{TextRange, TextSize};
let error = LexerError::new(
TextRange::new(TextSize::from(5), TextSize::from(6)),
LexerErrorKind::UnexpectedChar { char: '!' },
);
LexerErrorKind Variants
UnexpectedChar
An invalid character was encountered that doesn’t match any token pattern.
- Contains the unexpected character
- Usually indicates a typo or unsupported character
Example:
// Input: "let x = 42#"
// Error: UnexpectedChar { char: '#' }
UnterminatedString
A string literal was started but never closed.
- Common when quotes are mismatched
- Indicates incomplete string literal
Example:
// Input: "let s = \"hello world"
// Error: UnterminatedString
InvalidEscape
An invalid escape sequence was found in a string.
- Contains the invalid escape sequence
- Common with malformed escape sequences
Example:
// Input: "let s = \"hello\\zworld\""
// Error: InvalidEscape { escape: "\\z" }
InvalidNumber
A number literal has invalid format.
- Contains a reason explaining the issue
- Common with malformed numeric literals
Example:
// Input: "let x = 123abc"
// Error: InvalidNumber { reason: "Invalid digit 'a' in number" }
UnexpectedEof
End of file was reached unexpectedly during tokenization.
- Usually indicates incomplete input
- Common when input is cut off mid-token
Example:
// Input: "let x = 4" (cut off)
// Error: UnexpectedEof
ParseWarning
ParseWarning represents non-fatal issues that don’t prevent parsing:
use sipha::error::{ParseWarning, Severity};
use sipha::syntax::{TextRange, TextSize};
// Create warnings with different severity levels
let warning = ParseWarning::warning(
TextRange::new(TextSize::from(0), TextSize::from(10)),
"Deprecated syntax used".to_string(),
);
let info = ParseWarning::info(
TextRange::new(TextSize::from(10), TextSize::from(20)),
"Consider using newer syntax".to_string(),
);
let hint = ParseWarning::hint(
TextRange::new(TextSize::from(20), TextSize::from(30)),
"This can be simplified".to_string(),
);
Severity Levels
Warning
Important issues that should be addressed.
- Indicates potential problems
- Should be shown to users
- May indicate deprecated or problematic code
Info
Informational messages.
- Provides context or suggestions
- Less urgent than warnings
- Can be shown optionally
Hint
Suggestions for improvement.
- Optimization opportunities
- Style suggestions
- Can be shown in IDE tooltips
Converting Between Error Types
Lexer errors can be converted to parse errors:
use sipha::error::{LexerError, ParseError};
let lexer_error: LexerError = /* ... */;
let parse_error: ParseError = lexer_error.into();
This is useful when you want to handle all errors uniformly.
Error Methods
All error types provide useful methods:
ParseError Methods
use sipha::error::ParseError;
// Get the error location
let span = error.span();
// Format expected tokens as a readable string
let expected_str = error.format_expected();
// Returns: "identifier or number" or "identifier, number, or string"
// Get "did you mean" suggestions
if let Some(suggestion) = error.did_you_mean("identifer") {
println!("{}", suggestion); // "Did you mean 'identifier'?"
}
// Get context around the error
if let Some((before, error_span, after)) = error.get_context(source_code) {
println!("Context: ...{}[{}]{}...", before, error_span, after);
}
// Format error with full context
let formatted = error.format_with_context(source_code, Some("actual_token"));
println!("{}", formatted);
LexerError Methods
use sipha::error::LexerError;
// Get the error location
let span = error.span();
// Get the error kind
let kind = error.kind();
Next Steps
- Learn about Working with Errors to see how to use these error types
- See Error Recovery to understand how errors are handled
- Check Best Practices for guidelines on error handling