docs: Add comprehensive documentation to src/tokens/error.rs
This commit is contained in:
parent
02684e3e98
commit
7ccefac553
4 changed files with 208 additions and 0 deletions
20
src/snapshots/doctest_tokens_rs__invalid integer.snap
Normal file
20
src/snapshots/doctest_tokens_rs__invalid integer.snap
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
source: src/tokens.rs
|
||||||
|
expression: err
|
||||||
|
---
|
||||||
|
Err(
|
||||||
|
[
|
||||||
|
ScanError {
|
||||||
|
location: Location {
|
||||||
|
file: "<test>",
|
||||||
|
offset: 7,
|
||||||
|
length: 19,
|
||||||
|
},
|
||||||
|
kind: ParseIntError(
|
||||||
|
ParseIntError {
|
||||||
|
kind: PosOverflow,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
18
src/snapshots/doctest_tokens_rs__invalid meta-command.snap
Normal file
18
src/snapshots/doctest_tokens_rs__invalid meta-command.snap
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
source: src/tokens.rs
|
||||||
|
expression: err
|
||||||
|
---
|
||||||
|
Err(
|
||||||
|
[
|
||||||
|
ScanError {
|
||||||
|
location: Location {
|
||||||
|
file: "<test>",
|
||||||
|
offset: 0,
|
||||||
|
length: 8,
|
||||||
|
},
|
||||||
|
kind: UnknownMetaCommand(
|
||||||
|
".invalid",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
23
src/snapshots/doctest_tokens_rs__unclosed double quote.snap
Normal file
23
src/snapshots/doctest_tokens_rs__unclosed double quote.snap
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
source: src/tokens.rs
|
||||||
|
expression: err
|
||||||
|
---
|
||||||
|
Err(
|
||||||
|
[
|
||||||
|
ScanError {
|
||||||
|
location: Location {
|
||||||
|
file: "<test>",
|
||||||
|
offset: 18,
|
||||||
|
length: 0,
|
||||||
|
},
|
||||||
|
kind: UnexpectedEndOfInputWhileLookingForMatching(
|
||||||
|
'"',
|
||||||
|
Location {
|
||||||
|
file: "<test>",
|
||||||
|
offset: 9,
|
||||||
|
length: 1,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
@ -1,12 +1,136 @@
|
||||||
|
//! Lexical analysis error and diagnostics
|
||||||
|
//!
|
||||||
|
//! This module contains types for representing errors that occur during
|
||||||
|
//! the tokenization phase of parsing. These errors capture both the type
|
||||||
|
//! of lexical issue and its precise location in source code.
|
||||||
|
//!
|
||||||
|
//! # Example
|
||||||
|
//! ```
|
||||||
|
//! use osdb::tokens::error::ScanError;
|
||||||
|
//! use osdb::tokens::error::ScanErrorKind;
|
||||||
|
//! use osdb::tokens::location::Location;
|
||||||
|
//!
|
||||||
|
//! // Creating a scan error for an unexpected character
|
||||||
|
//! let location = Location::new("query.sql".into(), 10, 1);
|
||||||
|
//! let error = ScanError {
|
||||||
|
//! location,
|
||||||
|
//! kind: ScanErrorKind::UnexpectedChar('$'),
|
||||||
|
//! };
|
||||||
|
//! assert_eq!(format!("{}", error), "unexpected char: '$'");
|
||||||
|
//! ```
|
||||||
|
|
||||||
use super::Location;
|
use super::Location;
|
||||||
|
|
||||||
|
/// Category of lexical error encountered during tokenization
|
||||||
|
///
|
||||||
|
/// Represents different types of errors that can occur when scanning source text
|
||||||
|
/// into tokens, each carrying relevant context about the specific error condition.
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub enum ScanErrorKind {
|
pub enum ScanErrorKind {
|
||||||
|
/// Unexpected character in input stream
|
||||||
|
///
|
||||||
|
/// Occurs when encountering a character that is invalid in the current scanning context.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use osdb::tokens::error::{ScanError, ScanErrorKind};
|
||||||
|
/// # use osdb::tokens::location::Location;
|
||||||
|
/// let error = ScanError {
|
||||||
|
/// location: Location::new("file.txt".into(), 5, 1),
|
||||||
|
/// kind: ScanErrorKind::UnexpectedChar('@'),
|
||||||
|
/// };
|
||||||
|
/// assert_eq!(format!("{}", error), "unexpected char: '@'");
|
||||||
|
/// ```
|
||||||
UnexpectedChar(char),
|
UnexpectedChar(char),
|
||||||
|
|
||||||
|
/// Premature end of input
|
||||||
|
///
|
||||||
|
/// Triggered when input ends unexpectedly during scanning of a token or literal.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use osdb::tokens::error::{ScanError, ScanErrorKind};
|
||||||
|
/// # use osdb::tokens::location::Location;
|
||||||
|
/// let error = ScanError {
|
||||||
|
/// location: Location::new("input".into(), 3, 0),
|
||||||
|
/// kind: ScanErrorKind::UnexpectedEndOfInput,
|
||||||
|
/// };
|
||||||
|
/// assert_eq!(format!("{}", error), "unexpected end of input");
|
||||||
|
/// ```
|
||||||
UnexpectedEndOfInput,
|
UnexpectedEndOfInput,
|
||||||
|
|
||||||
|
/// Unrecognized keyword in input
|
||||||
|
///
|
||||||
|
/// Occurs when scanning an identifier that doesn't match any known SQL keyword.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use osdb::tokens::error::{ScanError, ScanErrorKind};
|
||||||
|
/// # use osdb::tokens::location::Location;
|
||||||
|
/// let error = ScanError {
|
||||||
|
/// location: Location::new("query.sql".into(), 8, 6),
|
||||||
|
/// kind: ScanErrorKind::UnknownKeyword("SELECTT".into()),
|
||||||
|
/// };
|
||||||
|
/// assert_eq!(format!("{}", error), "unknown keyword: \"SELECTT\"");
|
||||||
|
/// ```
|
||||||
UnknownKeyword(String),
|
UnknownKeyword(String),
|
||||||
|
|
||||||
|
/// Invalid meta-command syntax
|
||||||
|
///
|
||||||
|
/// Triggered by unrecognized commands starting with '.' that don't match any known meta-commands.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use osdb::tokens::error::{ScanError, ScanErrorKind};
|
||||||
|
/// # use osdb::tokens::location::Location;
|
||||||
|
/// let error = ScanError {
|
||||||
|
/// location: Location::new("cmd".into(), 1, 5),
|
||||||
|
/// kind: ScanErrorKind::UnknownMetaCommand(".test".into()),
|
||||||
|
/// };
|
||||||
|
/// assert_eq!(format!("{}", error), "unknown meta-command: \".test\"");
|
||||||
|
/// ```
|
||||||
UnknownMetaCommand(String),
|
UnknownMetaCommand(String),
|
||||||
|
|
||||||
|
/// Invalid integer literal format
|
||||||
|
///
|
||||||
|
/// Contains the underlying parse error from failed integer conversion.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use osdb::tokens::error::{ScanError, ScanErrorKind};
|
||||||
|
/// # use osdb::tokens::location::Location;
|
||||||
|
/// # use std::num::ParseIntError;
|
||||||
|
/// let parse_error = "123a".parse::<i64>().unwrap_err();
|
||||||
|
/// let error = ScanError {
|
||||||
|
/// location: Location::new("nums".into(), 0, 4),
|
||||||
|
/// kind: ScanErrorKind::ParseIntError(parse_error),
|
||||||
|
/// };
|
||||||
|
/// assert!(match &error.kind {
|
||||||
|
/// ScanErrorKind::ParseIntError(_) => true,
|
||||||
|
/// _ => false
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
ParseIntError(std::num::ParseIntError),
|
ParseIntError(std::num::ParseIntError),
|
||||||
|
|
||||||
|
/// Unclosed string literal
|
||||||
|
///
|
||||||
|
/// Occurs when a string literal is missing its closing quote. Carries the quote
|
||||||
|
/// character and location where the string started.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # use osdb::tokens::error::{ScanError, ScanErrorKind};
|
||||||
|
/// # use osdb::tokens::location::Location;
|
||||||
|
/// let start_loc = Location::new("strings".into(), 0, 1);
|
||||||
|
/// let error = ScanError {
|
||||||
|
/// location: Location::new("strings".into(), 5, 0),
|
||||||
|
/// kind: ScanErrorKind::UnexpectedEndOfInputWhileLookingForMatching('"', start_loc),
|
||||||
|
/// };
|
||||||
|
/// assert_eq!(
|
||||||
|
/// format!("{}", error),
|
||||||
|
/// "unexpected end of input while looking for matching '\"'"
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
UnexpectedEndOfInputWhileLookingForMatching(char, Location),
|
UnexpectedEndOfInputWhileLookingForMatching(char, Location),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -26,9 +150,32 @@ impl std::fmt::Display for ScanErrorKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Lexical error with source location information
|
||||||
|
///
|
||||||
|
/// Combines a [`ScanErrorKind`] with precise source code location details
|
||||||
|
/// to enable rich error reporting and diagnostics.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// use osdb::tokens::error::ScanError;
|
||||||
|
/// use osdb::tokens::error::ScanErrorKind;
|
||||||
|
/// use osdb::tokens::location::Location;
|
||||||
|
///
|
||||||
|
/// let location = Location::new("script.osql".into(), 20, 3);
|
||||||
|
/// let error = ScanError {
|
||||||
|
/// location,
|
||||||
|
/// kind: ScanErrorKind::UnexpectedChar('?'),
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// assert_eq!(error.location.file, "script.osql");
|
||||||
|
/// assert_eq!(error.location.offset, 20);
|
||||||
|
/// assert_eq!(format!("{}", error), "unexpected char: '?'");
|
||||||
|
/// ```
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct ScanError {
|
pub struct ScanError {
|
||||||
|
/// Source location where the error occurred
|
||||||
pub location: Location,
|
pub location: Location,
|
||||||
|
/// Specific type of lexical error
|
||||||
pub kind: ScanErrorKind,
|
pub kind: ScanErrorKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue