Unify error types ♾
This commit is contained in:
parent
9fb31defd0
commit
f72b1505be
@ -64,14 +64,14 @@ impl<'a> ArgParser<'a> {
|
||||
if self.positional_index == self.args.positional.len() {
|
||||
Ok(())
|
||||
} else {
|
||||
pr!("unexpected argument");
|
||||
error!(unexpected_argument);
|
||||
}
|
||||
}
|
||||
|
||||
/// Covert an option to a result with an error on `None`.
|
||||
fn expected<T>(val: Option<Spanned<T::Output>>) -> ParseResult<Spanned<T::Output>>
|
||||
where T: Argument<'a> {
|
||||
val.ok_or_else(|| pr!(@"expected {}", T::ERROR_MESSAGE))
|
||||
val.ok_or_else(|| error!(@"expected {}", T::ERROR_MESSAGE))
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,10 +93,10 @@ macro_rules! arg {
|
||||
const ERROR_MESSAGE: &'static str = $err;
|
||||
|
||||
fn from_expr(expr: &'a Spanned<Expression>) -> ParseResult<Spanned<Self::Output>> {
|
||||
#[allow(unreachable_patterns)]
|
||||
#[allow(unreachable_code)]
|
||||
match &expr.val {
|
||||
$wanted => Ok(Spanned::new($converted, expr.span)),
|
||||
_ => pr!("expected {}", $err),
|
||||
_ => error!("expected {}", $err),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -179,7 +179,7 @@ impl AlignmentKey {
|
||||
Right if horizontal => axes.right(),
|
||||
Top if !horizontal => axes.top(),
|
||||
Bottom if !horizontal => axes.bottom(),
|
||||
_ => lr!(
|
||||
_ => error!(
|
||||
"invalid alignment `{}` for {} axis",
|
||||
format!("{:?}", self).to_lowercase(),
|
||||
format!("{:?}", axis).to_lowercase()
|
||||
|
@ -111,7 +111,7 @@ macro_rules! function {
|
||||
macro_rules! parse {
|
||||
(forbidden: $body:expr) => {
|
||||
if $body.is_some() {
|
||||
pr!("unexpected body");
|
||||
error!("unexpected body");
|
||||
}
|
||||
};
|
||||
|
||||
@ -127,23 +127,16 @@ macro_rules! parse {
|
||||
if let Some(body) = $body {
|
||||
$crate::syntax::parse(body, $ctx)?
|
||||
} else {
|
||||
pr!("expected body");
|
||||
error!("expected body");
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/// Early-return with a formatted parsing error or yield
|
||||
/// an error expression without returning when prefixed with `@`.
|
||||
/// Early-return with a formatted typesetting error or construct an error
|
||||
/// expression without returning when prefixed with `@`.
|
||||
#[macro_export]
|
||||
macro_rules! pr {
|
||||
(@$($tts:tt)*) => ($crate::syntax::ParseError::new(format!($($tts)*)));
|
||||
($($tts:tt)*) => (return Err(pr!(@$($tts)*)););
|
||||
}
|
||||
|
||||
/// Early-return with a formatted layouting error or yield
|
||||
/// an error expression without returning when prefixed with `@`.
|
||||
#[macro_export]
|
||||
macro_rules! lr {
|
||||
(@$($tts:tt)*) => ($crate::layout::LayoutError::new(format!($($tts)*)));
|
||||
($($tts:tt)*) => (return Err(lr!(@$($tts)*)););
|
||||
macro_rules! error {
|
||||
(@unexpected_argument) => (error!(@"unexpected argument"));
|
||||
(@$($tts:tt)*) => ($crate::TypesetError::with_message(format!($($tts)*)));
|
||||
($($tts:tt)*) => (return Err(error!(@$($tts)*)););
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ pub mod prelude {
|
||||
pub use super::args::*;
|
||||
pub use super::{Scope, ParseFunc, LayoutFunc, Command, Commands};
|
||||
pub use crate::syntax::{SyntaxTree, FuncHeader, FuncArgs, Expression, Spanned, Span};
|
||||
pub use crate::syntax::{parse, ParseContext, ParseError, ParseResult};
|
||||
pub use crate::syntax::{parse, ParseContext, ParseResult};
|
||||
pub use crate::size::{Size, Size2D, SizeBox};
|
||||
pub use crate::style::{PageStyle, TextStyle};
|
||||
pub use crate::layout::{
|
||||
@ -24,8 +24,7 @@ pub mod prelude {
|
||||
LayoutContext, LayoutSpace, LayoutSpaces,
|
||||
LayoutAxes, Axis, GenericAxisKind, SpecificAxisKind,
|
||||
LayoutAlignment, Alignment,
|
||||
SpacingKind,
|
||||
LayoutError, LayoutResult,
|
||||
SpacingKind, LayoutResult,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -230,7 +230,8 @@ impl FlexLayouter {
|
||||
|
||||
while size.x > self.line.usable {
|
||||
if self.stack.space_is_last() {
|
||||
lr!("box does not fit into line");
|
||||
error!("box of size {} does not fit into line of size {}",
|
||||
size.x, self.line.usable);
|
||||
}
|
||||
|
||||
self.stack.finish_space(true);
|
||||
|
@ -5,8 +5,8 @@ use std::io::{self, Write};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use toddle::query::{FontClass, SharedFontLoader};
|
||||
use toddle::Error as FontError;
|
||||
|
||||
use crate::TypesetResult;
|
||||
use crate::func::Command;
|
||||
use crate::size::{Size, Size2D, SizeBox};
|
||||
use crate::style::{LayoutStyle, TextStyle};
|
||||
@ -366,22 +366,5 @@ impl Serialize for MultiLayout {
|
||||
}
|
||||
}
|
||||
|
||||
/// The error type for layouting.
|
||||
pub struct LayoutError(String);
|
||||
|
||||
/// The result type for layouting.
|
||||
pub type LayoutResult<T> = Result<T, LayoutError>;
|
||||
|
||||
impl LayoutError {
|
||||
/// Create a new layout error with a message.
|
||||
pub fn new<S: Into<String>>(message: S) -> LayoutError {
|
||||
LayoutError(message.into())
|
||||
}
|
||||
}
|
||||
|
||||
error_type! {
|
||||
err: LayoutError,
|
||||
show: f => f.write_str(&err.0),
|
||||
from: (std::io::Error, LayoutError::new(err.to_string())),
|
||||
from: (FontError, LayoutError::new(err.to_string())),
|
||||
}
|
||||
pub type LayoutResult<T> = TypesetResult<T>;
|
||||
|
@ -108,7 +108,8 @@ impl StackLayouter {
|
||||
// Find the first (sub-)space that fits the layout.
|
||||
while !self.sub.usable.fits(new_size) {
|
||||
if self.space_is_last() && self.space_is_empty() {
|
||||
lr!("box does not fit into stack");
|
||||
error!("box of size {} does not fit into remaining stack of size {}",
|
||||
size, self.sub.usable - Size2D::with_y(self.sub.size.y));
|
||||
}
|
||||
|
||||
self.finish_space(true);
|
||||
|
@ -116,6 +116,6 @@ impl<'a, 'p> TextLayouter<'a, 'p> {
|
||||
self.classes.pop();
|
||||
}
|
||||
|
||||
lr!("no suitable font for character `{}`", c);
|
||||
error!("no suitable font for character `{}`", c);
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
|
||||
SetTextStyle(style) => self.style.text = style,
|
||||
SetPageStyle(style) => {
|
||||
if !self.ctx.top_level {
|
||||
lr!("page style cannot only be altered in the top-level context");
|
||||
error!("the page style cannot only be altered from a top-level context");
|
||||
}
|
||||
|
||||
self.style.page = style;
|
||||
|
43
src/lib.rs
43
src/lib.rs
@ -18,13 +18,15 @@ pub extern crate toddle;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use smallvec::smallvec;
|
||||
|
||||
use toddle::query::{FontLoader, FontProvider, SharedFontLoader};
|
||||
use toddle::Error as FontError;
|
||||
|
||||
use crate::func::Scope;
|
||||
use crate::layout::{layout_tree, MultiLayout, LayoutContext};
|
||||
use crate::layout::{LayoutAxes, LayoutAlignment, Axis, Alignment};
|
||||
use crate::layout::{LayoutError, LayoutResult, LayoutSpace};
|
||||
use crate::syntax::{SyntaxTree, parse, ParseContext, ParseError, ParseResult};
|
||||
use crate::layout::{LayoutResult, LayoutSpace};
|
||||
use crate::syntax::{parse, SyntaxTree, ParseContext, Span, ParseResult};
|
||||
use crate::style::{LayoutStyle, PageStyle, TextStyle};
|
||||
|
||||
#[macro_use]
|
||||
@ -116,24 +118,31 @@ impl<'p> Typesetter<'p> {
|
||||
}
|
||||
}
|
||||
|
||||
/// The general error type for typesetting.
|
||||
pub enum TypesetError {
|
||||
/// An error that occured in the parsing step.
|
||||
Parse(ParseError),
|
||||
/// An error that occured in the layouting step.
|
||||
Layout(LayoutError),
|
||||
/// The result type for typesetting.
|
||||
pub type TypesetResult<T> = Result<T, TypesetError>;
|
||||
|
||||
/// The error type for typesetting.
|
||||
pub struct TypesetError {
|
||||
message: String,
|
||||
span: Option<Span>,
|
||||
}
|
||||
|
||||
impl TypesetError {
|
||||
/// Create a new typesetting error.
|
||||
pub fn with_message(message: String) -> TypesetError {
|
||||
TypesetError { message, span: None }
|
||||
}
|
||||
}
|
||||
|
||||
error_type! {
|
||||
err: TypesetError,
|
||||
show: f => match err {
|
||||
TypesetError::Parse(e) => write!(f, "{}", e),
|
||||
TypesetError::Layout(e) => write!(f, "{}", e),
|
||||
show: f => {
|
||||
write!(f, "{}", err.message)?;
|
||||
if let Some(span) = err.span {
|
||||
write!(f, " at {}", span)?;
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
source: match err {
|
||||
TypesetError::Parse(e) => Some(e),
|
||||
TypesetError::Layout(e) => Some(e),
|
||||
},
|
||||
from: (ParseError, TypesetError::Parse(err)),
|
||||
from: (LayoutError, TypesetError::Layout(err)),
|
||||
from: (std::io::Error, TypesetError::with_message(err.to_string())),
|
||||
from: (FontError, TypesetError::with_message(err.to_string())),
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ function! {
|
||||
"vertical" => Key::Axis(AxisKey::Vertical),
|
||||
"primary" => Key::Axis(AxisKey::Primary),
|
||||
"secondary" => Key::Axis(AxisKey::Secondary),
|
||||
_ => pr!("unexpected argument"),
|
||||
_ => error!(unexpected_argument),
|
||||
};
|
||||
|
||||
let value = AlignmentKey::parse(arg.val.1.val)?;
|
||||
|
@ -17,7 +17,7 @@ function! {
|
||||
"height" | "h" => AxisKey::Vertical,
|
||||
"primary-size" => AxisKey::Primary,
|
||||
"secondary-size" => AxisKey::Secondary,
|
||||
_ => pr!("unexpected argument"),
|
||||
_ => error!(unexpected_argument),
|
||||
};
|
||||
|
||||
let size = ArgParser::convert::<ArgSize>(arg.val.1.val)?;
|
||||
|
@ -128,7 +128,7 @@ function! {
|
||||
"vertical-origin" => AxisAligned(AxisKey::Vertical, Origin),
|
||||
"vertical-end" => AxisAligned(AxisKey::Vertical, End),
|
||||
|
||||
_ => pr!("unexpected argument"),
|
||||
_ => error!(unexpected_argument),
|
||||
};
|
||||
|
||||
let size = ArgParser::convert::<ArgSize>(arg.val.1.val)?;
|
||||
@ -200,13 +200,13 @@ function! {
|
||||
"vertical" => AxisKey::Vertical,
|
||||
"primary" => AxisKey::Primary,
|
||||
"secondary" => AxisKey::Secondary,
|
||||
_ => pr!("unexpected argument"),
|
||||
_ => error!(unexpected_argument),
|
||||
};
|
||||
|
||||
let spacing = SpacingValue::from_expr(arg.val.1.val)?;
|
||||
Spacing { axis, spacing }
|
||||
} else {
|
||||
pr!("expected axis and expression")
|
||||
error!("expected axis and expression")
|
||||
}
|
||||
};
|
||||
|
||||
@ -236,7 +236,7 @@ impl SpacingValue {
|
||||
Ok(match expr.val {
|
||||
Expression::Size(s) => SpacingValue::Absolute(*s),
|
||||
Expression::Num(f) => SpacingValue::Relative(*f as f32),
|
||||
_ => pr!("invalid spacing: expected size or number"),
|
||||
_ => error!("invalid spacing: expected size or number"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ mod span;
|
||||
|
||||
pub use span::{Span, Spanned};
|
||||
pub use tokens::{tokenize, Tokens};
|
||||
pub use parsing::{parse, ParseContext, ParseError, ParseResult};
|
||||
pub use parsing::{parse, ParseContext, ParseResult};
|
||||
|
||||
/// A logical unit of the incoming text stream.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use unicode_xid::UnicodeXID;
|
||||
|
||||
use crate::TypesetResult;
|
||||
use crate::func::{LayoutFunc, Scope};
|
||||
use crate::size::Size;
|
||||
use super::*;
|
||||
@ -69,7 +70,7 @@ impl<'s> Parser<'s> {
|
||||
match token.val {
|
||||
// Functions.
|
||||
LeftBracket => self.parse_func()?,
|
||||
RightBracket => return Err(ParseError::new("unexpected closing bracket")),
|
||||
RightBracket => error!("unexpected closing bracket"),
|
||||
|
||||
// Modifiers.
|
||||
Underscore => self.append_consumed(Node::ToggleItalics, token.span),
|
||||
@ -120,10 +121,10 @@ impl<'s> Parser<'s> {
|
||||
if is_identifier(word) {
|
||||
Ok(Spanned::new(word.to_owned(), span))
|
||||
} else {
|
||||
pr!("invalid identifier: '{}'", word);
|
||||
error!("invalid identifier: `{}`", word);
|
||||
}
|
||||
}
|
||||
_ => pr!("expected identifier"),
|
||||
_ => error!("expected identifier"),
|
||||
}?;
|
||||
|
||||
self.skip_white();
|
||||
@ -132,7 +133,7 @@ impl<'s> Parser<'s> {
|
||||
let args = match self.tokens.next().map(Spanned::value) {
|
||||
Some(Token::RightBracket) => FuncArgs::new(),
|
||||
Some(Token::Colon) => self.parse_func_args()?,
|
||||
_ => pr!("expected arguments or closing bracket"),
|
||||
_ => error!("expected arguments or closing bracket"),
|
||||
};
|
||||
|
||||
let end = self.tokens.string_index();
|
||||
@ -158,7 +159,7 @@ impl<'s> Parser<'s> {
|
||||
match self.tokens.next().map(Spanned::value) {
|
||||
Some(Token::Comma) => {},
|
||||
Some(Token::RightBracket) => break,
|
||||
_ => pr!("expected comma or closing bracket"),
|
||||
_ => error!("expected comma or closing bracket"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,7 +184,7 @@ impl<'s> Parser<'s> {
|
||||
self.skip_white();
|
||||
|
||||
let name = token.span_map(|_| name.to_string());
|
||||
let next = self.tokens.next().ok_or_else(|| pr!(@"expected value"))?;
|
||||
let next = self.tokens.next().ok_or_else(|| error!(@"expected expression"))?;
|
||||
let val = Self::parse_expression(next)?;
|
||||
let span = Span::merge(name.span, val.span);
|
||||
|
||||
@ -218,8 +219,7 @@ impl<'s> Parser<'s> {
|
||||
Expression::Ident(text.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
_ => pr!("expected expression"),
|
||||
_ => error!("expected expression"),
|
||||
}, token.span))
|
||||
}
|
||||
|
||||
@ -231,7 +231,7 @@ impl<'s> Parser<'s> {
|
||||
.ctx
|
||||
.scope
|
||||
.get_parser(&header.name.val)
|
||||
.ok_or_else(|| pr!(@"unknown function: '{}'", &header.name.val))?;
|
||||
.ok_or_else(|| error!(@"unknown function: `{}`", &header.name.val))?;
|
||||
|
||||
let has_body = self.tokens.peek().map(Spanned::value) == Some(Token::LeftBracket);
|
||||
|
||||
@ -243,7 +243,7 @@ impl<'s> Parser<'s> {
|
||||
let start = self.tokens.string_index();
|
||||
let end = find_closing_bracket(&self.src[start..])
|
||||
.map(|end| start + end)
|
||||
.ok_or_else(|| ParseError::new("expected closing bracket"))?;
|
||||
.ok_or_else(|| error!(@"expected closing bracket"))?;
|
||||
|
||||
// Parse the body.
|
||||
let body_string = &self.src[start..end];
|
||||
@ -299,7 +299,7 @@ impl<'s> Parser<'s> {
|
||||
state = NewlineState::Zero;
|
||||
match token.val {
|
||||
Token::LineComment(_) | Token::BlockComment(_) => self.advance(),
|
||||
Token::StarSlash => pr!("unexpected end of block comment"),
|
||||
Token::StarSlash => error!("unexpected end of block comment"),
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
@ -431,23 +431,8 @@ fn is_identifier(string: &str) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// The error type for parsing.
|
||||
pub struct ParseError(String);
|
||||
|
||||
/// The result type for parsing.
|
||||
pub type ParseResult<T> = Result<T, ParseError>;
|
||||
|
||||
impl ParseError {
|
||||
/// Create a new parse error with a message.
|
||||
pub fn new<S: Into<String>>(message: S) -> ParseError {
|
||||
ParseError(message.into())
|
||||
}
|
||||
}
|
||||
|
||||
error_type! {
|
||||
err: ParseError,
|
||||
show: f => f.write_str(&err.0),
|
||||
}
|
||||
pub type ParseResult<T> = TypesetResult<T>;
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
|
Loading…
x
Reference in New Issue
Block a user