diff options
| author | Laurenz <laurmaedje@gmail.com> | 2019-04-29 11:03:17 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2019-04-29 11:03:17 +0200 |
| commit | 14c9ff571d41e01fe46fb842aa5ea1b93497c4ab (patch) | |
| tree | 0a09cec0552dcd990d12df8ab361271112d4bb83 /src/func.rs | |
| parent | f279c52b503e9dacb558d8a46a75b42bc5222ee4 (diff) | |
Remove stack from parser ♻
Diffstat (limited to 'src/func.rs')
| -rw-r--r-- | src/func.rs | 83 |
1 files changed, 41 insertions, 42 deletions
diff --git a/src/func.rs b/src/func.rs index cbc2f58b..d85d7a18 100644 --- a/src/func.rs +++ b/src/func.rs @@ -3,37 +3,67 @@ use std::any::Any; use std::collections::HashMap; use std::fmt::Debug; + use crate::syntax::{Token, FuncHeader, Expression}; -use crate::parsing::ParseError; +use crate::parsing::ParseResult; /// An optional iterator over the tokens of a function body. pub type BodyTokens<'a> = Option<Box<dyn Iterator<Item=Token<'a>> + 'a>>; +/// Parser functions. +pub type ParseFunc = dyn Fn(&FuncHeader, BodyTokens<'_>, &Scope) + -> ParseResult<Box<dyn Function>>; /// Types that act as functions. /// /// These types have to be able to parse tokens into themselves and store the /// relevant information from the parsing to do their role in typesetting later. /// -/// `FunctionRequirements` is automatically implemented for types which -/// can be used as functions, that is they fulfill the bounds -/// `Debug + PartialEq + 'static`. -pub trait Function: FunctionRequirements + 'static { +/// The trait `FunctionBounds` is automatically implemented for types which can be +/// used as functions, that is they fulfill the bounds `Debug + PartialEq + 'static`. +pub trait Function: FunctionBounds { /// Parse the function. fn parse(header: &FuncHeader, tokens: BodyTokens<'_>, scope: &Scope) - -> Result<Self, ParseError> where Self: Sized; + -> ParseResult<Self> where Self: Sized; /// Execute the function and optionally yield a return value. fn typeset(&self, header: &FuncHeader) -> Option<Expression>; } -/// A helper trait that describes requirements for types implement [`Function`]. +/// A map from identifiers to functions. +pub struct Scope { + parsers: HashMap<String, Box<ParseFunc>>, +} + +impl Scope { + /// Create a new empty scope. + pub fn new() -> Scope { + Scope { parsers: HashMap::new() } + } + + /// Add a function type to the scope with a given name. + pub fn add<F: Function + 'static>(&mut self, name: &str) { + self.parsers.insert( + name.to_owned(), + Box::new(|header, tokens, scope| match F::parse(header, tokens, scope) { + Ok(func) => Ok(Box::new(func)), + Err(err) => Err(err), + }) + ); + } + + /// Return the parser with the given name if there is one. + pub fn get_parser(&self, name: &str) -> Option<&ParseFunc> { + self.parsers.get(name).map(|x| &**x) + } +} + +/// A helper trait that describes requirements for types that can implement [`Function`]. /// /// Automatically implemented for all types which fulfill to the bounds -/// `Debug + PartialEq + 'static`. There should be no need to implement this -/// manually. -pub trait FunctionRequirements: Debug { +/// `Debug + PartialEq + 'static`. There should be no need to implement this manually. +pub trait FunctionBounds: Debug { /// Cast self into `Any`. fn help_cast_as_any(&self) -> &dyn Any; @@ -41,7 +71,7 @@ pub trait FunctionRequirements: Debug { fn help_eq(&self, other: &dyn Function) -> bool; } -impl<T> FunctionRequirements for T where T: Debug + PartialEq + 'static { +impl<T> FunctionBounds for T where T: Debug + PartialEq + 'static { fn help_cast_as_any(&self) -> &dyn Any { self } @@ -60,34 +90,3 @@ impl PartialEq for dyn Function { self.help_eq(other) } } - -/// A map from identifiers to functions. -pub struct Scope { - parsers: HashMap<String, Box<dyn Fn(&FuncHeader, BodyTokens<'_>, &Scope) - -> Result<Box<dyn Function>, ParseError>>>, -} - -impl Scope { - /// Create a new empty scope. - pub fn new() -> Scope { - Scope { parsers: HashMap::new() } - } - - /// Add a function type to the scope with a given name. - pub fn add<F: Function + 'static>(&mut self, name: &str) { - self.parsers.insert( - name.to_owned(), - Box::new(|header, tokens, scope| match F::parse(header, tokens, scope) { - Ok(func) => Ok(Box::new(func)), - Err(err) => Err(err), - }) - ); - } - - /// Return the parser with the given name if there is one. - pub fn get_parser(&self, name: &str) - -> Option<&dyn Fn(&FuncHeader, BodyTokens<'_>, &Scope) - -> Result<Box<dyn Function>, ParseError>> { - self.parsers.get(name).map(|x| &**x) - } -} |
