diff options
Diffstat (limited to 'src/func')
| -rw-r--r-- | src/func/macros.rs | 15 | ||||
| -rw-r--r-- | src/func/mod.rs | 26 |
2 files changed, 32 insertions, 9 deletions
diff --git a/src/func/macros.rs b/src/func/macros.rs index 9e931ea2..1083e53c 100644 --- a/src/func/macros.rs +++ b/src/func/macros.rs @@ -75,6 +75,8 @@ macro_rules! function { parse($args:ident, $body:pat, $ctx:pat, $metadata:pat) $code:block $($rest:tt)* ) => { + use $crate::func::prelude::*; + impl $crate::func::ParseFunc for $type { type Meta = $meta; @@ -88,7 +90,8 @@ macro_rules! function { let mut $args = args; let val = $code; if !$args.is_empty() { - error!(unexpected_argument); + return Err($crate::TypesetError + ::with_message("unexpected arguments")); } Ok(val) } @@ -109,6 +112,8 @@ macro_rules! function { // (2-arg) Parse a layout-definition with all arguments. (@layout $type:ident | layout($this:ident, $ctx:pat) $code:block) => { + use $crate::func::prelude::*; + impl LayoutFunc for $type { fn layout<'a, 'life0, 'life1, 'async_trait>( &'a $this, @@ -138,13 +143,13 @@ macro_rules! function { macro_rules! parse { (forbidden: $body:expr) => { if $body.is_some() { - error!("unexpected body"); + return Err($crate::TypesetError::with_message("unexpected body")); } }; (optional: $body:expr, $ctx:expr) => ( if let Some(body) = $body { - Some($crate::syntax::parse(body, $ctx)) + Some($crate::syntax::parse(body, $ctx).0) } else { None } @@ -152,9 +157,9 @@ macro_rules! parse { (expected: $body:expr, $ctx:expr) => ( if let Some(body) = $body { - $crate::syntax::parse(body, $ctx)? + $crate::syntax::parse(body, $ctx).0 } else { - error!("expected body"); + Err($crate::TypesetError::with_message("unexpected body")) } ) } diff --git a/src/func/mod.rs b/src/func/mod.rs index 5f4918d9..90b2a31d 100644 --- a/src/func/mod.rs +++ b/src/func/mod.rs @@ -119,6 +119,7 @@ pub enum Command<'a> { /// A map from identifiers to function parsers. pub struct Scope { parsers: HashMap<String, Box<Parser>>, + debug: Option<Box<Parser>> } /// A function which parses the source of a function into a function type which @@ -129,11 +130,30 @@ type Parser = dyn Fn( ParseContext ) -> ParseResult<Box<dyn LayoutFunc>>; +fn make_parser<F>(metadata: <F as ParseFunc>::Meta) -> Box<Parser> +where F: ParseFunc + LayoutFunc + 'static { + Box::new(move |a, b, c| { + F::parse(a, b, c, metadata.clone()) + .map(|f| Box::new(f) as Box<dyn LayoutFunc>) + }) +} + impl Scope { /// Create a new empty scope. pub fn new() -> Scope { Scope { parsers: HashMap::new(), + debug: None, + } + } + + /// Create a new scope with a debug parser that is invoked if not other + /// match is found. + pub fn with_debug<F>() -> Scope + where F: ParseFunc<Meta=()> + LayoutFunc + 'static { + Scope { + parsers: HashMap::new(), + debug: Some(make_parser::<F>(())), } } @@ -154,16 +174,14 @@ impl Scope { where F: ParseFunc + LayoutFunc + 'static { self.parsers.insert( name.to_owned(), - Box::new(move |a, b, c| { - F::parse(a, b, c, metadata.clone()) - .map(|f| Box::new(f) as Box<dyn LayoutFunc>) - }) + make_parser::<F>(metadata), ); } /// Return the parser with the given name if there is one. pub(crate) fn get_parser(&self, name: &str) -> Option<&Parser> { self.parsers.get(name).map(|x| &**x) + .or(self.debug.as_ref().map(|x| &**x)) } } |
