#[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
}
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))]
)
]
)
}
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,
}
}
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()));
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()));
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) => {
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,
}
}
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())
}
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()
}
}
Self {
reader: src,
machine_st,
- line_num: 0,
- col_num: 0,
+ location: Location::BOF,
}
}
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;
}
}
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);
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('/');
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)
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)
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()))
}
}
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)
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)
'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);
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()))
}
}
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()))
}
}
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);
self.skip_char(c);
Ok(token)
} else {
- Err(ParserError::MissingQuote(self.line_num, self.col_num))
+ Err(ParserError::MissingQuote(self.location.clone()))
}
}
.map(NumberToken::Integer)
} else {
self.return_char(start);
- Err(ParserError::ParseBigInt(self.line_num, self.col_num))
+ Err(ParserError::ParseBigInt(self.location.clone()))
}
}
.map(NumberToken::Integer)
} else {
self.return_char(start);
- Err(ParserError::ParseBigInt(self.line_num, self.col_num))
+ Err(ParserError::ParseBigInt(self.location.clone()))
}
}
.map(NumberToken::Integer)
} else {
self.return_char(start);
- Err(ParserError::ParseBigInt(self.line_num, self.col_num))
+ Err(ParserError::ParseBigInt(self.location.clone()))
}
}
}
} 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),
}
}
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)
.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()))
})
}
}
}
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);
Some(term) => term,
_ => {
return Err(ParserError::IncompleteReduction(
- self.lexer.line_num,
- self.lexer.col_num,
+ self.lexer.location.clone(),
))
}
};
if arity > self.terms.len() {
return Err(ParserError::IncompleteReduction(
- self.lexer.line_num,
- self.lexer.col_num,
+ self.lexer.location.clone(),
));
}
Some(term) => term,
_ => {
return Err(ParserError::IncompleteReduction(
- self.lexer.line_num,
- self.lexer.col_num,
+ self.lexer.location.clone(),
))
}
};
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)| {
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(),
));
}
}
Token::CloseList => {
if !self.reduce_list()? {
return Err(ParserError::IncompleteReduction(
- self.lexer.line_num,
- self.lexer.col_num,
+ self.lexer.location.clone(),
));
}
}
Token::CloseCurly => {
if !self.reduce_curly()? {
return Err(ParserError::IncompleteReduction(
- self.lexer.line_num,
- self.lexer.col_num,
+ self.lexer.location.clone(),
));
}
}
| Some(TokenType::HeadTailSeparator)
| Some(TokenType::Comma) => {
return Err(ParserError::IncompleteReduction(
- self.lexer.line_num,
- self.lexer.col_num,
+ self.lexer.location.clone(),
))
}
_ => {}
#[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.
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(),
));
}
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(),
)),
}
}
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(),
+ ));
}
}