Parse errors now use Strings for error messages.
This allows the error messages to be more informative by including dynamically determined information. Also made a utility function for ensuring that nodes get closed.
This commit is contained in:
parent
4f564d1474
commit
6b188c4451
|
@ -1,377 +0,0 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use std::{io::Cursor, iter::Iterator, result::Result, slice};
|
||||
|
||||
use data_tree::{reader::DataTreeReader, Event};
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum DataTree {
|
||||
Internal {
|
||||
type_name: String,
|
||||
ident: Option<String>,
|
||||
children: Vec<DataTree>,
|
||||
byte_offset: usize,
|
||||
},
|
||||
|
||||
Leaf {
|
||||
type_name: String,
|
||||
contents: String,
|
||||
byte_offset: usize,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum ParseError {
|
||||
Other(&'static str),
|
||||
}
|
||||
|
||||
// #[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
// pub enum ParseError {
|
||||
// MissingOpener(usize),
|
||||
// MissingOpenInternal(usize),
|
||||
// MissingCloseInternal(usize),
|
||||
// MissingOpenLeaf(usize),
|
||||
// MissingCloseLeaf(usize),
|
||||
// MissingTypeName(usize),
|
||||
// UnexpectedIdent(usize),
|
||||
// UnknownToken(usize),
|
||||
// Other((usize, &'static str)),
|
||||
// }
|
||||
|
||||
impl<'a> DataTree {
|
||||
pub fn from_str(source_text: &'a str) -> Result<DataTree, ParseError> {
|
||||
let mut parser = DataTreeReader::new(Cursor::new(source_text));
|
||||
let mut items = Vec::new();
|
||||
|
||||
loop {
|
||||
let event = parser.next_event();
|
||||
match event {
|
||||
Ok(Event::InnerOpen {
|
||||
type_name,
|
||||
ident,
|
||||
byte_offset,
|
||||
}) => {
|
||||
let type_name = type_name.into();
|
||||
let ident = ident.map(|id| id.into());
|
||||
items.push(parse_node(&mut parser, type_name, ident, byte_offset)?);
|
||||
}
|
||||
Ok(Event::Leaf {
|
||||
type_name,
|
||||
contents,
|
||||
byte_offset,
|
||||
}) => return Err(ParseError::Other("Unexpected leaf value at root level.")),
|
||||
Ok(Event::InnerClose { .. }) => {
|
||||
return Err(ParseError::Other("Unexpected closing tag."))
|
||||
}
|
||||
Ok(Event::ValidEnd) => {
|
||||
break;
|
||||
}
|
||||
|
||||
Ok(Event::NeedMoreInput) | Err(_) => {
|
||||
return Err(ParseError::Other("Some error happened."))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(DataTree::Internal {
|
||||
type_name: "ROOT".into(),
|
||||
ident: None,
|
||||
children: items,
|
||||
byte_offset: 0,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn type_name(&'a self) -> &'a str {
|
||||
match self {
|
||||
DataTree::Internal { type_name, .. } | DataTree::Leaf { type_name, .. } => type_name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ident(&'a self) -> Option<&'a str> {
|
||||
match self {
|
||||
DataTree::Internal {
|
||||
ident: Some(id), ..
|
||||
} => Some(id.as_str()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn byte_offset(&'a self) -> usize {
|
||||
match self {
|
||||
DataTree::Internal { byte_offset, .. } | DataTree::Leaf { byte_offset, .. } => {
|
||||
*byte_offset
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_internal(&self) -> bool {
|
||||
match self {
|
||||
DataTree::Internal { .. } => true,
|
||||
DataTree::Leaf { .. } => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_leaf(&self) -> bool {
|
||||
match self {
|
||||
DataTree::Internal { .. } => false,
|
||||
DataTree::Leaf { .. } => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn leaf_contents(&'a self) -> Option<&'a str> {
|
||||
match self {
|
||||
DataTree::Internal { .. } => None,
|
||||
DataTree::Leaf { contents, .. } => Some(contents.as_str()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter_children(&'a self) -> slice::Iter<'a, DataTree> {
|
||||
if let DataTree::Internal { ref children, .. } = self {
|
||||
children.iter()
|
||||
} else {
|
||||
[].iter()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter_children_with_type(&'a self, type_name: &'static str) -> DataTreeFilterIter<'a> {
|
||||
if let DataTree::Internal { ref children, .. } = self {
|
||||
DataTreeFilterIter {
|
||||
type_name: type_name,
|
||||
iter: children.iter(),
|
||||
}
|
||||
} else {
|
||||
DataTreeFilterIter {
|
||||
type_name: type_name,
|
||||
iter: [].iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter_internal_children_with_type(
|
||||
&'a self,
|
||||
type_name: &'static str,
|
||||
) -> DataTreeFilterInternalIter<'a> {
|
||||
if let DataTree::Internal { ref children, .. } = *self {
|
||||
DataTreeFilterInternalIter {
|
||||
type_name: type_name,
|
||||
iter: children.iter(),
|
||||
}
|
||||
} else {
|
||||
DataTreeFilterInternalIter {
|
||||
type_name: type_name,
|
||||
iter: [].iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter_leaf_children_with_type(
|
||||
&'a self,
|
||||
type_name: &'static str,
|
||||
) -> DataTreeFilterLeafIter<'a> {
|
||||
if let DataTree::Internal { ref children, .. } = *self {
|
||||
DataTreeFilterLeafIter {
|
||||
type_name: type_name,
|
||||
iter: children.iter(),
|
||||
}
|
||||
} else {
|
||||
DataTreeFilterLeafIter {
|
||||
type_name: type_name,
|
||||
iter: [].iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For unit tests
|
||||
fn internal_data_or_panic(&'a self) -> (&'a str, Option<&'a str>, &'a Vec<DataTree>) {
|
||||
if let DataTree::Internal {
|
||||
type_name,
|
||||
ref ident,
|
||||
ref children,
|
||||
..
|
||||
} = self
|
||||
{
|
||||
(type_name, ident.as_ref().map(|id| id.as_str()), children)
|
||||
} else {
|
||||
panic!("Expected DataTree::Internal, found DataTree::Leaf")
|
||||
}
|
||||
}
|
||||
fn leaf_data_or_panic(&'a self) -> (&'a str, &'a str) {
|
||||
if let DataTree::Leaf {
|
||||
type_name,
|
||||
contents,
|
||||
..
|
||||
} = self
|
||||
{
|
||||
(type_name, contents)
|
||||
} else {
|
||||
panic!("Expected DataTree::Leaf, found DataTree::Internal")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_node<R: std::io::BufRead>(
|
||||
parser: &mut DataTreeReader<R>,
|
||||
type_name: String,
|
||||
ident: Option<String>,
|
||||
byte_offset: usize,
|
||||
) -> Result<DataTree, ParseError> {
|
||||
let mut children = Vec::new();
|
||||
loop {
|
||||
match parser.next_event() {
|
||||
Ok(Event::InnerOpen {
|
||||
type_name,
|
||||
ident,
|
||||
byte_offset,
|
||||
}) => {
|
||||
let type_name = type_name.into();
|
||||
let ident = ident.map(|id| id.into());
|
||||
children.push(parse_node(parser, type_name, ident, byte_offset)?);
|
||||
}
|
||||
Ok(Event::Leaf {
|
||||
type_name,
|
||||
contents,
|
||||
byte_offset,
|
||||
}) => {
|
||||
children.push(DataTree::Leaf {
|
||||
type_name: type_name.into(),
|
||||
contents: contents.into(),
|
||||
byte_offset: byte_offset,
|
||||
});
|
||||
}
|
||||
Ok(Event::InnerClose { .. }) => break,
|
||||
Ok(Event::ValidEnd) => {
|
||||
return Err(ParseError::Other("Unexpected end of contents."));
|
||||
}
|
||||
Ok(Event::NeedMoreInput) | Err(_) => {
|
||||
return Err(ParseError::Other("Some error happened."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(DataTree::Internal {
|
||||
type_name: type_name,
|
||||
ident: ident,
|
||||
children: children,
|
||||
byte_offset: byte_offset,
|
||||
})
|
||||
}
|
||||
|
||||
/// Splits text at approximately the given byte index,
|
||||
/// shifting it as needed to stay in bounds and be on a
|
||||
/// valid `char` break.
|
||||
fn aprx_split_at(text: &str, idx: usize) -> (&str, &str) {
|
||||
let mut idx = text.len().min(idx);
|
||||
|
||||
while !text.is_char_boundary(idx) {
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
(&text[..idx], &text[idx..])
|
||||
}
|
||||
|
||||
/// An iterator over the children of a `DataTree` node that filters out the
|
||||
/// children not matching a specified type name.
|
||||
pub struct DataTreeFilterIter<'a> {
|
||||
type_name: &'a str,
|
||||
iter: slice::Iter<'a, DataTree>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for DataTreeFilterIter<'a> {
|
||||
type Item = &'a DataTree;
|
||||
|
||||
fn next(&mut self) -> Option<&'a DataTree> {
|
||||
loop {
|
||||
if let Some(dt) = self.iter.next() {
|
||||
if dt.type_name() == self.type_name {
|
||||
return Some(dt);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the children of a `DataTree` node that filters out the
|
||||
/// children that aren't internal nodes and that don't match a specified
|
||||
/// type name.
|
||||
pub struct DataTreeFilterInternalIter<'a> {
|
||||
type_name: &'a str,
|
||||
iter: slice::Iter<'a, DataTree>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for DataTreeFilterInternalIter<'a> {
|
||||
type Item = (&'a str, Option<&'a str>, &'a Vec<DataTree>, usize);
|
||||
|
||||
fn next(&mut self) -> Option<(&'a str, Option<&'a str>, &'a Vec<DataTree>, usize)> {
|
||||
loop {
|
||||
match self.iter.next() {
|
||||
Some(DataTree::Internal {
|
||||
type_name,
|
||||
ident,
|
||||
children,
|
||||
byte_offset,
|
||||
}) => {
|
||||
if type_name == self.type_name {
|
||||
return Some((
|
||||
type_name,
|
||||
ident.as_ref().map(|id| id.as_str()),
|
||||
children,
|
||||
*byte_offset,
|
||||
));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Some(DataTree::Leaf { .. }) => {
|
||||
continue;
|
||||
}
|
||||
|
||||
None => {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the children of a `DataTree` node that filters out the
|
||||
/// children that aren't internal nodes and that don't match a specified
|
||||
/// type name.
|
||||
pub struct DataTreeFilterLeafIter<'a> {
|
||||
type_name: &'a str,
|
||||
iter: slice::Iter<'a, DataTree>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for DataTreeFilterLeafIter<'a> {
|
||||
type Item = (&'a str, &'a str, usize);
|
||||
|
||||
fn next(&mut self) -> Option<(&'a str, &'a str, usize)> {
|
||||
loop {
|
||||
match self.iter.next() {
|
||||
Some(DataTree::Internal { .. }) => {
|
||||
continue;
|
||||
}
|
||||
|
||||
Some(DataTree::Leaf {
|
||||
type_name,
|
||||
contents,
|
||||
byte_offset,
|
||||
}) => {
|
||||
if type_name == self.type_name {
|
||||
return Some((type_name, contents, *byte_offset));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
None => {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
pub mod basics;
|
||||
// mod data_tree;
|
||||
mod parse_utils;
|
||||
mod psy;
|
||||
mod psy_assembly;
|
||||
mod psy_light;
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
//! Some basic nom parsers
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::str::{self, FromStr};
|
||||
use std::{
|
||||
io::BufRead,
|
||||
str::{self, FromStr},
|
||||
};
|
||||
|
||||
use nom::{
|
||||
character::complete::{digit1, multispace0, one_of},
|
||||
|
@ -11,6 +14,10 @@ use nom::{
|
|||
IResult,
|
||||
};
|
||||
|
||||
use data_tree::{reader::DataTreeReader, Event};
|
||||
|
||||
use super::psy::{PsyError, PsyResult};
|
||||
|
||||
// ========================================================
|
||||
|
||||
pub fn ws_f32(input: &str) -> IResult<&str, f32, ()> {
|
||||
|
@ -36,6 +43,39 @@ pub fn ws_i32(input: &str) -> IResult<&str, i32, ()> {
|
|||
)(input)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
/// Ensures that we encounter a InnerClose event, and returns a useful
|
||||
/// error if we don't.
|
||||
pub fn ensure_close(events: &mut DataTreeReader<impl BufRead>) -> PsyResult<()> {
|
||||
match events.next_event()? {
|
||||
Event::InnerClose { .. } => Ok(()),
|
||||
Event::InnerOpen {
|
||||
type_name,
|
||||
byte_offset,
|
||||
..
|
||||
} => Err(PsyError::ExpectedInternalNodeClose(
|
||||
byte_offset,
|
||||
format!(
|
||||
"Expected the node to be closed, but instead found a '{}'.",
|
||||
type_name
|
||||
),
|
||||
)),
|
||||
Event::Leaf {
|
||||
type_name,
|
||||
byte_offset,
|
||||
..
|
||||
} => Err(PsyError::ExpectedInternalNodeClose(
|
||||
byte_offset,
|
||||
format!(
|
||||
"Expected the node to be closed, but instead found a '{}'.",
|
||||
type_name
|
||||
),
|
||||
)),
|
||||
_ => Err(PsyError::UnknownError(events.byte_offset())),
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================
|
||||
|
||||
#[cfg(test)]
|
156
src/parse/psy.rs
156
src/parse/psy.rs
|
@ -22,33 +22,36 @@ use crate::{
|
|||
};
|
||||
|
||||
use super::{
|
||||
basics::{ws_f32, ws_u32},
|
||||
parse_utils::{ensure_close, ws_f32, ws_u32},
|
||||
psy_assembly::parse_assembly,
|
||||
psy_light::parse_distant_disk_light,
|
||||
psy_surface_shader::parse_surface_shader,
|
||||
};
|
||||
|
||||
pub type PsyResult<T> = Result<T, PsyError>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PsyParseError {
|
||||
pub enum PsyError {
|
||||
// The first usize for all errors is their byte offset
|
||||
// into the psy content where they occured.
|
||||
UnknownError(usize),
|
||||
UnknownVariant(usize, &'static str), // Error message
|
||||
ExpectedInternalNode(usize, &'static str), // Error message
|
||||
ExpectedLeafNode(usize, &'static str), // Error message
|
||||
ExpectedIdent(usize, &'static str), // Error message
|
||||
MissingNode(usize, &'static str), // Error message
|
||||
IncorrectLeafData(usize, &'static str), // Error message
|
||||
WrongNodeCount(usize, &'static str), // Error message
|
||||
InstancedMissingData(usize, &'static str, String), // Error message, data name
|
||||
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),
|
||||
ReaderError(ReaderError),
|
||||
}
|
||||
|
||||
impl PsyParseError {
|
||||
impl PsyError {
|
||||
pub fn print(&self, psy_content: &str) {
|
||||
match *self {
|
||||
PsyParseError::UnknownError(offset) => {
|
||||
let line = line_count_to_byte_offset(psy_content, offset);
|
||||
match self {
|
||||
PsyError::UnknownError(offset) => {
|
||||
let line = line_count_to_byte_offset(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.",
|
||||
|
@ -56,43 +59,43 @@ impl PsyParseError {
|
|||
);
|
||||
}
|
||||
|
||||
PsyParseError::UnknownVariant(offset, error) => {
|
||||
let line = line_count_to_byte_offset(psy_content, offset);
|
||||
PsyError::UnknownVariant(offset, error) => {
|
||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||
println!("Line {}: {}", line, error);
|
||||
}
|
||||
|
||||
PsyParseError::ExpectedInternalNode(offset, error) => {
|
||||
let line = line_count_to_byte_offset(psy_content, offset);
|
||||
PsyError::ExpectedInternalNode(offset, error) => {
|
||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||
println!("Line {}: {}", line, error);
|
||||
}
|
||||
|
||||
PsyParseError::ExpectedLeafNode(offset, error) => {
|
||||
let line = line_count_to_byte_offset(psy_content, offset);
|
||||
PsyError::ExpectedLeafNode(offset, error) => {
|
||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||
println!("Line {}: {}", line, error);
|
||||
}
|
||||
|
||||
PsyParseError::ExpectedIdent(offset, error) => {
|
||||
let line = line_count_to_byte_offset(psy_content, offset);
|
||||
PsyError::ExpectedIdent(offset, error) => {
|
||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||
println!("Line {}: {}", line, error);
|
||||
}
|
||||
|
||||
PsyParseError::MissingNode(offset, error) => {
|
||||
let line = line_count_to_byte_offset(psy_content, offset);
|
||||
PsyError::MissingNode(offset, error) => {
|
||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||
println!("Line {}: {}", line, error);
|
||||
}
|
||||
|
||||
PsyParseError::IncorrectLeafData(offset, error) => {
|
||||
let line = line_count_to_byte_offset(psy_content, offset);
|
||||
PsyError::IncorrectLeafData(offset, error) => {
|
||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||
println!("Line {}: {}", line, error);
|
||||
}
|
||||
|
||||
PsyParseError::WrongNodeCount(offset, error) => {
|
||||
let line = line_count_to_byte_offset(psy_content, offset);
|
||||
PsyError::WrongNodeCount(offset, error) => {
|
||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||
println!("Line {}: {}", line, error);
|
||||
}
|
||||
|
||||
PsyParseError::InstancedMissingData(offset, error, ref data_name) => {
|
||||
let line = line_count_to_byte_offset(psy_content, offset);
|
||||
PsyError::InstancedMissingData(offset, error, data_name) => {
|
||||
let line = line_count_to_byte_offset(psy_content, *offset);
|
||||
println!("Line {}: {} Data name: '{}'", line, error, data_name);
|
||||
}
|
||||
|
||||
|
@ -101,17 +104,17 @@ impl PsyParseError {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for PsyParseError {}
|
||||
impl std::error::Error for PsyError {}
|
||||
|
||||
impl std::fmt::Display for PsyParseError {
|
||||
impl std::fmt::Display for PsyError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ReaderError> for PsyParseError {
|
||||
impl From<ReaderError> for PsyError {
|
||||
fn from(e: ReaderError) -> Self {
|
||||
PsyParseError::ReaderError(e)
|
||||
PsyError::ReaderError(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,7 +129,7 @@ pub fn parse_scene<'a>(
|
|||
arena: &'a Arena,
|
||||
events: &mut DataTreeReader<impl BufRead>,
|
||||
_ident: Option<&str>,
|
||||
) -> Result<Scene<'a>, PsyParseError> {
|
||||
) -> PsyResult<Scene<'a>> {
|
||||
// Get output info.
|
||||
let _output_info = if let Event::InnerOpen {
|
||||
type_name: "Output",
|
||||
|
@ -226,7 +229,7 @@ pub fn parse_scene<'a>(
|
|||
return Ok(scene);
|
||||
}
|
||||
|
||||
fn parse_output_info(events: &mut DataTreeReader<impl BufRead>) -> Result<String, PsyParseError> {
|
||||
fn parse_output_info(events: &mut DataTreeReader<impl BufRead>) -> PsyResult<String> {
|
||||
let mut found_path = false;
|
||||
let mut path = String::new();
|
||||
loop {
|
||||
|
@ -239,15 +242,15 @@ fn parse_output_info(events: &mut DataTreeReader<impl BufRead>) -> Result<String
|
|||
// Trim and validate
|
||||
let tc = contents.trim();
|
||||
if tc.chars().count() < 2 {
|
||||
return Err(PsyParseError::IncorrectLeafData(
|
||||
return Err(PsyError::IncorrectLeafData(
|
||||
byte_offset,
|
||||
"File path format is incorrect.",
|
||||
"File path format is incorrect.".into(),
|
||||
));
|
||||
}
|
||||
if tc.chars().nth(0).unwrap() != '"' || !tc.ends_with('"') {
|
||||
return Err(PsyParseError::IncorrectLeafData(
|
||||
return Err(PsyError::IncorrectLeafData(
|
||||
byte_offset,
|
||||
"File paths must be surrounded by quotes.",
|
||||
"File paths must be surrounded by quotes.".into(),
|
||||
));
|
||||
}
|
||||
let len = tc.len();
|
||||
|
@ -272,7 +275,7 @@ fn parse_output_info(events: &mut DataTreeReader<impl BufRead>) -> Result<String
|
|||
if found_path {
|
||||
return Ok(path);
|
||||
} else {
|
||||
// return Err(PsyParseError::MissingNode(
|
||||
// return Err(PsyError::MissingNode(
|
||||
// tree.byte_offset(),
|
||||
// "Output section must contain a Path.",
|
||||
// ));
|
||||
|
@ -282,7 +285,7 @@ fn parse_output_info(events: &mut DataTreeReader<impl BufRead>) -> Result<String
|
|||
|
||||
fn parse_render_settings(
|
||||
events: &mut DataTreeReader<impl BufRead>,
|
||||
) -> Result<((u32, u32), u32, u32), PsyParseError> {
|
||||
) -> PsyResult<((u32, u32), u32, u32)> {
|
||||
let mut found_res = false;
|
||||
let mut found_spp = false;
|
||||
let mut res = (0, 0);
|
||||
|
@ -302,10 +305,11 @@ fn parse_render_settings(
|
|||
res = (w, h);
|
||||
} else {
|
||||
// Found Resolution, but its contents is not in the right format
|
||||
return Err(PsyParseError::IncorrectLeafData(
|
||||
return Err(PsyError::IncorrectLeafData(
|
||||
byte_offset,
|
||||
"Resolution should be specified with two \
|
||||
integers in the form '[width height]'.",
|
||||
integers in the form '[width height]'."
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -321,11 +325,11 @@ fn parse_render_settings(
|
|||
spp = n;
|
||||
} else {
|
||||
// Found SamplesPerPixel, but its contents is not in the right format
|
||||
return Err(PsyParseError::IncorrectLeafData(
|
||||
return Err(PsyError::IncorrectLeafData(
|
||||
byte_offset,
|
||||
"SamplesPerPixel should be \
|
||||
an integer specified in \
|
||||
the form '[samples]'.",
|
||||
"SamplesPerPixel should be an integer specified in \
|
||||
the form '[samples]'."
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -340,11 +344,11 @@ fn parse_render_settings(
|
|||
seed = n;
|
||||
} else {
|
||||
// Found Seed, but its contents is not in the right format
|
||||
return Err(PsyParseError::IncorrectLeafData(
|
||||
return Err(PsyError::IncorrectLeafData(
|
||||
byte_offset,
|
||||
"Seed should be an integer \
|
||||
specified in the form \
|
||||
'[samples]'.",
|
||||
"Seed should be an integer specified in the form \
|
||||
'[samples]'."
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -362,7 +366,7 @@ fn parse_render_settings(
|
|||
if found_res && found_spp {
|
||||
return Ok((res, spp, seed));
|
||||
} else {
|
||||
// return Err(PsyParseError::MissingNode(
|
||||
// return Err(PsyError::MissingNode(
|
||||
// tree.byte_offset(),
|
||||
// "RenderSettings must have both Resolution and \
|
||||
// SamplesPerPixel specified.",
|
||||
|
@ -374,7 +378,7 @@ fn parse_render_settings(
|
|||
fn parse_camera<'a>(
|
||||
arena: &'a Arena,
|
||||
events: &mut DataTreeReader<impl BufRead>,
|
||||
) -> Result<Camera<'a>, PsyParseError> {
|
||||
) -> PsyResult<Camera<'a>> {
|
||||
let mut mats = Vec::new();
|
||||
let mut fovs = Vec::new();
|
||||
let mut focus_distances = Vec::new();
|
||||
|
@ -393,11 +397,11 @@ fn parse_camera<'a>(
|
|||
fovs.push(fov * (f32::consts::PI / 180.0));
|
||||
} else {
|
||||
// Found Fov, but its contents is not in the right format
|
||||
return Err(PsyParseError::IncorrectLeafData(
|
||||
return Err(PsyError::IncorrectLeafData(
|
||||
byte_offset,
|
||||
"Fov should be a decimal \
|
||||
number specified in the \
|
||||
form '[fov]'.",
|
||||
"Fov should be a decimal number specified in the \
|
||||
form '[fov]'."
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -412,11 +416,11 @@ fn parse_camera<'a>(
|
|||
focus_distances.push(fd);
|
||||
} else {
|
||||
// Found FocalDistance, but its contents is not in the right format
|
||||
return Err(PsyParseError::IncorrectLeafData(
|
||||
return Err(PsyError::IncorrectLeafData(
|
||||
byte_offset,
|
||||
"FocalDistance should be a \
|
||||
decimal number specified \
|
||||
in the form '[fov]'.",
|
||||
"FocalDistance should be a decimal number specified \
|
||||
in the form '[fov]'."
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -431,11 +435,11 @@ fn parse_camera<'a>(
|
|||
aperture_radii.push(ar);
|
||||
} else {
|
||||
// Found ApertureRadius, but its contents is not in the right format
|
||||
return Err(PsyParseError::IncorrectLeafData(
|
||||
return Err(PsyError::IncorrectLeafData(
|
||||
byte_offset,
|
||||
"ApertureRadius should be a \
|
||||
decimal number specified \
|
||||
in the form '[fov]'.",
|
||||
"ApertureRadius should be a decimal number specified \
|
||||
in the form '[fov]'."
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -476,7 +480,7 @@ fn parse_camera<'a>(
|
|||
fn parse_world<'a>(
|
||||
arena: &'a Arena,
|
||||
events: &mut DataTreeReader<impl BufRead>,
|
||||
) -> Result<World<'a>, PsyParseError> {
|
||||
) -> PsyResult<World<'a>> {
|
||||
let mut background_color = None;
|
||||
let mut lights: Vec<&dyn WorldLightSource> = Vec::new();
|
||||
|
||||
|
@ -524,10 +528,7 @@ fn parse_world<'a>(
|
|||
}
|
||||
|
||||
// Close it out.
|
||||
if let Event::InnerClose { .. } = events.next_event()? {
|
||||
} else {
|
||||
todo!(); // Return error.
|
||||
}
|
||||
ensure_close(events)?;
|
||||
}
|
||||
|
||||
// Parse light sources
|
||||
|
@ -568,7 +569,7 @@ fn parse_world<'a>(
|
|||
fn parse_shaders<'a>(
|
||||
arena: &'a Arena,
|
||||
events: &mut DataTreeReader<impl BufRead>,
|
||||
) -> Result<HashMap<String, Box<dyn SurfaceShader>>, PsyParseError> {
|
||||
) -> PsyResult<HashMap<String, Box<dyn SurfaceShader>>> {
|
||||
let mut shaders = HashMap::new();
|
||||
loop {
|
||||
match events.next_event()? {
|
||||
|
@ -602,7 +603,7 @@ fn parse_shaders<'a>(
|
|||
return Ok(shaders);
|
||||
}
|
||||
|
||||
pub fn parse_matrix(contents: &str) -> Result<Matrix4x4, PsyParseError> {
|
||||
pub fn parse_matrix(contents: &str) -> PsyResult<Matrix4x4> {
|
||||
if let IResult::Ok((leftover, ns)) = all_consuming(tuple((
|
||||
ws_f32, ws_f32, ws_f32, ws_f32, ws_f32, ws_f32, ws_f32, ws_f32, ws_f32, ws_f32, ws_f32,
|
||||
ws_f32, ws_f32, ws_f32, ws_f32, ws_f32,
|
||||
|
@ -619,15 +620,16 @@ pub fn parse_matrix(contents: &str) -> Result<Matrix4x4, PsyParseError> {
|
|||
todo!(); // Return an error.
|
||||
}
|
||||
|
||||
pub fn make_transform_format_error(byte_offset: usize) -> PsyParseError {
|
||||
PsyParseError::IncorrectLeafData(
|
||||
pub fn make_transform_format_error(byte_offset: usize) -> PsyError {
|
||||
PsyError::IncorrectLeafData(
|
||||
byte_offset,
|
||||
"Transform should be sixteen integers specified in \
|
||||
the form '[# # # # # # # # # # # # # # # #]'.",
|
||||
the form '[# # # # # # # # # # # # # # # #]'."
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn parse_color(contents: &str) -> Result<Color, PsyParseError> {
|
||||
pub fn parse_color(contents: &str) -> PsyResult<Color> {
|
||||
let items: Vec<_> = contents.split(',').map(|s| s.trim()).collect();
|
||||
if items.len() != 2 {
|
||||
todo!(); // Return an error.
|
||||
|
|
|
@ -9,7 +9,8 @@ use data_tree::{reader::DataTreeReader, Event};
|
|||
use crate::scene::{Assembly, Object, ObjectData};
|
||||
|
||||
use super::{
|
||||
psy::{parse_matrix, PsyParseError},
|
||||
parse_utils::ensure_close,
|
||||
psy::{parse_matrix, PsyError, PsyResult},
|
||||
psy_light::{parse_rectangle_light, parse_sphere_light},
|
||||
psy_mesh_surface::parse_mesh_surface,
|
||||
};
|
||||
|
@ -17,7 +18,7 @@ use super::{
|
|||
pub fn parse_assembly<'a>(
|
||||
arena: &'a Arena,
|
||||
events: &mut DataTreeReader<impl BufRead>,
|
||||
) -> Result<Assembly<'a>, PsyParseError> {
|
||||
) -> PsyResult<Assembly<'a>> {
|
||||
let mut assembly = Assembly::new();
|
||||
loop {
|
||||
match events.next_event()? {
|
||||
|
@ -30,9 +31,10 @@ pub fn parse_assembly<'a>(
|
|||
let object_ident = if let Some(id) = ident {
|
||||
id.to_string()
|
||||
} else {
|
||||
return Err(PsyParseError::ExpectedIdent(
|
||||
return Err(PsyError::ExpectedIdent(
|
||||
byte_offset,
|
||||
"\'Object\' types must have an identifier, but the identifier is missing.",
|
||||
"\'Object\' types must have an identifier, but the identifier is missing."
|
||||
.into(),
|
||||
));
|
||||
};
|
||||
|
||||
|
@ -92,26 +94,22 @@ pub fn parse_assembly<'a>(
|
|||
} => ObjectData::Light(Box::new(parse_rectangle_light(arena, events)?)),
|
||||
|
||||
Event::InnerClose { byte_offset } => {
|
||||
return Err(PsyParseError::MissingNode(
|
||||
return Err(PsyError::MissingNode(
|
||||
byte_offset,
|
||||
"Object contains no object data.",
|
||||
"Object contains no object data.".into(),
|
||||
));
|
||||
}
|
||||
|
||||
_ => {
|
||||
return Err(PsyParseError::UnknownVariant(
|
||||
return Err(PsyError::UnknownVariant(
|
||||
byte_offset,
|
||||
"Unknown data type for Object.",
|
||||
"Unknown data type for Object.".into(),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
// Close object node.
|
||||
if let Event::InnerClose { .. } = events.next_event()? {
|
||||
// Success, do nothing.
|
||||
} else {
|
||||
todo!(); // Return error.
|
||||
}
|
||||
ensure_close(events)?;
|
||||
|
||||
assembly.objects.insert(
|
||||
object_ident,
|
||||
|
@ -133,7 +131,7 @@ pub fn parse_assembly<'a>(
|
|||
}
|
||||
|
||||
// if !tree.is_internal() {
|
||||
// return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
||||
// return Err(PsyError::UnknownError(tree.byte_offset()));
|
||||
// }
|
||||
|
||||
// for object in tree.iter_children() {
|
||||
|
|
|
@ -14,15 +14,15 @@ use crate::{
|
|||
};
|
||||
|
||||
use super::{
|
||||
basics::ws_f32,
|
||||
psy::{parse_color, PsyParseError},
|
||||
parse_utils::ws_f32,
|
||||
psy::{parse_color, PsyError, PsyResult},
|
||||
};
|
||||
|
||||
pub fn parse_distant_disk_light<'a>(
|
||||
arena: &'a Arena,
|
||||
events: &mut DataTreeReader<impl BufRead>,
|
||||
_ident: Option<&str>,
|
||||
) -> Result<DistantDiskLight<'a>, PsyParseError> {
|
||||
) -> PsyResult<DistantDiskLight<'a>> {
|
||||
let mut radii = Vec::new();
|
||||
let mut directions = Vec::new();
|
||||
let mut colors = Vec::new();
|
||||
|
@ -39,7 +39,7 @@ pub fn parse_distant_disk_light<'a>(
|
|||
radii.push(radius);
|
||||
} else {
|
||||
// Found radius, but its contents is not in the right format
|
||||
return Err(PsyParseError::UnknownError(byte_offset));
|
||||
return Err(PsyError::UnknownError(byte_offset));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ pub fn parse_distant_disk_light<'a>(
|
|||
directions.push(Vector::new(direction.0, direction.1, direction.2));
|
||||
} else {
|
||||
// Found direction, but its contents is not in the right format
|
||||
return Err(PsyParseError::UnknownError(byte_offset));
|
||||
return Err(PsyError::UnknownError(byte_offset));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ pub fn parse_distant_disk_light<'a>(
|
|||
colors.push(color);
|
||||
} else {
|
||||
// Found color, but its contents is not in the right format
|
||||
return Err(PsyParseError::UnknownError(byte_offset));
|
||||
return Err(PsyError::UnknownError(byte_offset));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ pub fn parse_distant_disk_light<'a>(
|
|||
pub fn parse_sphere_light<'a>(
|
||||
arena: &'a Arena,
|
||||
events: &mut DataTreeReader<impl BufRead>,
|
||||
) -> Result<SphereLight<'a>, PsyParseError> {
|
||||
) -> Result<SphereLight<'a>, PsyError> {
|
||||
let mut radii = Vec::new();
|
||||
let mut colors = Vec::new();
|
||||
|
||||
|
@ -106,7 +106,7 @@ pub fn parse_sphere_light<'a>(
|
|||
radii.push(radius);
|
||||
} else {
|
||||
// Found radius, but its contents is not in the right format
|
||||
return Err(PsyParseError::UnknownError(byte_offset));
|
||||
return Err(PsyError::UnknownError(byte_offset));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ pub fn parse_sphere_light<'a>(
|
|||
colors.push(color);
|
||||
} else {
|
||||
// Found color, but its contents is not in the right format
|
||||
return Err(PsyParseError::UnknownError(byte_offset));
|
||||
return Err(PsyError::UnknownError(byte_offset));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ pub fn parse_sphere_light<'a>(
|
|||
pub fn parse_rectangle_light<'a>(
|
||||
arena: &'a Arena,
|
||||
events: &mut DataTreeReader<impl BufRead>,
|
||||
) -> Result<RectangleLight<'a>, PsyParseError> {
|
||||
) -> Result<RectangleLight<'a>, PsyError> {
|
||||
let mut dimensions = Vec::new();
|
||||
let mut colors = Vec::new();
|
||||
|
||||
|
@ -158,7 +158,7 @@ pub fn parse_rectangle_light<'a>(
|
|||
dimensions.push(radius);
|
||||
} else {
|
||||
// Found dimensions, but its contents is not in the right format
|
||||
return Err(PsyParseError::UnknownError(byte_offset));
|
||||
return Err(PsyError::UnknownError(byte_offset));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,7 +172,7 @@ pub fn parse_rectangle_light<'a>(
|
|||
colors.push(color);
|
||||
} else {
|
||||
// Found color, but its contents is not in the right format
|
||||
return Err(PsyParseError::UnknownError(byte_offset));
|
||||
return Err(PsyError::UnknownError(byte_offset));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ use crate::{
|
|||
};
|
||||
|
||||
use super::{
|
||||
basics::{ws_f32, ws_usize},
|
||||
psy::PsyParseError,
|
||||
parse_utils::{ws_f32, ws_usize},
|
||||
psy::{PsyError, PsyResult},
|
||||
};
|
||||
|
||||
// pub struct TriangleMesh {
|
||||
|
@ -28,7 +28,7 @@ use super::{
|
|||
pub fn parse_mesh_surface<'a>(
|
||||
arena: &'a Arena,
|
||||
events: &mut DataTreeReader<impl BufRead>,
|
||||
) -> Result<TriangleMesh<'a>, PsyParseError> {
|
||||
) -> PsyResult<TriangleMesh<'a>> {
|
||||
let mut verts = Vec::new(); // Vec of vecs, one for each time sample
|
||||
let mut normals = Vec::new(); // Vec of vecs, on for each time sample
|
||||
let mut face_vert_counts = Vec::new();
|
||||
|
@ -81,9 +81,9 @@ pub fn parse_mesh_surface<'a>(
|
|||
byte_offset,
|
||||
} => {
|
||||
if !face_vert_counts.is_empty() {
|
||||
return Err(PsyParseError::WrongNodeCount(
|
||||
return Err(PsyError::WrongNodeCount(
|
||||
byte_offset,
|
||||
"Meshes can only have one FaceVertCounts section.",
|
||||
"Meshes can only have one FaceVertCounts section.".into(),
|
||||
));
|
||||
}
|
||||
let mut text = contents;
|
||||
|
@ -99,9 +99,9 @@ pub fn parse_mesh_surface<'a>(
|
|||
byte_offset,
|
||||
} => {
|
||||
if !face_vert_indices.is_empty() {
|
||||
return Err(PsyParseError::WrongNodeCount(
|
||||
return Err(PsyError::WrongNodeCount(
|
||||
byte_offset,
|
||||
"Meshes can only have one FaceVertIndices section.",
|
||||
"Meshes can only have one FaceVertIndices section.".into(),
|
||||
));
|
||||
}
|
||||
let mut text = contents;
|
||||
|
|
|
@ -11,8 +11,8 @@ use data_tree::{reader::DataTreeReader, Event};
|
|||
use crate::shading::{SimpleSurfaceShader, SurfaceShader};
|
||||
|
||||
use super::{
|
||||
basics::ws_f32,
|
||||
psy::{parse_color, PsyParseError},
|
||||
parse_utils::{ensure_close, ws_f32},
|
||||
psy::{parse_color, PsyError, PsyResult},
|
||||
};
|
||||
|
||||
// pub struct TriangleMesh {
|
||||
|
@ -26,7 +26,7 @@ pub fn parse_surface_shader(
|
|||
_arena: &Arena,
|
||||
events: &mut DataTreeReader<impl BufRead>,
|
||||
_ident: Option<&str>,
|
||||
) -> Result<Box<dyn SurfaceShader>, PsyParseError> {
|
||||
) -> PsyResult<Box<dyn SurfaceShader>> {
|
||||
// Get shader type.
|
||||
let shader = match events.next_event()? {
|
||||
Event::Leaf {
|
||||
|
@ -44,21 +44,17 @@ pub fn parse_surface_shader(
|
|||
color
|
||||
} else {
|
||||
// Found color, but its contents is not in the right format
|
||||
return Err(PsyParseError::UnknownError(byte_offset));
|
||||
return Err(PsyError::UnknownError(byte_offset));
|
||||
}
|
||||
} else {
|
||||
return Err(PsyParseError::MissingNode(
|
||||
return Err(PsyError::MissingNode(
|
||||
events.byte_offset(),
|
||||
"Expected a Color field in Lambert SurfaceShader.",
|
||||
"Expected a Color field in Lambert SurfaceShader.".into(),
|
||||
));
|
||||
};
|
||||
|
||||
// Close shader node.
|
||||
if let Event::InnerClose { .. } = events.next_event()? {
|
||||
// Success, do nothing.
|
||||
} else {
|
||||
todo!(); // Return error.
|
||||
}
|
||||
ensure_close(events)?;
|
||||
|
||||
Box::new(SimpleSurfaceShader::Lambert { color: color })
|
||||
}
|
||||
|
@ -85,7 +81,7 @@ pub fn parse_surface_shader(
|
|||
} else {
|
||||
// Found color, but its contents is not in the right
|
||||
// format.
|
||||
return Err(PsyParseError::UnknownError(byte_offset));
|
||||
return Err(PsyError::UnknownError(byte_offset));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,7 +94,7 @@ pub fn parse_surface_shader(
|
|||
if let IResult::Ok((_, rgh)) = all_consuming(ws_f32)(contents) {
|
||||
roughness = Some(rgh);
|
||||
} else {
|
||||
return Err(PsyParseError::UnknownError(byte_offset));
|
||||
return Err(PsyError::UnknownError(byte_offset));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +107,7 @@ pub fn parse_surface_shader(
|
|||
if let IResult::Ok((_, frs)) = all_consuming(ws_f32)(contents) {
|
||||
fresnel = Some(frs);
|
||||
} else {
|
||||
return Err(PsyParseError::UnknownError(byte_offset));
|
||||
return Err(PsyError::UnknownError(byte_offset));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,9 +123,9 @@ pub fn parse_surface_shader(
|
|||
|
||||
// Validation: make sure all fields are present.
|
||||
if color == None || roughness == None || fresnel == None {
|
||||
return Err(PsyParseError::MissingNode(
|
||||
return Err(PsyError::MissingNode(
|
||||
events.byte_offset(),
|
||||
"GGX shader requires one of each field: Color, Roughness, Fresnel.",
|
||||
"GGX shader requires one of each field: Color, Roughness, Fresnel.".into(),
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -155,21 +151,17 @@ pub fn parse_surface_shader(
|
|||
color
|
||||
} else {
|
||||
// Found color, but its contents is not in the right format
|
||||
return Err(PsyParseError::UnknownError(byte_offset));
|
||||
return Err(PsyError::UnknownError(byte_offset));
|
||||
}
|
||||
} else {
|
||||
return Err(PsyParseError::MissingNode(
|
||||
return Err(PsyError::MissingNode(
|
||||
events.byte_offset(),
|
||||
"Expected a Color field in Emit SurfaceShader.",
|
||||
"Expected a Color field in Emit SurfaceShader.".into(),
|
||||
));
|
||||
};
|
||||
|
||||
// Close shader node.
|
||||
if let Event::InnerClose { .. } = events.next_event()? {
|
||||
// Success, do nothing.
|
||||
} else {
|
||||
todo!(); // Return error.
|
||||
}
|
||||
ensure_close(events)?;
|
||||
|
||||
Box::new(SimpleSurfaceShader::Emit { color: color })
|
||||
}
|
||||
|
@ -179,9 +171,9 @@ pub fn parse_surface_shader(
|
|||
byte_offset,
|
||||
..
|
||||
} => {
|
||||
return Err(PsyParseError::MissingNode(
|
||||
return Err(PsyError::MissingNode(
|
||||
byte_offset,
|
||||
"Unknown SurfaceShader type.",
|
||||
"Unknown SurfaceShader type.".into(),
|
||||
));
|
||||
}
|
||||
_ => {
|
||||
|
|
Loading…
Reference in New Issue
Block a user