diff --git a/src/main.rs b/src/main.rs index 377f6aa..bc390f2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,7 +40,14 @@ mod timer; // mod tracer; 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 nom::bytes::complete::take_until; @@ -261,8 +268,8 @@ fn main() { let ident = ident.map(|v| v.to_string()); let scene = parse_scene(&arena, &mut events, ident.as_deref()).unwrap_or_else(|e| { - println!("Parse error: {}", e); - // e.print(&psy_contents); + print!("Parse error: "); + e.print(&mut io::BufReader::new(File::open(file_path).unwrap())); panic!("Parse error."); }); diff --git a/src/parse/psy.rs b/src/parse/psy.rs index c631255..6b2bd0f 100644 --- a/src/parse/psy.rs +++ b/src/parse/psy.rs @@ -32,23 +32,22 @@ pub enum PsyError { // The first usize for all errors is their byte offset // into the psy content where they occured. UnknownError(usize), - UnknownVariant(usize, String), // Error message - ExpectedInternalNode(usize, String), // Error message - ExpectedLeafNode(usize, String), // Error message - ExpectedIdent(usize, String), // Error message - MissingNode(usize, String), // Error message - IncorrectLeafData(usize, String), // Error message - WrongNodeCount(usize, String), // Error message - InstancedMissingData(usize, String, String), // Error message, data name - ExpectedInternalNodeClose(usize, String), + UnknownVariant(usize, String), // Error message + ExpectedInternalNode(usize, String), // Error message + ExpectedLeafNode(usize, String), // Error message + ExpectedIdent(usize, String), // Error message + MissingNode(usize, String), // Error message + IncorrectLeafData(usize, String), // Error message + WrongNodeCount(usize, String), // Error message + ExpectedInternalNodeClose(usize, String), // Error message ReaderError(data_tree::Error), } impl PsyError { - pub fn print(&self, psy_content: &str) { + pub fn print(&self, psy_content: impl BufRead) { match self { PsyError::UnknownError(offset) => { - let line = line_count_to_byte_offset(psy_content, *offset); + let line = byte_offset_to_line_char(psy_content, *offset); println!( "Line {}: Unknown parse error. If you get this message, please report \ it to the developers so they can improve the error messages.", @@ -57,46 +56,87 @@ impl PsyError { } 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); } 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); } 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); } 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); } 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); } 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); } 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); } - PsyError::InstancedMissingData(offset, error, data_name) => { - let line = line_count_to_byte_offset(psy_content, *offset); - println!("Line {}: {} Data name: '{}'", line, error, data_name); + PsyError::ExpectedInternalNodeClose(offset, error) => { + let line = byte_offset_to_line_char(psy_content, *offset); + 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 for PsyError { } } -fn line_count_to_byte_offset(text: &str, offset: usize) -> usize { - text[..offset].matches('\n').count() + 1 +fn byte_offset_to_line_char(mut reader: impl BufRead, byte_offset: usize) -> usize { + 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; } //---------------------------------------------------------------- diff --git a/src/parse/psy_assembly.rs b/src/parse/psy_assembly.rs index a2a0c70..4a1eae6 100644 --- a/src/parse/psy_assembly.rs +++ b/src/parse/psy_assembly.rs @@ -100,12 +100,20 @@ pub fn parse_assembly<'a>( )); } - _ => { + Event::InnerOpen { + type_name, + byte_offset, + .. + } => { return Err(PsyError::UnknownVariant( 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.