Skip to content

Commit

Permalink
feat: Function Definitions
Browse files Browse the repository at this point in the history
Function Definition can be added to 'group' functions together to make it easier to write expressions with a lot of redundant function calls

Resolves #59
  • Loading branch information
thygesteffensen committed Feb 28, 2022
1 parent 6290a57 commit 0efcfad
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 4 deletions.
19 changes: 17 additions & 2 deletions ExpressionEngine/ExpressionGrammar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ namespace ExpressionEngine
{
public class ExpressionGrammar
{
private readonly IList<IFunctionDefinition> _functionDefinitions;
private readonly Parser<IRule> _method;
private readonly Parser<Task<ValueContainer>> _input;

public ExpressionGrammar(IEnumerable<IFunction> functions)
public ExpressionGrammar(IEnumerable<IFunction> functions, IEnumerable<IFunctionDefinition> functionDefinitions)
{
_functionDefinitions = functionDefinitions?.ToList();

var functionCollection = functions ?? throw new ArgumentNullException(nameof(functions));

#region BasicAuxParsers
Expand Down Expand Up @@ -122,13 +125,25 @@ from t in simpleString.Or(allowedCharacters).Many()

public async ValueTask<string> EvaluateToString(string input)
{
var output = await _input.Parse(input);
var output = await PreAnalyzeAndParse(input);

return output.GetValue<string>();
}

public async ValueTask<ValueContainer> EvaluateToValueContainer(string input)
{
return await PreAnalyzeAndParse(input);
}

private async ValueTask<ValueContainer> PreAnalyzeAndParse(string input)
{
if (_functionDefinitions != null)
{
input = _functionDefinitions.Aggregate(input,
(current, functionDefinition) =>
current.Replace(functionDefinition.From(), functionDefinition.To()));
}

return await _input.Parse(input);
}
}
Expand Down
11 changes: 11 additions & 0 deletions ExpressionEngine/FlowRunnerDependencyExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ public static void AddExpressionEngine(this IServiceCollection services)
services.AddTransient<IFunction, GreaterFunction>();
}

/// <summary>
/// Added FunctionDefinition to service collection
/// </summary>
/// <param name="services"></param>
/// <param name="from"></param>
/// <param name="to"></param>
public static void AddFunctionDefinition(this IServiceCollection services, string from, string to)
{
services.AddTransient<IFunctionDefinition, FunctionDefinition>(_ => new FunctionDefinition(from, to));
}

private static void AddStringFunctions(IServiceCollection services)
{
services.AddTransient<IFunction, ConcatFunction>();
Expand Down
41 changes: 41 additions & 0 deletions ExpressionEngine/FunctionDefinition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace ExpressionEngine
{
/// <summary>
/// A Function Definition is a map to a collected set of functions.
/// - currentCellValue() -> formvalue(logicalName())[idx()][attributeLogicalName()]
/// </summary>
public class FunctionDefinition : IFunctionDefinition
{
private readonly string _from;
private readonly string _to;

/// <summary>
/// Construction a Function Definition
/// </summary>
/// <param name="from"></param>
/// <param name="to"></param>
public FunctionDefinition(string from, string to)
{
_from = @from;
_to = to;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public string From()
{
return _from;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public string To()
{
return _to;
}
}
}
8 changes: 8 additions & 0 deletions ExpressionEngine/IFunctionDefinition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace ExpressionEngine
{
public interface IFunctionDefinition
{
public string From();
public string To();
}
}
2 changes: 1 addition & 1 deletion Test/ExpressionGrammarTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public void SetUp()

var functions = new List<IFunction> {_dummyFunction};

_expressionGrammar = new ExpressionGrammar(functions);
_expressionGrammar = new ExpressionGrammar(functions, null);
}

[Test]
Expand Down
32 changes: 32 additions & 0 deletions Test/FunctionDefinitionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Threading.Tasks;
using ExpressionEngine;
using Microsoft.Extensions.DependencyInjection;
using NUnit.Framework;

namespace Test
{
public class FunctionDefinitionTests
{
private IExpressionEngine _ee;

[SetUp]
public void Setup()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddExpressionEngine();
serviceCollection.AddFunctionDefinition("addAndConcat()", "concat('result of 1+1 is: ', add(1,1))");

_ee = serviceCollection.BuildServiceProvider().GetRequiredService<IExpressionEngine>();
}

[TestCase]
public async Task TestFunctionDef()
{
const string expectedResult = "result of 1+1 is: 2!";

var actualResult = await _ee.Parse("@concat(addAndConcat(), '!')");

Assert.AreEqual(expectedResult, actualResult);
}
}
}
2 changes: 1 addition & 1 deletion Test/NullCoalescingTest2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void Setup()

var functions = new List<IFunction> {_returnData};

_expressionGrammar = new ExpressionGrammar(functions);
_expressionGrammar = new ExpressionGrammar(functions, null);
}

[Test]
Expand Down

0 comments on commit 0efcfad

Please sign in to comment.