let value = self.machine_st.registers[2];
unify_fn!(&mut self.machine_st, value, heap_loc_as_cell!(offset.heap_loc));
}
- Err(CompilationError::ParserError(ParserError::UnexpectedEOF)) => {
+ Err(CompilationError::ParserError(e)) if e.is_unexpected_eof() => {
let value = self.machine_st.registers[2];
self.machine_st.unify_atom(atom!("end_of_file"), value);
}
functor!(atom!("no_such_module"), [atom(module_name)])
}
&CompilationError::InvalidRuleHead => {
-
functor!(atom!("invalid_head_of_rule")) // TODO: type_error(callable, _).
}
&CompilationError::InvalidUseModuleDecl => {
return Ok(unify_fn!(*self, var_names_offset, var_names_addr));
}
Err(err) => {
- if let CompilationError::ParserError(ParserError::UnexpectedEOF) = err {
- self.eof_action(
- self.registers[2],
- stream,
- atom!("read_term"),
- 3,
- )?;
-
- if stream.options().eof_action() == EOFAction::Reset {
- if self.fail == false {
- continue;
+ match err {
+ CompilationError::ParserError(e) if e.is_unexpected_eof() => {
+ self.eof_action(
+ self.registers[2],
+ stream,
+ atom!("read_term"),
+ 3,
+ )?;
+
+ if stream.options().eof_action() == EOFAction::Reset {
+ if self.fail == false {
+ continue;
+ }
}
- }
- return Ok(());
+ return Ok(());
+ }
+ _ => {}
}
let stub = functor_stub(atom!("read_term"), 3);
}
}
- pub(crate) fn open_parsing_stream(
- &mut self,
- mut stream: Stream,
- stub_name: Atom,
- stub_arity: usize,
- ) -> Result<Stream, MachineStub> {
+ pub(crate) fn open_parsing_stream(&mut self, mut stream: Stream) -> Result<Stream, ParserError> {
match stream.peek_char() {
None => Ok(stream), // empty stream is handled gracefully by Lexer::eof
- Some(Err(e)) => {
- let err = self.session_error(SessionError::from(e));
- let stub = functor_stub(stub_name, stub_arity);
-
- Err(self.error_form(err, stub))
- }
+ Some(Err(e)) => Err(ParserError::IO(e)),
Some(Ok(c)) => {
if c == '\u{feff}' {
// skip UTF-8 BOM
loop {
match lexer.lookahead_char() {
- Err(ParserError::UnexpectedEOF) => {
+ Err(e) if e.is_unexpected_eof() => {
let mut parser = Parser::from_lexer(lexer);
let op_dir = CompositeOpDir::new(&indices.op_dir, None);
}
let stub_gen = || functor_stub(atom!("get_char"), 2);
- let mut iter = self.machine_st.open_parsing_stream(stream, atom!("get_char"), 2)?;
+ let result = self.machine_st.open_parsing_stream(stream);
let addr = if addr.is_var() {
addr
)
};
- loop {
- let result = iter.read_char();
+ let mut iter = match result {
+ Ok(iter) => iter,
+ Err(e) => {
+ if e.is_unexpected_eof() {
+ self.machine_st.unify_atom(atom!("end_of_file"), addr);
+ return Ok(());
+ } else {
+ let err = self.machine_st.session_error(SessionError::from(e));
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ }
+ };
- match result {
- Some(Ok('\u{0}')) | Some(Err(_)) | None => {
+ loop {
+ match iter.read_char() {
+ Some(Ok(c)) => {
+ self.machine_st.unify_char(c, addr);
+ break;
+ }
+ _ => {
self.machine_st.eof_action(
self.machine_st.registers[2],
stream,
break;
}
}
- Some(Ok(c)) => {
- self.machine_st.unify_char(c, addr);
- break;
- }
}
}
string.push(c as char);
}
} else {
- let mut iter = self.machine_st.open_parsing_stream(stream, atom!("get_n_chars"), 2)?;
+ let mut iter = self.machine_st.open_parsing_stream(stream)
+ .map_err(|e| {
+ let err = self.machine_st.session_error(SessionError::from(e));
+ let stub = functor_stub(atom!("get_n_chars"), 2);
+
+ self.machine_st.error_form(err, stub)
+ })?;
for _ in 0..num {
let result = iter.read_char();
}
};
- let mut iter = self.machine_st.open_parsing_stream(stream.clone(), atom!("get_code"), 2)?;
+ let mut iter = self.machine_st.open_parsing_stream(stream)
+ .map_err(|e| {
+ let err = self.machine_st.session_error(SessionError::from(e));
+ let stub = functor_stub(atom!("get_code"), 2);
+
+ self.machine_st.error_form(err, stub)
+ })?;
loop {
let result = iter.read_char();
impl TermStream for InlineTermStream {
fn next(&mut self, _: &CompositeOpDir) -> Result<Term, CompilationError> {
- Err(CompilationError::from(ParserError::UnexpectedEOF))
+ Err(CompilationError::from(ParserError::unexpected_eof()))
}
fn eof(&mut self) -> Result<bool, CompilationError> {
- Ok(true)
+ Ok(true)
}
fn listing_src(&self) -> &ListingSource {
- &ListingSource::User
+ &ListingSource::User
}
}
use std::cell::{Cell, Ref, RefCell, RefMut};
use std::fmt;
use std::hash::{Hash, Hasher};
-use std::io::{Error as IOError};
+use std::io::{Error as IOError, ErrorKind};
use std::ops::{Deref, Neg};
use std::rc::Rc;
use std::vec::Vec;
NonPrologChar(usize, usize),
ParseBigInt(usize, usize),
UnexpectedChar(char, usize, usize),
- UnexpectedEOF,
+ // UnexpectedEOF,
Utf8Error(usize, usize),
}
ParserError::BackQuotedString(..) => atom!("back_quoted_string"),
ParserError::IncompleteReduction(..) => atom!("incomplete_reduction"),
ParserError::InvalidSingleQuotedCharacter(..) => atom!("invalid_single_quoted_character"),
+ ParserError::IO(e) if e.kind() == ErrorKind::UnexpectedEof => atom!("unexpected_end_of_file"),
ParserError::IO(_) => atom!("input_output_error"),
- ParserError::LexicalError(_) => atom!("lexical_error"), // TODO: ?
+ 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::UnexpectedEOF => atom!("unexpected_end_of_file"),
ParserError::Utf8Error(..) => atom!("utf8_conversion_error"),
}
}
+
+ #[inline]
+ pub fn unexpected_eof() -> Self {
+ ParserError::IO(std::io::Error::from(ErrorKind::UnexpectedEof))
+ }
+
+ #[inline]
+ pub fn is_unexpected_eof(&self) -> bool {
+ if let ParserError::IO(e) = self {
+ e.kind() == ErrorKind::UnexpectedEof
+ } else {
+ false
+ }
+ }
}
impl From<lexical::Error> for ParserError {
// Branch using `>=` instead of the more correct `==`
// to tell the compiler that the pos..cap slice is always valid.
if self.pos >= self.buf.len() {
- debug_assert!(self.pos >= self.buf.len());
-
self.buf.clear();
let mut word = [0u8; std::mem::size_of::<char>()];
return Ok(true);
}
Ok(c) => c,
- Err($crate::parser::ast::ParserError::UnexpectedEOF) => return Ok(true),
+ Err(e) if e.is_unexpected_eof() => return Ok(true),
Err(e) => return Err(e),
}
};
pub fn lookahead_char(&mut self) -> Result<char, ParserError> {
match self.reader.peek_char() {
Some(Ok(c)) => Ok(c),
- _ => Err(ParserError::UnexpectedEOF)
+ _ => Err(ParserError::unexpected_eof())
}
}
pub fn read_char(&mut self) -> Result<char, ParserError> {
match self.reader.read_char() {
Some(Ok(c)) => Ok(c),
- _ => Err(ParserError::UnexpectedEOF)
+ _ => Err(ParserError::unexpected_eof())
}
}
let mut c = self.lookahead_char()?;
- let mut comment_loop = || {
+ let mut comment_loop = || -> Result<(), ParserError> {
loop {
while !comment_2_char!(c) {
self.skip_char(c);
};
match comment_loop() {
- Err(ParserError::UnexpectedEOF) => {
+ Err(e) if e.is_unexpected_eof() => {
return Err(ParserError::IncompleteReduction(self.line_num, self.col_num));
}
Err(e) => {
return Ok(Token::End);
}
- Err(ParserError::UnexpectedEOF) => {
+ Err(e) if e.is_unexpected_eof() => {
return Ok(Token::End);
}
_ => {
}
if c == '\u{0}' {
- return Err(ParserError::UnexpectedEOF);
+ return Err(ParserError::unexpected_eof())
}
self.name_token(c)
break;
}
}
- Err(ParserError::UnexpectedEOF) if !tokens.is_empty() => {
+ Err(e) if e.is_unexpected_eof() && !tokens.is_empty() => {
return Err(ParserError::IncompleteReduction(
lexer.line_num,
lexer.col_num,
}) = get_op_desc(name, op_dir)
{
if (pre > 0 && inf + post > 0) || is_negate!(spec) {
- match self.tokens.last().ok_or(ParserError::UnexpectedEOF)? {
+ match self.tokens.last().ok_or(ParserError::unexpected_eof())? {
// do this when layout hasn't been inserted,
// ie. why we don't match on Token::Open.
Token::OpenCT => {
Ok(self.pending_input.get_ref().get_ref().len())
}
- Err(ReadlineError::Eof) => Ok(0),
+ Err(ReadlineError::Eof) => Err(Error::from(ErrorKind::UnexpectedEof)),
Err(e) => Err(Error::new(ErrorKind::InvalidInput, e)),
}
}
loop {
match byte {
- Some(0) => {
- return Ok(0);
- }
Some(b) => {
return Ok(b);
}
Err(e) => {
return Err(e);
}
- Ok(0) => {
- self.pending_input.get_mut().get_mut().push('\u{0}');
- return Ok(0);
- }
_ => {
set_prompt(false);
}
fn peek_char(&mut self) -> Option<std::io::Result<char>> {
loop {
match self.pending_input.peek_char() {
- Some(Ok('\u{0}')) => {
- return Some(Ok('\u{0}'));
- }
Some(Ok(c)) => {
return Some(Ok(c));
}
Err(e) => {
return Some(Err(e));
}
- Ok(0) => {
- self.pending_input.get_mut().get_mut().push('\u{0}');
- return Some(Ok('\u{0}'));
- }
_ => {
set_prompt(false);
}