From 14c9ff571d41e01fe46fb842aa5ea1b93497c4ab Mon Sep 17 00:00:00 2001 From: Laurenz Date: Mon, 29 Apr 2019 11:03:17 +0200 Subject: =?UTF-8?q?Remove=20stack=20from=20parser=20=E2=99=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/func.rs | 83 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 41 insertions(+), 42 deletions(-) (limited to 'src/func.rs') 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> + 'a>>; +/// Parser functions. +pub type ParseFunc = dyn Fn(&FuncHeader, BodyTokens<'_>, &Scope) + -> ParseResult>; /// 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 where Self: Sized; + -> ParseResult where Self: Sized; /// Execute the function and optionally yield a return value. fn typeset(&self, header: &FuncHeader) -> Option; } -/// A helper trait that describes requirements for types implement [`Function`]. +/// A map from identifiers to functions. +pub struct Scope { + parsers: HashMap>, +} + +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(&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 FunctionRequirements for T where T: Debug + PartialEq + 'static { +impl 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, &Scope) - -> Result, 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(&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, ParseError>> { - self.parsers.get(name).map(|x| &**x) - } -} -- cgit v1.2.3