Skip to content

Commit 96da136

Browse files
authored
Move token and error structs into related modules (#11957)
## Summary This PR does some housekeeping into moving certain structs into related modules. Specifically, 1. Move `LexicalError` from `lexer.rs` to `error.rs` which also contains the `ParseError` 2. Move `Token`, `TokenFlags` and `TokenValue` from `lexer.rs` to `token.rs`
1 parent 4667d86 commit 96da136

File tree

10 files changed

+352
-342
lines changed

10 files changed

+352
-342
lines changed

crates/ruff_python_parser/src/error.rs

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use std::fmt;
22

33
use ruff_text_size::TextRange;
44

5-
use crate::lexer::{LexicalError, LexicalErrorType};
65
use crate::TokenKind;
76

87
/// Represents represent errors that occur during parsing and are
@@ -295,3 +294,135 @@ impl std::fmt::Display for ParseErrorType {
295294
}
296295
}
297296
}
297+
298+
/// Represents an error that occur during lexing and are
299+
/// returned by the `parse_*` functions in the iterator in the
300+
/// [lexer] implementation.
301+
///
302+
/// [lexer]: crate::lexer
303+
#[derive(Debug, Clone, PartialEq)]
304+
pub struct LexicalError {
305+
/// The type of error that occurred.
306+
error: LexicalErrorType,
307+
/// The location of the error.
308+
location: TextRange,
309+
}
310+
311+
impl LexicalError {
312+
/// Creates a new `LexicalError` with the given error type and location.
313+
pub fn new(error: LexicalErrorType, location: TextRange) -> Self {
314+
Self { error, location }
315+
}
316+
317+
pub fn error(&self) -> &LexicalErrorType {
318+
&self.error
319+
}
320+
321+
pub fn into_error(self) -> LexicalErrorType {
322+
self.error
323+
}
324+
325+
pub fn location(&self) -> TextRange {
326+
self.location
327+
}
328+
}
329+
330+
impl std::ops::Deref for LexicalError {
331+
type Target = LexicalErrorType;
332+
333+
fn deref(&self) -> &Self::Target {
334+
self.error()
335+
}
336+
}
337+
338+
impl std::error::Error for LexicalError {
339+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
340+
Some(self.error())
341+
}
342+
}
343+
344+
impl std::fmt::Display for LexicalError {
345+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
346+
write!(
347+
f,
348+
"{} at byte offset {}",
349+
self.error(),
350+
u32::from(self.location().start())
351+
)
352+
}
353+
}
354+
355+
/// Represents the different types of errors that can occur during lexing.
356+
#[derive(Debug, Clone, PartialEq)]
357+
pub enum LexicalErrorType {
358+
// TODO: Can probably be removed, the places it is used seem to be able
359+
// to use the `UnicodeError` variant instead.
360+
#[doc(hidden)]
361+
StringError,
362+
/// A string literal without the closing quote.
363+
UnclosedStringError,
364+
/// Decoding of a unicode escape sequence in a string literal failed.
365+
UnicodeError,
366+
/// Missing the `{` for unicode escape sequence.
367+
MissingUnicodeLbrace,
368+
/// Missing the `}` for unicode escape sequence.
369+
MissingUnicodeRbrace,
370+
/// The indentation is not consistent.
371+
IndentationError,
372+
/// An unrecognized token was encountered.
373+
UnrecognizedToken { tok: char },
374+
/// An f-string error containing the [`FStringErrorType`].
375+
FStringError(FStringErrorType),
376+
/// Invalid character encountered in a byte literal.
377+
InvalidByteLiteral,
378+
/// An unexpected character was encountered after a line continuation.
379+
LineContinuationError,
380+
/// An unexpected end of file was encountered.
381+
Eof,
382+
/// An unexpected error occurred.
383+
OtherError(Box<str>),
384+
}
385+
386+
impl std::error::Error for LexicalErrorType {}
387+
388+
impl std::fmt::Display for LexicalErrorType {
389+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
390+
match self {
391+
LexicalErrorType::StringError => write!(f, "Got unexpected string"),
392+
LexicalErrorType::FStringError(error) => write!(f, "f-string: {error}"),
393+
LexicalErrorType::InvalidByteLiteral => {
394+
write!(f, "bytes can only contain ASCII literal characters")
395+
}
396+
LexicalErrorType::UnicodeError => write!(f, "Got unexpected unicode"),
397+
LexicalErrorType::IndentationError => {
398+
write!(f, "unindent does not match any outer indentation level")
399+
}
400+
LexicalErrorType::UnrecognizedToken { tok } => {
401+
write!(f, "Got unexpected token {tok}")
402+
}
403+
LexicalErrorType::LineContinuationError => {
404+
write!(f, "unexpected character after line continuation character")
405+
}
406+
LexicalErrorType::Eof => write!(f, "unexpected EOF while parsing"),
407+
LexicalErrorType::OtherError(msg) => write!(f, "{msg}"),
408+
LexicalErrorType::UnclosedStringError => {
409+
write!(f, "missing closing quote in string literal")
410+
}
411+
LexicalErrorType::MissingUnicodeLbrace => {
412+
write!(f, "Missing `{{` in Unicode escape sequence")
413+
}
414+
LexicalErrorType::MissingUnicodeRbrace => {
415+
write!(f, "Missing `}}` in Unicode escape sequence")
416+
}
417+
}
418+
}
419+
}
420+
421+
#[cfg(target_pointer_width = "64")]
422+
mod sizes {
423+
use crate::error::{LexicalError, LexicalErrorType};
424+
use static_assertions::assert_eq_size;
425+
426+
assert_eq_size!(LexicalErrorType, [u8; 24]);
427+
assert_eq_size!(LexicalError, [u8; 32]);
428+
}

0 commit comments

Comments
 (0)