From 3343188756c2dd476d5ea01ecaf96a4d8699e897 Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 24 Jan 2026 01:54:29 +0100 Subject: [PATCH 1/7] replace pairs of usize with location struct --- src/machine/machine_errors.rs | 11 +++--- src/machine/system_calls.rs | 8 ++--- src/parser/ast.rs | 60 +++++++++++++++++++++---------- src/parser/lexer.rs | 66 ++++++++++++++--------------------- src/parser/parser.rs | 44 ++++++++--------------- src/read.rs | 9 ++--- 6 files changed, 96 insertions(+), 102 deletions(-) diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs index 4ed19893..2dccd1c8 100644 --- a/src/machine/machine_errors.rs +++ b/src/machine/machine_errors.rs @@ -20,7 +20,7 @@ pub type MachineStubGen = Box MachineStub>; #[derive(Debug)] pub(crate) struct MachineError { stub: MachineStub, - location: Option<(usize, usize)>, // line_num, col_num + location: Option, } // from 7.12.2 b) of 13211-1:1995 @@ -753,14 +753,15 @@ impl MachineState { } pub(super) fn error_form(&mut self, err: MachineError, src: MachineStub) -> MachineStub { - if let Some((line_num, _col_num)) = err.location { + if let Some(location) = err.location { + let line = location.line(); functor!( atom!("error"), [ functor((err.stub)), functor( (atom!(":")), - [functor(src), number(line_num, (&mut self.arena))] + [functor(src), number(line, (&mut self.arena))] ) ] ) @@ -853,9 +854,9 @@ impl From for CompilationError { } impl CompilationError { - pub(crate) fn line_and_col_num(&self) -> Option<(usize, usize)> { + pub(crate) fn line_and_col_num(&self) -> Option { match self { - CompilationError::ParserError(err) => err.line_and_col_num(), + CompilationError::ParserError(err) => err.location(), _ => None, } } diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index edd08cb5..f6763153 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1016,7 +1016,7 @@ impl MachineState { self.unify_fixnum(n, nx); } _ => { - let err = ParserError::ParseBigInt(0, 0); + let err = ParserError::ParseBigInt(parser.lexer.location.clone()); let err = self.syntax_error(err); return Err(self.error_form(err, stub_gen())); @@ -1026,9 +1026,7 @@ impl MachineState { return Ok(()); } Ok(c) => { - let (line_num, col_num) = (lexer.line_num, lexer.col_num); - - let err = ParserError::UnexpectedChar(c, line_num, col_num); + let err = ParserError::UnexpectedChar(c, lexer.location); let err = self.syntax_error(err); return Err(self.error_form(err, stub_gen())); @@ -9196,7 +9194,7 @@ impl Machine { stream.add_lines_read(parser.lines_read()); } Ok(true) => { - stream.add_lines_read(parser.lexer.line_num); + stream.add_lines_read(parser.lexer.location.line()); self.machine_st.fail = true; } Err(err) => { diff --git a/src/parser/ast.rs b/src/parser/ast.rs index ba18d36e..0d789c33 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -426,34 +426,53 @@ pub enum ArithmeticError { UninstantiatedVar, } +#[derive(Debug, Clone)] +pub struct Location { + pub(super) line: usize, + pub(super) column: usize, +} + +impl Location { + // beginning of file + pub(crate) const BOF: Self = Self { line: 0, column: 0 }; + + pub fn line(&self) -> usize { + self.line + } + + pub fn column(&self) -> usize { + self.column + } +} + #[allow(dead_code)] #[derive(Debug)] pub enum ParserError { - BackQuotedString(usize, usize), + BackQuotedString(Location), IO(IOError), - IncompleteReduction(usize, usize), - InfiniteFloat(usize, usize), + IncompleteReduction(Location), + InfiniteFloat(Location), InvalidSingleQuotedCharacter(char), LexicalError(lexical::Error), - MissingQuote(usize, usize), - NonPrologChar(usize, usize), - ParseBigInt(usize, usize), - UnexpectedChar(char, usize, usize), + MissingQuote(Location), + NonPrologChar(Location), + ParseBigInt(Location), + UnexpectedChar(char, Location), // UnexpectedEOF, - Utf8Error(usize, usize), + Utf8Error(Option), } impl ParserError { - pub fn line_and_col_num(&self) -> Option<(usize, usize)> { + pub fn location(&self) -> Option { match self { - &ParserError::BackQuotedString(line_num, col_num) - | &ParserError::IncompleteReduction(line_num, col_num) - | &ParserError::InfiniteFloat(line_num, col_num) - | &ParserError::MissingQuote(line_num, col_num) - | &ParserError::NonPrologChar(line_num, col_num) - | &ParserError::ParseBigInt(line_num, col_num) - | &ParserError::UnexpectedChar(_, line_num, col_num) - | &ParserError::Utf8Error(line_num, col_num) => Some((line_num, col_num)), + ParserError::BackQuotedString(location) + | ParserError::IncompleteReduction(location) + | ParserError::InfiniteFloat(location) + | ParserError::MissingQuote(location) + | ParserError::NonPrologChar(location) + | ParserError::ParseBigInt(location) + | ParserError::UnexpectedChar(_, location) => Some(location.clone()), + ParserError::Utf8Error(location) => location.as_ref().cloned(), _ => None, } } @@ -513,8 +532,11 @@ impl From for ParserError { impl From<&IOError> for ParserError { fn from(error: &IOError) -> ParserError { - if error.get_ref().filter(|e| e.is::()).is_some() { - ParserError::Utf8Error(0, 0) + if let Some(_utf8_error) = error + .get_ref() + .and_then(|e| e.downcast_ref::()) + { + ParserError::Utf8Error(None) } else { ParserError::IO(error.kind().into()) } diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs index bfc3fb8f..ed39e210 100644 --- a/src/parser/lexer.rs +++ b/src/parser/lexer.rs @@ -91,16 +91,14 @@ macro_rules! try_nt { pub(crate) struct Lexer<'a, R> { pub(crate) reader: R, pub(crate) machine_st: &'a mut MachineState, - pub(crate) line_num: usize, - pub(crate) col_num: usize, + pub(crate) location: Location, } impl<'a, R: fmt::Debug> fmt::Debug for Lexer<'a, R> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("LexerParser") .field("reader", &"&'a mut R") // Hacky solution. - .field("line_num", &self.line_num) - .field("col_num", &self.col_num) + .field("location", &self.location) .finish() } } @@ -110,8 +108,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { Self { reader: src, machine_st, - line_num: 0, - col_num: 0, + location: Location::BOF, } } @@ -138,10 +135,10 @@ impl<'a, R: CharRead> Lexer<'a, R> { self.reader.consume(c.len_utf8()); if new_line_char!(c) { - self.line_num += 1; - self.col_num = 0; + self.location.line += 1; + self.location.column = 0; } else { - self.col_num += 1; + self.location.column += 1; } } @@ -200,10 +197,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { match comment_loop() { Err(e) if e.is_unexpected_eof() => { - return Err(ParserError::IncompleteReduction( - self.line_num, - self.col_num, - )); + return Err(ParserError::IncompleteReduction(self.location.clone())); } Err(e) => { return Err(e); @@ -215,7 +209,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { self.skip_char(c); Ok(true) } else { - Err(ParserError::NonPrologChar(self.line_num, self.col_num)) + Err(ParserError::NonPrologChar(self.location.clone())) } } else { self.return_char('/'); @@ -232,7 +226,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { if !back_quote_char!(c2) { self.return_char(c); - Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)) + Err(ParserError::UnexpectedChar(c, self.location.clone())) } else { self.skip_char(c2); Ok(c2) @@ -257,7 +251,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { Ok(None) } else { self.return_char(c); - Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)) + Err(ParserError::UnexpectedChar(c, self.location.clone())) } } else { self.get_back_quoted_char().map(Some) @@ -279,10 +273,10 @@ impl<'a, R: CharRead> Lexer<'a, R> { self.skip_char(c); Ok(token) } else { - Err(ParserError::MissingQuote(self.line_num, self.col_num)) + Err(ParserError::MissingQuote(self.location.clone())) } } else { - Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)) + Err(ParserError::UnexpectedChar(c, self.location.clone())) } } @@ -313,7 +307,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { if !single_quote_char!(c2) { self.return_char(c); - Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)) + Err(ParserError::UnexpectedChar(c, self.location.clone())) } else { self.skip_char(c2); Ok(c2) @@ -354,7 +348,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { if !double_quote_char!(c2) { self.return_char(c); - Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)) + Err(ParserError::UnexpectedChar(c, self.location.clone())) } else { self.skip_char(c2); Ok(c2) @@ -378,7 +372,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { 't' => '\t', 'n' => '\n', 'r' => '\r', - c => return Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)), + c => return Err(ParserError::UnexpectedChar(c, self.location.clone())), }; self.skip_char(c); @@ -396,10 +390,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { if hexadecimal_digit_char!(c) { self.escape_sequence_to_char(|c| hexadecimal_digit_char!(c), 16) } else { - Err(ParserError::IncompleteReduction( - self.line_num, - self.col_num, - )) + Err(ParserError::IncompleteReduction(self.location.clone())) } } @@ -425,17 +416,14 @@ impl<'a, R: CharRead> Lexer<'a, R> { if backslash_char!(c) { self.skip_char(c); u32::from_str_radix(&token, radix).map_or_else( - |_| Err(ParserError::ParseBigInt(self.line_num, self.col_num)), + |_| Err(ParserError::ParseBigInt(self.location.clone())), |n| { char::try_from(n) - .map_err(|_| ParserError::Utf8Error(self.line_num, self.col_num)) + .map_err(|_| ParserError::Utf8Error(Some(self.location.clone()))) }, ) } else { - Err(ParserError::IncompleteReduction( - self.line_num, - self.col_num, - )) + Err(ParserError::IncompleteReduction(self.location.clone())) } } @@ -447,7 +435,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { Ok(c) } else { if !backslash_char!(c) { - return Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)); + return Err(ParserError::UnexpectedChar(c, self.location.clone())); } self.skip_char(c); @@ -478,7 +466,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { self.skip_char(c); Ok(token) } else { - Err(ParserError::MissingQuote(self.line_num, self.col_num)) + Err(ParserError::MissingQuote(self.location.clone())) } } @@ -509,7 +497,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { .map(NumberToken::Integer) } else { self.return_char(start); - Err(ParserError::ParseBigInt(self.line_num, self.col_num)) + Err(ParserError::ParseBigInt(self.location.clone())) } } @@ -540,7 +528,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { .map(NumberToken::Integer) } else { self.return_char(start); - Err(ParserError::ParseBigInt(self.line_num, self.col_num)) + Err(ParserError::ParseBigInt(self.location.clone())) } } @@ -571,7 +559,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { .map(NumberToken::Integer) } else { self.return_char(start); - Err(ParserError::ParseBigInt(self.line_num, self.col_num)) + Err(ParserError::ParseBigInt(self.location.clone())) } } @@ -648,7 +636,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { } } else { match self.get_back_quoted_string() { - Ok(_) => return Err(ParserError::BackQuotedString(self.line_num, self.col_num)), + Ok(_) => return Err(ParserError::BackQuotedString(self.location.clone())), Err(e) => return Err(e), } } @@ -686,7 +674,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { if decimal_digit_char!(c) { Ok(c) } else { - Err(ParserError::ParseBigInt(self.line_num, self.col_num)) + Err(ParserError::ParseBigInt(self.location.clone())) } } else { Ok(c) @@ -708,7 +696,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { .or_else(|_| { Integer::from_str_radix(token, radix) .map(|n| GInteger::Integer(arena_alloc!(n, &mut self.machine_st.arena))) - .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num)) + .map_err(|_| ParserError::ParseBigInt(self.location.clone())) }) } diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 61e85c7e..eda980c9 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -254,10 +254,7 @@ pub fn read_tokens(lexer: &mut Lexer<'_, R>) -> Result, } } Err(e) if e.is_unexpected_eof() && !tokens.is_empty() => { - return Err(ParserError::IncompleteReduction( - lexer.line_num, - lexer.col_num, - )); + return Err(ParserError::IncompleteReduction(lexer.location.clone())); } Err(e) => { return Err(e); @@ -702,8 +699,7 @@ impl<'a, R: CharRead> Parser<'a, R> { Some(term) => term, _ => { return Err(ParserError::IncompleteReduction( - self.lexer.line_num, - self.lexer.col_num, + self.lexer.location.clone(), )) } }; @@ -719,8 +715,7 @@ impl<'a, R: CharRead> Parser<'a, R> { if arity > self.terms.len() { return Err(ParserError::IncompleteReduction( - self.lexer.line_num, - self.lexer.col_num, + self.lexer.location.clone(), )); } @@ -791,8 +786,7 @@ impl<'a, R: CharRead> Parser<'a, R> { Some(term) => term, _ => { return Err(ParserError::IncompleteReduction( - self.lexer.line_num, - self.lexer.col_num, + self.lexer.location.clone(), )) } }; @@ -972,10 +966,7 @@ impl<'a, R: CharRead> Parser<'a, R> { self.negate_number(n, negate_rat_rc, Literal::Rational) } Token::Literal(Literal::F64(_offset, n)) if n.is_infinite() => { - return Err(ParserError::InfiniteFloat( - self.lexer.line_num, - self.lexer.col_num, - )); + return Err(ParserError::InfiniteFloat(self.lexer.location.clone())); } Token::Literal(Literal::F64(offset, n)) => { self.negate_number((offset, n), negate_f64, |(offset, n)| { @@ -998,8 +989,7 @@ impl<'a, R: CharRead> Parser<'a, R> { Token::Close => { if !self.reduce_term() && !self.reduce_brackets() { return Err(ParserError::IncompleteReduction( - self.lexer.line_num, - self.lexer.col_num, + self.lexer.location.clone(), )); } } @@ -1007,8 +997,7 @@ impl<'a, R: CharRead> Parser<'a, R> { Token::CloseList => { if !self.reduce_list()? { return Err(ParserError::IncompleteReduction( - self.lexer.line_num, - self.lexer.col_num, + self.lexer.location.clone(), )); } } @@ -1016,8 +1005,7 @@ impl<'a, R: CharRead> Parser<'a, R> { Token::CloseCurly => { if !self.reduce_curly()? { return Err(ParserError::IncompleteReduction( - self.lexer.line_num, - self.lexer.col_num, + self.lexer.location.clone(), )); } } @@ -1053,8 +1041,7 @@ impl<'a, R: CharRead> Parser<'a, R> { | Some(TokenType::HeadTailSeparator) | Some(TokenType::Comma) => { return Err(ParserError::IncompleteReduction( - self.lexer.line_num, - self.lexer.col_num, + self.lexer.location.clone(), )) } _ => {} @@ -1066,12 +1053,12 @@ impl<'a, R: CharRead> Parser<'a, R> { #[inline] pub fn add_lines_read(&mut self, lines_read: usize) { - self.lexer.line_num += lines_read; + self.lexer.location.line += lines_read; } #[inline] pub fn lines_read(&self) -> usize { - self.lexer.line_num + self.lexer.location.line } // on success, returns the parsed term and the number of lines read. @@ -1093,8 +1080,7 @@ impl<'a, R: CharRead> Parser<'a, R> { if self.terms.len() > 1 || self.stack.len() > 1 { return Err(ParserError::IncompleteReduction( - self.lexer.line_num, - self.lexer.col_num, + self.lexer.location.clone(), )); } @@ -1104,14 +1090,12 @@ impl<'a, R: CharRead> Parser<'a, R> { Ok(term) } else { Err(ParserError::IncompleteReduction( - self.lexer.line_num, - self.lexer.col_num, + self.lexer.location.clone(), )) } } _ => Err(ParserError::IncompleteReduction( - self.lexer.line_num, - self.lexer.col_num, + self.lexer.location.clone(), )), } } diff --git a/src/read.rs b/src/read.rs index fe709c7e..9f578bf8 100644 --- a/src/read.rs +++ b/src/read.rs @@ -48,12 +48,13 @@ pub(crate) fn error_after_read_term( parser: &Parser, ) -> CompilationError { if err.is_unexpected_eof() { - let line_num = parser.lexer.line_num; - let col_num = parser.lexer.col_num; + let location = &parser.lexer.location; // rough overlap with errors 8.14.1.3 k) & l) of the ISO standard here - if !(line_num == prior_num_lines_read && col_num == 0) { - return CompilationError::from(ParserError::IncompleteReduction(line_num, col_num)); + if !(location.line() == prior_num_lines_read && location.column() == 0) { + return CompilationError::from(ParserError::IncompleteReduction( + parser.lexer.location.clone(), + )); } } From 083546442df31cf4a77bf95938e042b75bc31a90 Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 24 Jan 2026 02:22:44 +0100 Subject: [PATCH 2/7] make match exhaustive --- src/parser/ast.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/parser/ast.rs b/src/parser/ast.rs index 0d789c33..fe28207b 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -473,7 +473,9 @@ impl ParserError { | ParserError::ParseBigInt(location) | ParserError::UnexpectedChar(_, location) => Some(location.clone()), ParserError::Utf8Error(location) => location.as_ref().cloned(), - _ => None, + ParserError::IO(_) + | ParserError::LexicalError(_) + | ParserError::InvalidSingleQuotedCharacter(_) => None, } } From bd233fedfd6ef10743bee2035176d13c561d7274 Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 24 Jan 2026 02:23:19 +0100 Subject: [PATCH 3/7] add location to InvalidSingleQuotedCharacter --- src/parser/ast.rs | 7 +++---- src/parser/lexer.rs | 5 ++++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/parser/ast.rs b/src/parser/ast.rs index fe28207b..17caae24 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -452,7 +452,7 @@ pub enum ParserError { IO(IOError), IncompleteReduction(Location), InfiniteFloat(Location), - InvalidSingleQuotedCharacter(char), + InvalidSingleQuotedCharacter(char, Location), LexicalError(lexical::Error), MissingQuote(Location), NonPrologChar(Location), @@ -466,6 +466,7 @@ impl ParserError { pub fn location(&self) -> Option { match self { ParserError::BackQuotedString(location) + | ParserError::InvalidSingleQuotedCharacter(_, location) | ParserError::IncompleteReduction(location) | ParserError::InfiniteFloat(location) | ParserError::MissingQuote(location) @@ -473,9 +474,7 @@ impl ParserError { | ParserError::ParseBigInt(location) | ParserError::UnexpectedChar(_, location) => Some(location.clone()), ParserError::Utf8Error(location) => location.as_ref().cloned(), - ParserError::IO(_) - | ParserError::LexicalError(_) - | ParserError::InvalidSingleQuotedCharacter(_) => None, + ParserError::IO(_) | ParserError::LexicalError(_) => None, } } diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs index ed39e210..7acf76b6 100644 --- a/src/parser/lexer.rs +++ b/src/parser/lexer.rs @@ -632,7 +632,10 @@ impl<'a, R: CharRead> Lexer<'a, R> { } } } else { - return Err(ParserError::InvalidSingleQuotedCharacter(c)); + return Err(ParserError::InvalidSingleQuotedCharacter( + c, + self.location.clone(), + )); } } else { match self.get_back_quoted_string() { From 18b476af28e104cea2be75eeb8f3b1982d85a1a4 Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 24 Jan 2026 03:24:02 +0100 Subject: [PATCH 4/7] make ParserError a struct with an enum kind field --- src/machine/streams.rs | 2 +- src/machine/system_calls.rs | 4 +- src/parser/ast.rs | 97 +++++++++++++++++-------------------- src/parser/lexer.rs | 94 ++++++++++++++++++++++------------- src/parser/parser.rs | 50 +++++-------------- src/read.rs | 4 +- 6 files changed, 120 insertions(+), 131 deletions(-) diff --git a/src/machine/streams.rs b/src/machine/streams.rs index 0d88ca58..760c6840 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -1952,7 +1952,7 @@ impl MachineState { ) -> Result { match stream.peek_char() { None => Ok(stream), // empty stream is handled gracefully by Lexer::eof - Some(Err(e)) => Err(ParserError::IO(e)), + Some(Err(e)) => Err(ParserError::from(e)), Some(Ok(c)) => { if c == '\u{feff}' { // skip UTF-8 BOM diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index f6763153..59ba3975 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1016,7 +1016,7 @@ impl MachineState { self.unify_fixnum(n, nx); } _ => { - let err = ParserError::ParseBigInt(parser.lexer.location.clone()); + let err = parser.lexer.parse_big_int_error(); let err = self.syntax_error(err); return Err(self.error_form(err, stub_gen())); @@ -1026,7 +1026,7 @@ impl MachineState { return Ok(()); } Ok(c) => { - let err = ParserError::UnexpectedChar(c, lexer.location); + let err = lexer.unexpected_char(c); let err = self.syntax_error(err); return Err(self.error_form(err, stub_gen())); diff --git a/src/parser/ast.rs b/src/parser/ast.rs index 17caae24..18f2335d 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -447,71 +447,71 @@ impl Location { #[allow(dead_code)] #[derive(Debug)] -pub enum ParserError { - BackQuotedString(Location), +pub struct ParserError { + pub(crate) location: Option, + pub(crate) kind: ParserErrorKind, +} + +#[allow(dead_code)] +#[derive(Debug)] +#[non_exhaustive] +pub enum ParserErrorKind { + BackQuotedString, IO(IOError), - IncompleteReduction(Location), - InfiniteFloat(Location), - InvalidSingleQuotedCharacter(char, Location), + IncompleteReduction, + InfiniteFloat, + InvalidSingleQuotedCharacter(char), LexicalError(lexical::Error), - MissingQuote(Location), - NonPrologChar(Location), - ParseBigInt(Location), - UnexpectedChar(char, Location), + MissingQuote, + NonPrologChar, + ParseBigInt, + UnexpectedChar(char), // UnexpectedEOF, - Utf8Error(Option), + Utf8Error, } impl ParserError { pub fn location(&self) -> Option { - match self { - ParserError::BackQuotedString(location) - | ParserError::InvalidSingleQuotedCharacter(_, location) - | ParserError::IncompleteReduction(location) - | ParserError::InfiniteFloat(location) - | ParserError::MissingQuote(location) - | ParserError::NonPrologChar(location) - | ParserError::ParseBigInt(location) - | ParserError::UnexpectedChar(_, location) => Some(location.clone()), - ParserError::Utf8Error(location) => location.as_ref().cloned(), - ParserError::IO(_) | ParserError::LexicalError(_) => None, - } + self.location.as_ref().cloned() } pub fn as_atom(&self) -> Atom { - match self { - ParserError::BackQuotedString(..) => atom!("back_quoted_string"), - ParserError::IncompleteReduction(..) => atom!("incomplete_reduction"), - ParserError::InvalidSingleQuotedCharacter(..) => { + match &self.kind { + ParserErrorKind::BackQuotedString => atom!("back_quoted_string"), + ParserErrorKind::IncompleteReduction => atom!("incomplete_reduction"), + ParserErrorKind::InvalidSingleQuotedCharacter(..) => { atom!("invalid_single_quoted_character") } - ParserError::InfiniteFloat(..) => { + ParserErrorKind::InfiniteFloat => { atom!("infinite_float") } - ParserError::IO(e) if e.kind() == ErrorKind::UnexpectedEof => { + ParserErrorKind::IO(e) if e.kind() == ErrorKind::UnexpectedEof => { atom!("unexpected_end_of_file") } - ParserError::IO(e) if e.kind() == ErrorKind::InvalidData => { + ParserErrorKind::IO(e) if e.kind() == ErrorKind::InvalidData => { atom!("invalid_data") } - ParserError::IO(_) => atom!("input_output_error"), - ParserError::LexicalError(_) => atom!("lexical_error"), - ParserError::MissingQuote(..) => atom!("missing_quote"), - ParserError::NonPrologChar(..) => atom!("non_prolog_character"), - ParserError::ParseBigInt(..) => atom!("cannot_parse_big_int"), - ParserError::UnexpectedChar(..) => atom!("unexpected_char"), - ParserError::Utf8Error(..) => atom!("utf8_conversion_error"), + ParserErrorKind::IO(_) => atom!("input_output_error"), + ParserErrorKind::LexicalError(_) => atom!("lexical_error"), + ParserErrorKind::MissingQuote => atom!("missing_quote"), + ParserErrorKind::NonPrologChar => atom!("non_prolog_character"), + ParserErrorKind::ParseBigInt => atom!("cannot_parse_big_int"), + ParserErrorKind::UnexpectedChar(..) => atom!("unexpected_char"), + ParserErrorKind::Utf8Error => atom!("utf8_conversion_error"), } } #[inline] pub fn unexpected_eof() -> Self { - ParserError::IO(std::io::Error::from(ErrorKind::UnexpectedEof)) + ParserError { + location: None, + kind: ParserErrorKind::IO(std::io::Error::from(ErrorKind::UnexpectedEof)), + } } #[inline] pub fn is_unexpected_eof(&self) -> bool { - if let ParserError::IO(e) = self { + if let ParserErrorKind::IO(e) = &self.kind { e.kind() == ErrorKind::UnexpectedEof } else { false @@ -521,25 +521,18 @@ impl ParserError { impl From for ParserError { fn from(e: lexical::Error) -> ParserError { - ParserError::LexicalError(e) + ParserError { + location: None, + kind: ParserErrorKind::LexicalError(e), + } } } impl From for ParserError { fn from(e: IOError) -> ParserError { - ParserError::IO(e) - } -} - -impl From<&IOError> for ParserError { - fn from(error: &IOError) -> ParserError { - if let Some(_utf8_error) = error - .get_ref() - .and_then(|e| e.downcast_ref::()) - { - ParserError::Utf8Error(None) - } else { - ParserError::IO(error.kind().into()) + ParserError { + location: None, + kind: ParserErrorKind::IO(e), } } } diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs index 7acf76b6..0d3f8941 100644 --- a/src/parser/lexer.rs +++ b/src/parser/lexer.rs @@ -16,7 +16,10 @@ macro_rules! consume_chars_with { match $e { Ok(Some(c)) => $token.push(c), Ok(None) => continue, - Err($crate::parser::ast::ParserError::UnexpectedChar(..)) => break, + Err($crate::parser::ast::ParserError { + kind: $crate::parser::ast::ParserErrorKind::UnexpectedChar(..), + .. + }) => break, Err(e) => return Err(e), } } @@ -103,6 +106,27 @@ impl<'a, R: fmt::Debug> fmt::Debug for Lexer<'a, R> { } } +impl Lexer<'_, R> { + pub(crate) fn located_error(&self, kind: ParserErrorKind) -> ParserError { + ParserError { + location: Some(self.location.clone()), + kind, + } + } + + pub(crate) fn parse_big_int_error(&self) -> ParserError { + self.located_error(ParserErrorKind::ParseBigInt) + } + + pub(crate) fn incomplete_reduction(&self) -> ParserError { + self.located_error(ParserErrorKind::IncompleteReduction) + } + + pub(crate) fn unexpected_char(&self, c: char) -> ParserError { + self.located_error(ParserErrorKind::UnexpectedChar(c)) + } +} + impl<'a, R: CharRead> Lexer<'a, R> { pub fn new(src: R, machine_st: &'a mut MachineState) -> Self { Self { @@ -197,7 +221,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { match comment_loop() { Err(e) if e.is_unexpected_eof() => { - return Err(ParserError::IncompleteReduction(self.location.clone())); + return Err(self.incomplete_reduction()); } Err(e) => { return Err(e); @@ -209,7 +233,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { self.skip_char(c); Ok(true) } else { - Err(ParserError::NonPrologChar(self.location.clone())) + Err(self.located_error(ParserErrorKind::NonPrologChar)) } } else { self.return_char('/'); @@ -226,7 +250,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { if !back_quote_char!(c2) { self.return_char(c); - Err(ParserError::UnexpectedChar(c, self.location.clone())) + Err(self.unexpected_char(c)) } else { self.skip_char(c2); Ok(c2) @@ -251,7 +275,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { Ok(None) } else { self.return_char(c); - Err(ParserError::UnexpectedChar(c, self.location.clone())) + Err(self.unexpected_char(c)) } } else { self.get_back_quoted_char().map(Some) @@ -273,10 +297,13 @@ impl<'a, R: CharRead> Lexer<'a, R> { self.skip_char(c); Ok(token) } else { - Err(ParserError::MissingQuote(self.location.clone())) + Err({ + let this = &self; + this.located_error(ParserErrorKind::MissingQuote) + }) } } else { - Err(ParserError::UnexpectedChar(c, self.location.clone())) + Err(self.unexpected_char(c)) } } @@ -307,7 +334,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { if !single_quote_char!(c2) { self.return_char(c); - Err(ParserError::UnexpectedChar(c, self.location.clone())) + Err(self.unexpected_char(c)) } else { self.skip_char(c2); Ok(c2) @@ -348,7 +375,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { if !double_quote_char!(c2) { self.return_char(c); - Err(ParserError::UnexpectedChar(c, self.location.clone())) + Err(self.unexpected_char(c)) } else { self.skip_char(c2); Ok(c2) @@ -372,7 +399,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { 't' => '\t', 'n' => '\n', 'r' => '\r', - c => return Err(ParserError::UnexpectedChar(c, self.location.clone())), + c => return Err(self.unexpected_char(c)), }; self.skip_char(c); @@ -390,7 +417,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { if hexadecimal_digit_char!(c) { self.escape_sequence_to_char(|c| hexadecimal_digit_char!(c), 16) } else { - Err(ParserError::IncompleteReduction(self.location.clone())) + Err(self.incomplete_reduction()) } } @@ -416,14 +443,11 @@ impl<'a, R: CharRead> Lexer<'a, R> { if backslash_char!(c) { self.skip_char(c); u32::from_str_radix(&token, radix).map_or_else( - |_| Err(ParserError::ParseBigInt(self.location.clone())), - |n| { - char::try_from(n) - .map_err(|_| ParserError::Utf8Error(Some(self.location.clone()))) - }, + |_| Err(self.parse_big_int_error()), + |n| char::try_from(n).map_err(|_| self.located_error(ParserErrorKind::Utf8Error)), ) } else { - Err(ParserError::IncompleteReduction(self.location.clone())) + Err(self.incomplete_reduction()) } } @@ -435,7 +459,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { Ok(c) } else { if !backslash_char!(c) { - return Err(ParserError::UnexpectedChar(c, self.location.clone())); + return Err(self.unexpected_char(c)); } self.skip_char(c); @@ -466,7 +490,10 @@ impl<'a, R: CharRead> Lexer<'a, R> { self.skip_char(c); Ok(token) } else { - Err(ParserError::MissingQuote(self.location.clone())) + Err({ + let this = &self; + this.located_error(ParserErrorKind::MissingQuote) + }) } } @@ -497,7 +524,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { .map(NumberToken::Integer) } else { self.return_char(start); - Err(ParserError::ParseBigInt(self.location.clone())) + Err(self.parse_big_int_error()) } } @@ -528,7 +555,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { .map(NumberToken::Integer) } else { self.return_char(start); - Err(ParserError::ParseBigInt(self.location.clone())) + Err(self.parse_big_int_error()) } } @@ -559,7 +586,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { .map(NumberToken::Integer) } else { self.return_char(start); - Err(ParserError::ParseBigInt(self.location.clone())) + Err(self.parse_big_int_error()) } } @@ -632,14 +659,11 @@ impl<'a, R: CharRead> Lexer<'a, R> { } } } else { - return Err(ParserError::InvalidSingleQuotedCharacter( - c, - self.location.clone(), - )); + return Err(self.located_error(ParserErrorKind::InvalidSingleQuotedCharacter(c))); } } else { match self.get_back_quoted_string() { - Ok(_) => return Err(ParserError::BackQuotedString(self.location.clone())), + Ok(_) => return Err(self.located_error(ParserErrorKind::BackQuotedString)), Err(e) => return Err(e), } } @@ -677,7 +701,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { if decimal_digit_char!(c) { Ok(c) } else { - Err(ParserError::ParseBigInt(self.location.clone())) + Err(self.parse_big_int_error()) } } else { Ok(c) @@ -699,7 +723,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { .or_else(|_| { Integer::from_str_radix(token, radix) .map(|n| GInteger::Integer(arena_alloc!(n, &mut self.machine_st.arena))) - .map_err(|_| ParserError::ParseBigInt(self.location.clone())) + .map_err(|_| self.parse_big_int_error()) }) } @@ -817,7 +841,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { } else if token.starts_with('0') && token.len() == 1 { if c == 'x' { self.hexadecimal_constant(c).or_else(|e| { - if let ParserError::ParseBigInt(..) = e { + if let ParserErrorKind::ParseBigInt = e.kind { self.parse_integer(&token).map(NumberToken::Integer) } else { Err(e) @@ -825,7 +849,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { }) } else if c == 'o' { self.octal_constant(c).or_else(|e| { - if let ParserError::ParseBigInt(..) = e { + if let ParserErrorKind::ParseBigInt = e.kind { self.parse_integer(&token).map(NumberToken::Integer) } else { Err(e) @@ -833,7 +857,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { }) } else if c == 'b' { self.binary_constant(c).or_else(|e| { - if let ParserError::ParseBigInt(..) = e { + if let ParserErrorKind::ParseBigInt = e.kind { self.parse_integer(&token).map(NumberToken::Integer) } else { Err(e) @@ -862,9 +886,9 @@ impl<'a, R: CharRead> Lexer<'a, R> { self.get_single_quoted_char() .map(|c| NumberToken::Integer(GInteger::Fixnum(Fixnum::build_with(c)))) .or_else(|err| { - match err { - ParserError::UnexpectedChar('\'', ..) => {} - err => return Err(err), + match &err.kind { + ParserErrorKind::UnexpectedChar('\'', ..) => {} + _ => return Err(err), } self.return_char(c); diff --git a/src/parser/parser.rs b/src/parser/parser.rs index eda980c9..a7291908 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -254,7 +254,7 @@ pub fn read_tokens(lexer: &mut Lexer<'_, R>) -> Result, } } Err(e) if e.is_unexpected_eof() && !tokens.is_empty() => { - return Err(ParserError::IncompleteReduction(lexer.location.clone())); + return Err(lexer.incomplete_reduction()); } Err(e) => { return Err(e); @@ -697,11 +697,7 @@ impl<'a, R: CharRead> Parser<'a, R> { } else { let term = match self.terms.pop() { Some(term) => term, - _ => { - return Err(ParserError::IncompleteReduction( - self.lexer.location.clone(), - )) - } + _ => return Err(self.lexer.incomplete_reduction()), }; if self.stack[idx].priority > 1000 { @@ -714,9 +710,7 @@ impl<'a, R: CharRead> Parser<'a, R> { }; if arity > self.terms.len() { - return Err(ParserError::IncompleteReduction( - self.lexer.location.clone(), - )); + return Err(self.lexer.incomplete_reduction()); } let idx = self.terms.len() - arity; @@ -784,11 +778,7 @@ impl<'a, R: CharRead> Parser<'a, R> { let term = match self.terms.pop() { Some(term) => term, - _ => { - return Err(ParserError::IncompleteReduction( - self.lexer.location.clone(), - )) - } + _ => return Err(self.lexer.incomplete_reduction()), }; self.terms @@ -966,7 +956,7 @@ impl<'a, R: CharRead> Parser<'a, R> { self.negate_number(n, negate_rat_rc, Literal::Rational) } Token::Literal(Literal::F64(_offset, n)) if n.is_infinite() => { - return Err(ParserError::InfiniteFloat(self.lexer.location.clone())); + return Err(self.lexer.located_error(ParserErrorKind::InfiniteFloat)); } Token::Literal(Literal::F64(offset, n)) => { self.negate_number((offset, n), negate_f64, |(offset, n)| { @@ -988,25 +978,19 @@ impl<'a, R: CharRead> Parser<'a, R> { Token::OpenCT => self.shift(Token::OpenCT, 1300, DELIMITER), Token::Close => { if !self.reduce_term() && !self.reduce_brackets() { - return Err(ParserError::IncompleteReduction( - self.lexer.location.clone(), - )); + return Err(self.lexer.incomplete_reduction()); } } Token::OpenList => self.shift(Token::OpenList, 1300, DELIMITER), Token::CloseList => { if !self.reduce_list()? { - return Err(ParserError::IncompleteReduction( - self.lexer.location.clone(), - )); + return Err(self.lexer.incomplete_reduction()); } } Token::OpenCurly => self.shift(Token::OpenCurly, 1300, DELIMITER), Token::CloseCurly => { if !self.reduce_curly()? { - return Err(ParserError::IncompleteReduction( - self.lexer.location.clone(), - )); + return Err(self.lexer.incomplete_reduction()); } } Token::HeadTailSeparator => { @@ -1039,11 +1023,7 @@ impl<'a, R: CharRead> Parser<'a, R> { | Some(TokenType::OpenList) | Some(TokenType::OpenCurly) | Some(TokenType::HeadTailSeparator) - | Some(TokenType::Comma) => { - return Err(ParserError::IncompleteReduction( - self.lexer.location.clone(), - )) - } + | Some(TokenType::Comma) => return Err(self.lexer.incomplete_reduction()), _ => {} }, } @@ -1079,9 +1059,7 @@ impl<'a, R: CharRead> Parser<'a, R> { self.reduce_op(1400); if self.terms.len() > 1 || self.stack.len() > 1 { - return Err(ParserError::IncompleteReduction( - self.lexer.location.clone(), - )); + return Err(self.lexer.incomplete_reduction()); } match self.terms.pop() { @@ -1089,14 +1067,10 @@ impl<'a, R: CharRead> Parser<'a, R> { if self.terms.is_empty() { Ok(term) } else { - Err(ParserError::IncompleteReduction( - self.lexer.location.clone(), - )) + Err(self.lexer.incomplete_reduction()) } } - _ => Err(ParserError::IncompleteReduction( - self.lexer.location.clone(), - )), + _ => Err(self.lexer.incomplete_reduction()), } } } diff --git a/src/read.rs b/src/read.rs index 9f578bf8..a07f4d09 100644 --- a/src/read.rs +++ b/src/read.rs @@ -52,9 +52,7 @@ pub(crate) fn error_after_read_term( // rough overlap with errors 8.14.1.3 k) & l) of the ISO standard here if !(location.line() == prior_num_lines_read && location.column() == 0) { - return CompilationError::from(ParserError::IncompleteReduction( - parser.lexer.location.clone(), - )); + return CompilationError::from(parser.lexer.incomplete_reduction()); } } From d8c6fa1fe572861c5dcc733f864fc4dfba83f3a3 Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 24 Jan 2026 03:32:42 +0100 Subject: [PATCH 5/7] don't expose lexical error and provide location --- src/parser/ast.rs | 13 ++----------- src/parser/lexer.rs | 29 ++++++++++++++++------------- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/parser/ast.rs b/src/parser/ast.rs index 18f2335d..f9aa94f9 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -461,7 +461,7 @@ pub enum ParserErrorKind { IncompleteReduction, InfiniteFloat, InvalidSingleQuotedCharacter(char), - LexicalError(lexical::Error), + ParseFloat, MissingQuote, NonPrologChar, ParseBigInt, @@ -492,7 +492,7 @@ impl ParserError { atom!("invalid_data") } ParserErrorKind::IO(_) => atom!("input_output_error"), - ParserErrorKind::LexicalError(_) => atom!("lexical_error"), + ParserErrorKind::ParseFloat => atom!("parse_float"), ParserErrorKind::MissingQuote => atom!("missing_quote"), ParserErrorKind::NonPrologChar => atom!("non_prolog_character"), ParserErrorKind::ParseBigInt => atom!("cannot_parse_big_int"), @@ -519,15 +519,6 @@ impl ParserError { } } -impl From for ParserError { - fn from(e: lexical::Error) -> ParserError { - ParserError { - location: None, - kind: ParserErrorKind::LexicalError(e), - } - } -} - impl From for ParserError { fn from(e: IOError) -> ParserError { ParserError { diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs index 0d3f8941..e617c7d9 100644 --- a/src/parser/lexer.rs +++ b/src/parser/lexer.rs @@ -684,7 +684,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { ) -> Result<(F64Offset, OrderedFloat), ParserError> { self.return_char(token.pop().unwrap()); - let n = parse_float_lossy(&token)?; + let n = self.parse_float_lossy(&token)?; let offset = float_alloc!(n, self.machine_st.arena); Ok((offset, OrderedFloat(n))) @@ -821,7 +821,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { } } - let n = parse_float_lossy(&token)?; + let n = self.parse_float_lossy(&token)?; let offset = float_alloc!(n, self.machine_st.arena); Ok(NumberToken::Float(offset, OrderedFloat(n))) @@ -830,7 +830,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { .map(|(offset, fl)| NumberToken::Float(offset, fl)) } } else { - let n = parse_float_lossy(&token)?; + let n = self.parse_float_lossy(&token)?; let offset = float_alloc!(n, self.machine_st.arena); Ok(NumberToken::Float(offset, OrderedFloat(n))) } @@ -969,7 +969,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { Ok(NumberToken::Partial(token_string)) => match self.parse_integer(&token_string) { Ok(n) => Ok(Token::Literal(n.to_literal())), Err(_) => { - let n = parse_float_lossy(&token_string)?; + let n = self.parse_float_lossy(&token_string)?; let offset = float_alloc!(n, self.machine_st.arena); Ok(Token::Literal(Literal::F64(offset, OrderedFloat(n)))) } @@ -1083,14 +1083,17 @@ impl<'a, R: CharRead> Lexer<'a, R> { Err(e) => Err(e), } } -} -fn parse_float_lossy(token: &str) -> Result { - const FORMAT: u128 = lexical::format::STANDARD; - let options = lexical::ParseFloatOptions::builder() - .lossy(true) - .build() - .unwrap(); - let n = lexical::parse_with_options::(token.as_bytes(), &options)?; - Ok(n) + fn parse_float_lossy(&self, token: &str) -> Result { + const FORMAT: u128 = lexical::format::STANDARD; + let Ok(options) = lexical::ParseFloatOptions::builder().lossy(true).build() else { + return Err(self.located_error(ParserErrorKind::ParseFloat)); + }; + + let Ok(n) = lexical::parse_with_options::(token.as_bytes(), &options) + else { + return Err(self.located_error(ParserErrorKind::ParseFloat)); + }; + Ok(n) + } } From dfad71bc6e1a9bd84f610c143e0bfcd15560b387 Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 24 Jan 2026 04:13:26 +0100 Subject: [PATCH 6/7] fix some lint warnings --- src/debray_allocator.rs | 2 +- src/parser/ast.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index 30fae204..6988420f 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -106,7 +106,7 @@ impl BranchStack { let branch_num = self .last() .map(|occurrences| occurrences.current_branch_num.clone()) - .unwrap_or_else(|| BranchNumber::default()); + .unwrap_or_default(); BranchDesignator { branch_num } } diff --git a/src/parser/ast.rs b/src/parser/ast.rs index f9aa94f9..c8d046e7 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -4,7 +4,6 @@ use crate::arena::*; use crate::atom_table::*; use crate::offset_table::*; -use crate::parser::char_reader::*; use crate::types::HeapCellValueTag; use std::cell::{Cell, Ref, RefCell, RefMut}; From 65aadb3b88b9b7a128dee4e8bb279906d2427b40 Mon Sep 17 00:00:00 2001 From: Skgland Date: Sat, 24 Jan 2026 04:20:13 +0100 Subject: [PATCH 7/7] reduce visibility to pub(crate) to prevent accidentally exposing --- src/parser/ast.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/parser/ast.rs b/src/parser/ast.rs index c8d046e7..05d459dd 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -454,7 +454,7 @@ pub struct ParserError { #[allow(dead_code)] #[derive(Debug)] #[non_exhaustive] -pub enum ParserErrorKind { +pub(crate) enum ParserErrorKind { BackQuotedString, IO(IOError), IncompleteReduction, @@ -470,11 +470,11 @@ pub enum ParserErrorKind { } impl ParserError { - pub fn location(&self) -> Option { + pub(crate) fn location(&self) -> Option { self.location.as_ref().cloned() } - pub fn as_atom(&self) -> Atom { + pub(crate) fn as_atom(&self) -> Atom { match &self.kind { ParserErrorKind::BackQuotedString => atom!("back_quoted_string"), ParserErrorKind::IncompleteReduction => atom!("incomplete_reduction"), @@ -501,7 +501,7 @@ impl ParserError { } #[inline] - pub fn unexpected_eof() -> Self { + pub(crate) fn unexpected_eof() -> Self { ParserError { location: None, kind: ParserErrorKind::IO(std::io::Error::from(ErrorKind::UnexpectedEof)), @@ -509,7 +509,7 @@ impl ParserError { } #[inline] - pub fn is_unexpected_eof(&self) -> bool { + pub(crate) fn is_unexpected_eof(&self) -> bool { if let ParserErrorKind::IO(e) = &self.kind { e.kind() == ErrorKind::UnexpectedEof } else {