foliage-rs/src/parse/error.rs

183 lines
4.5 KiB
Rust
Raw Normal View History

2020-04-22 20:01:29 +02:00
pub type Source = Box<dyn std::error::Error>;
pub struct Location
{
start: usize,
end: Option<usize>,
}
impl Location
{
pub fn new(start: usize, end: Option<usize>) -> Self
{
Self
{
start,
end,
}
}
}
pub enum Kind
{
UnmatchedParenthesis,
CharacterNotAllowed(char),
ParseNumber(String),
MixedImplicationDirections(Location),
2020-04-27 19:30:25 +02:00
ExpectedVariableDeclaration,
UnexpectedToken,
2020-04-28 03:18:05 +02:00
EmptyExpression,
2020-04-27 19:30:25 +02:00
ExpectedLogicalConnectiveArgument(String),
2020-04-28 05:21:58 +02:00
ExpectedTerm,
2020-04-27 19:30:25 +02:00
MultipleComparisonOperators(crate::ComparisonOperator, crate::ComparisonOperator),
2020-04-22 20:01:29 +02:00
}
pub struct Error
{
pub kind: Kind,
pub location: Location,
pub source: Option<Source>,
}
impl Error
{
pub(crate) fn new(kind: Kind, location: Location) -> Self
{
Self
{
kind,
location,
source: None,
}
}
pub(crate) fn with<S: Into<Source>>(mut self, source: S) -> Self
{
self.source = Some(source.into());
self
}
pub(crate) fn new_unmatched_parenthesis(location: Location) -> Self
{
Self::new(Kind::UnmatchedParenthesis, location)
}
pub(crate) fn new_character_not_allowed(character: char, location: Location) -> Self
{
Self::new(Kind::CharacterNotAllowed(character), location)
}
pub(crate) fn new_parse_number<I: Into<String>, S: Into<Source>>(input: I, location: Location,
source: S)
-> Self
{
Self::new(Kind::ParseNumber(input.into()), location).with(source)
}
pub(crate) fn new_mixed_implication_directions(location_1: Location, location_2: Location)
-> Self
{
Self::new(Kind::MixedImplicationDirections(location_2), location_1)
}
2020-04-27 19:30:25 +02:00
pub(crate) fn new_expected_variable_declaration(location: Location) -> Self
{
Self::new(Kind::ExpectedVariableDeclaration, location)
}
pub(crate) fn new_unexpected_token(location: Location) -> Self
{
Self::new(Kind::UnexpectedToken, location)
}
2020-04-28 03:18:05 +02:00
pub(crate) fn new_empty_expression(location: Location) -> Self
2020-04-27 19:30:25 +02:00
{
2020-04-28 03:18:05 +02:00
Self::new(Kind::EmptyExpression, location)
2020-04-27 19:30:25 +02:00
}
pub(crate) fn new_expected_logical_connective_argument(logical_connective_name: String,
location: Location)
-> Self
{
Self::new(Kind::ExpectedLogicalConnectiveArgument(logical_connective_name), location)
}
2020-04-28 05:21:58 +02:00
pub(crate) fn new_expected_term(location: Location) -> Self
{
Self::new(Kind::ExpectedTerm, location)
}
2020-04-27 19:30:25 +02:00
pub(crate) fn new_multiple_comparison_operators(
comparison_operator_1: crate::ComparisonOperator,
comparison_operator_2: crate::ComparisonOperator, location: Location)
-> Self
{
Self::new(Kind::MultipleComparisonOperators(comparison_operator_1, comparison_operator_2),
location)
}
2020-04-22 20:01:29 +02:00
}
impl std::fmt::Debug for Error
{
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result
{
if let Some(end) = self.location.end
{
write!(formatter, "parsing error at {}:{}: ", self.location.start, end)?;
}
else
{
write!(formatter, "parsing error at {}: ", self.location.start)?;
}
match &self.kind
{
Kind::UnmatchedParenthesis => write!(formatter, "unmatched parenthesis")?,
Kind::CharacterNotAllowed(character) =>
write!(formatter, "character not allowed: {}", character)?,
Kind::ParseNumber(input) => write!(formatter, "could not “{}” as number", input)?,
// TODO: print second location properly
Kind::MixedImplicationDirections(_location_2) =>
write!(formatter, "-> and <- implications may not be mixed within the same scope")?,
2020-04-27 19:30:25 +02:00
Kind::ExpectedVariableDeclaration =>
2020-04-28 05:21:58 +02:00
write!(formatter, "expected a variable declaration")?,
2020-04-27 19:30:25 +02:00
Kind::UnexpectedToken => write!(formatter, "unexpected token")?,
2020-04-28 03:18:05 +02:00
Kind::EmptyExpression => write!(formatter, "empty expression")?,
2020-04-27 19:30:25 +02:00
Kind::ExpectedLogicalConnectiveArgument(ref logical_connective_name) =>
write!(formatter, "this “{}” logical connective is missing an argument",
logical_connective_name)?,
2020-04-28 05:21:58 +02:00
Kind::ExpectedTerm => write!(formatter, "expected a term")?,
2020-04-27 19:30:25 +02:00
Kind::MultipleComparisonOperators(comparison_operator_1, comparison_operator_2) =>
write!(formatter, "chained comparisons arent supported (found “{:?}” and “{:?}” in the same formula), consider separating them with “and”",
comparison_operator_1, comparison_operator_2)?,
2020-04-22 20:01:29 +02:00
}
if let Some(source) = &self.source
{
write!(formatter, "\nerror source: {}", source)?;
}
Ok(())
}
}
impl std::fmt::Display for Error
{
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result
{
write!(formatter, "{:?}", self)
}
}
impl std::error::Error for Error
{
fn source(&self) -> Option<&(dyn std::error::Error + 'static)>
{
match &self.source
{
Some(source) => Some(source.as_ref()),
None => None,
}
}
}