Re-implemented nicer error reporting.
We lost this in the initial move to streaming parsing. All errors now (again) print out a line number and an error message.
This commit is contained in:
parent
46d0ef3b28
commit
66dcbc2e7f
13
src/main.rs
13
src/main.rs
|
@ -40,7 +40,14 @@ mod timer;
|
||||||
// mod tracer;
|
// mod tracer;
|
||||||
mod transform_stack;
|
mod transform_stack;
|
||||||
|
|
||||||
use std::{fs::File, io, io::Read, mem, path::Path, str::FromStr};
|
use std::{
|
||||||
|
fs::File,
|
||||||
|
io,
|
||||||
|
io::{Read, Seek},
|
||||||
|
mem,
|
||||||
|
path::Path,
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use nom::bytes::complete::take_until;
|
use nom::bytes::complete::take_until;
|
||||||
|
@ -261,8 +268,8 @@ fn main() {
|
||||||
let ident = ident.map(|v| v.to_string());
|
let ident = ident.map(|v| v.to_string());
|
||||||
let scene =
|
let scene =
|
||||||
parse_scene(&arena, &mut events, ident.as_deref()).unwrap_or_else(|e| {
|
parse_scene(&arena, &mut events, ident.as_deref()).unwrap_or_else(|e| {
|
||||||
println!("Parse error: {}", e);
|
print!("Parse error: ");
|
||||||
// e.print(&psy_contents);
|
e.print(&mut io::BufReader::new(File::open(file_path).unwrap()));
|
||||||
panic!("Parse error.");
|
panic!("Parse error.");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
107
src/parse/psy.rs
107
src/parse/psy.rs
|
@ -32,23 +32,22 @@ pub enum PsyError {
|
||||||
// The first usize for all errors is their byte offset
|
// The first usize for all errors is their byte offset
|
||||||
// into the psy content where they occured.
|
// into the psy content where they occured.
|
||||||
UnknownError(usize),
|
UnknownError(usize),
|
||||||
UnknownVariant(usize, String), // Error message
|
UnknownVariant(usize, String), // Error message
|
||||||
ExpectedInternalNode(usize, String), // Error message
|
ExpectedInternalNode(usize, String), // Error message
|
||||||
ExpectedLeafNode(usize, String), // Error message
|
ExpectedLeafNode(usize, String), // Error message
|
||||||
ExpectedIdent(usize, String), // Error message
|
ExpectedIdent(usize, String), // Error message
|
||||||
MissingNode(usize, String), // Error message
|
MissingNode(usize, String), // Error message
|
||||||
IncorrectLeafData(usize, String), // Error message
|
IncorrectLeafData(usize, String), // Error message
|
||||||
WrongNodeCount(usize, String), // Error message
|
WrongNodeCount(usize, String), // Error message
|
||||||
InstancedMissingData(usize, String, String), // Error message, data name
|
ExpectedInternalNodeClose(usize, String), // Error message
|
||||||
ExpectedInternalNodeClose(usize, String),
|
|
||||||
ReaderError(data_tree::Error),
|
ReaderError(data_tree::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PsyError {
|
impl PsyError {
|
||||||
pub fn print(&self, psy_content: &str) {
|
pub fn print(&self, psy_content: impl BufRead) {
|
||||||
match self {
|
match self {
|
||||||
PsyError::UnknownError(offset) => {
|
PsyError::UnknownError(offset) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
let line = byte_offset_to_line_char(psy_content, *offset);
|
||||||
println!(
|
println!(
|
||||||
"Line {}: Unknown parse error. If you get this message, please report \
|
"Line {}: Unknown parse error. If you get this message, please report \
|
||||||
it to the developers so they can improve the error messages.",
|
it to the developers so they can improve the error messages.",
|
||||||
|
@ -57,46 +56,87 @@ impl PsyError {
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyError::UnknownVariant(offset, error) => {
|
PsyError::UnknownVariant(offset, error) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
let line = byte_offset_to_line_char(psy_content, *offset);
|
||||||
println!("Line {}: {}", line, error);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyError::ExpectedInternalNode(offset, error) => {
|
PsyError::ExpectedInternalNode(offset, error) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
let line = byte_offset_to_line_char(psy_content, *offset);
|
||||||
println!("Line {}: {}", line, error);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyError::ExpectedLeafNode(offset, error) => {
|
PsyError::ExpectedLeafNode(offset, error) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
let line = byte_offset_to_line_char(psy_content, *offset);
|
||||||
println!("Line {}: {}", line, error);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyError::ExpectedIdent(offset, error) => {
|
PsyError::ExpectedIdent(offset, error) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
let line = byte_offset_to_line_char(psy_content, *offset);
|
||||||
println!("Line {}: {}", line, error);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyError::MissingNode(offset, error) => {
|
PsyError::MissingNode(offset, error) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
let line = byte_offset_to_line_char(psy_content, *offset);
|
||||||
println!("Line {}: {}", line, error);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyError::IncorrectLeafData(offset, error) => {
|
PsyError::IncorrectLeafData(offset, error) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
let line = byte_offset_to_line_char(psy_content, *offset);
|
||||||
println!("Line {}: {}", line, error);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyError::WrongNodeCount(offset, error) => {
|
PsyError::WrongNodeCount(offset, error) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
let line = byte_offset_to_line_char(psy_content, *offset);
|
||||||
println!("Line {}: {}", line, error);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
PsyError::InstancedMissingData(offset, error, data_name) => {
|
PsyError::ExpectedInternalNodeClose(offset, error) => {
|
||||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
let line = byte_offset_to_line_char(psy_content, *offset);
|
||||||
println!("Line {}: {} Data name: '{}'", line, error, data_name);
|
println!("Line {}: {}", line, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => todo!(),
|
PsyError::ReaderError(data_tree::Error::ExpectedTypeNameOrClose(offset)) => {
|
||||||
|
let line = byte_offset_to_line_char(psy_content, *offset);
|
||||||
|
println!(
|
||||||
|
"Line {}: Expected either a type name or a closing brace.",
|
||||||
|
line
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PsyError::ReaderError(data_tree::Error::ExpectedOpenOrIdent(offset)) => {
|
||||||
|
let line = byte_offset_to_line_char(psy_content, *offset);
|
||||||
|
println!(
|
||||||
|
"Line {}: Expected either an opening brace/bracket or an ident.",
|
||||||
|
line
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PsyError::ReaderError(data_tree::Error::ExpectedOpen(offset)) => {
|
||||||
|
let line = byte_offset_to_line_char(psy_content, *offset);
|
||||||
|
println!("Line {}: Expected an opening brace.", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
PsyError::ReaderError(data_tree::Error::UnexpectedClose(offset)) => {
|
||||||
|
let line = byte_offset_to_line_char(psy_content, *offset);
|
||||||
|
println!("Line {}: Encountered an unexpected closing brace.", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
PsyError::ReaderError(data_tree::Error::UnexpectedIdent(offset)) => {
|
||||||
|
let line = byte_offset_to_line_char(psy_content, *offset);
|
||||||
|
println!("Line {}: Encountered and unexpected ident.", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
PsyError::ReaderError(data_tree::Error::UnexpectedEOF) => {
|
||||||
|
let line = byte_offset_to_line_char(psy_content, std::usize::MAX);
|
||||||
|
println!(
|
||||||
|
"Line {}: Unexpected end-of-stream, data tree incomplete.",
|
||||||
|
line
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PsyError::ReaderError(data_tree::Error::IO(error)) => {
|
||||||
|
println!("IO error while parsing scene: {}", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,8 +155,27 @@ impl From<data_tree::Error> for PsyError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn line_count_to_byte_offset(text: &str, offset: usize) -> usize {
|
fn byte_offset_to_line_char(mut reader: impl BufRead, byte_offset: usize) -> usize {
|
||||||
text[..offset].matches('\n').count() + 1
|
let mut line_buf = String::new();
|
||||||
|
let mut bytes_read = 0;
|
||||||
|
let mut current_line = 1;
|
||||||
|
loop {
|
||||||
|
line_buf.clear();
|
||||||
|
if let Ok(_) = reader.read_line(&mut line_buf) {
|
||||||
|
if line_buf.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bytes_read += line_buf.len();
|
||||||
|
if byte_offset < bytes_read {
|
||||||
|
return current_line;
|
||||||
|
}
|
||||||
|
current_line += 1;
|
||||||
|
} else {
|
||||||
|
todo!(); // Handle error properly.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return current_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
|
@ -100,12 +100,20 @@ pub fn parse_assembly<'a>(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
Event::InnerOpen {
|
||||||
|
type_name,
|
||||||
|
byte_offset,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
return Err(PsyError::UnknownVariant(
|
return Err(PsyError::UnknownVariant(
|
||||||
byte_offset,
|
byte_offset,
|
||||||
"Unknown data type for Object.".into(),
|
format!("Unknown data type '{}' for Object.", type_name),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
return Err(PsyError::UnknownError(byte_offset));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Close object node.
|
// Close object node.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user