summaryrefslogtreecommitdiff
path: root/src/func.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2019-04-29 11:03:17 +0200
committerLaurenz <laurmaedje@gmail.com>2019-04-29 11:03:17 +0200
commit14c9ff571d41e01fe46fb842aa5ea1b93497c4ab (patch)
tree0a09cec0552dcd990d12df8ab361271112d4bb83 /src/func.rs
parentf279c52b503e9dacb558d8a46a75b42bc5222ee4 (diff)
Remove stack from parser ♻
Diffstat (limited to 'src/func.rs')
-rw-r--r--src/func.rs83
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)
- }
-}