replace pairs of usize with location struct
This commit is contained in:
@@ -20,7 +20,7 @@ pub type MachineStubGen = Box<dyn Fn(&mut MachineState) -> MachineStub>;
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct MachineError {
|
||||
stub: MachineStub,
|
||||
location: Option<(usize, usize)>, // line_num, col_num
|
||||
location: Option<Location>,
|
||||
}
|
||||
|
||||
// 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<ParserError> for CompilationError {
|
||||
}
|
||||
|
||||
impl CompilationError {
|
||||
pub(crate) fn line_and_col_num(&self) -> Option<(usize, usize)> {
|
||||
pub(crate) fn line_and_col_num(&self) -> Option<Location> {
|
||||
match self {
|
||||
CompilationError::ParserError(err) => err.line_and_col_num(),
|
||||
CompilationError::ParserError(err) => err.location(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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<Location>),
|
||||
}
|
||||
|
||||
impl ParserError {
|
||||
pub fn line_and_col_num(&self) -> Option<(usize, usize)> {
|
||||
pub fn location(&self) -> Option<Location> {
|
||||
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<IOError> for ParserError {
|
||||
|
||||
impl From<&IOError> for ParserError {
|
||||
fn from(error: &IOError) -> ParserError {
|
||||
if error.get_ref().filter(|e| e.is::<BadUtf8Error>()).is_some() {
|
||||
ParserError::Utf8Error(0, 0)
|
||||
if let Some(_utf8_error) = error
|
||||
.get_ref()
|
||||
.and_then(|e| e.downcast_ref::<BadUtf8Error>())
|
||||
{
|
||||
ParserError::Utf8Error(None)
|
||||
} else {
|
||||
ParserError::IO(error.kind().into())
|
||||
}
|
||||
|
||||
@@ -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()))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -254,10 +254,7 @@ pub fn read_tokens<R: CharRead>(lexer: &mut Lexer<'_, R>) -> Result<Vec<Token>,
|
||||
}
|
||||
}
|
||||
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(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,12 +48,13 @@ pub(crate) fn error_after_read_term<R>(
|
||||
parser: &Parser<R>,
|
||||
) -> 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(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user