Skip to content

Proposed Enhancement for issue #7 #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions Math expression eval/UnitTest/TestAll.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1188,5 +1188,34 @@ public void Or_Operator_Test()
.Bind("b", 1);
Assert.AreEqual(true, expr4.Eval<bool>());
}


[TestMethod]
public void Custom_Function_Test()
{
//register new custom function
Parser.RegisterFunction("CUSTOM", typeof(customFunction));

//call function
var expr = new Expression("CUSTOM('1','a','#')");
Assert.AreEqual("1-a-#", expr.Eval<string>());
}

public class customFunction : org.matheval.Functions.IFunction
{
public List<org.matheval.Functions.FunctionDef> GetInfo()
{
return new List<org.matheval.Functions.FunctionDef> { new org.matheval.Functions.FunctionDef("custom", new Type[] { typeof(string), typeof(string), typeof(string) }, typeof(string), 3) };
}

public object Execute(Dictionary<string, object> args, ExpressionContext dc)
{
string a1 = (string)args["1"];
string a2 = (string)args["2"];
string a3 = (string)args["3"];

return string.Join("-", a1, a2, a3);
}
}
}
}
27 changes: 26 additions & 1 deletion Math expression eval/org.matheval/Parser/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,28 @@ namespace org.matheval
{
public class Parser
{
private static Dictionary<string, Type> _registeredFunctions;

/// <summary>
/// Registers a new custom function to all new Parsers
/// @param name function name as used in the expression
/// @param functionType type that implements the IFunction interface and will be used to handle the custom function call
/// </summary>
/// <param name="op">op</param>
public static void RegisterFunction(string name, Type functionType)
{
if (_registeredFunctions == null)
{
_registeredFunctions = new Dictionary<string, Type>();
}
//sanity check the provided type
//Additional checks could be done here to if needed.
if (functionType.IsAbstract || functionType.IsGenericType || !typeof(IFunction).IsAssignableFrom(functionType))
throw new ArgumentException(functionType.Name + " is not a concrete, non-generic type that implements the org.matheval.Functions.IFunction interface");

_registeredFunctions[name.ToLowerInvariant()] = functionType;
}

/// <summary>
/// Create object Lexer
/// </summary>
Expand Down Expand Up @@ -344,7 +366,10 @@ private Implements.Node ParseIdentifier()
IFunction funcExecuter;
try
{
Type t = Type.GetType("org.matheval.Functions." + identifierStr.ToLowerInvariant() + "Function", true);
if (_registeredFunctions == null || !_registeredFunctions.TryGetValue(identifierStr.ToLowerInvariant(), out Type t))
{
t = Type.GetType("org.matheval.Functions." + identifierStr.ToLowerInvariant() + "Function", true);
}
Object obj = (Activator.CreateInstance(t));

if (obj == null)
Expand Down