Skip to content

Commit c6575df

Browse files
Merge pull request #85 from delegateas/dev
New RELEASE
2 parents 0e708df + 942eec5 commit c6575df

File tree

75 files changed

+762
-664
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+762
-664
lines changed

.github/workflows/.releaserc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ plugins:
1414
- assets:
1515
- path: ../../artifacts/ExpressionEngine.*.nupkg
1616
label: Parser DLL
17+
- path: ../../artifacts/Documentation.md
18+
label: Documentation
1719

1820
- - "@semantic-release/exec"
1921
- publishCmd: "dotnet nuget push ..\\..\\artifacts\\Delegate.ExpressionEngine.*.nupkg --source https://nuget.pkg.github.com/delegateas/index.json --api-key ${process.env.GITHUB_TOKEN}"

.github/workflows/build.yml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,9 @@ jobs:
8080
- name: Archive build to artifacts
8181
uses: actions/[email protected]
8282
with:
83-
name: build
83+
name: Build
8484
path: |
8585
build/netcoreapp3.1/
8686
build/net5.0/
87+
Documentation.md
8788
retention-days: 5
88-
89-
- name: Archive documentation to artifacts
90-
uses: actions/[email protected]
91-
with:
92-
name: Documentation
93-
path: Documentation.md

.github/workflows/release.yml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,28 @@ jobs:
6060

6161
- name: Cleaning
6262
run: dotnet clean
63+
if: ${{ env.RELEASE_VERSION }}
6364

6465
- name: Restore NuGet packages
6566
run: dotnet restore ExpressionEngine.sln
67+
if: ${{ env.RELEASE_VERSION }}
6668

6769
- name: Package Parser
6870
run: dotnet pack -c Release -p:PackageVersion=${env:RELEASE_VERSION} -o ./artifacts
6971
if: ${{ env.RELEASE_VERSION }}
72+
73+
- name: Install Xml to Markdown tool
74+
run: dotnet new tool-manifest && dotnet tool install EAVFW.Extensions.Docs.TransformToMarkdown --version 1.0.0
75+
if: ${{ env.RELEASE_VERSION }}
76+
77+
- name: Generate docs
78+
run: dotnet tool run tomd --input ExpressionEngine/bin/Release/net5.0/ExpressionEngine.xml --output artifacts/Documentation.md
79+
if: ${{ env.RELEASE_VERSION }}
7080

7181
- name: Release to GitHub and NuGet
7282
working-directory: .\\.github\\workflows
7383
env:
7484
CI_NUGET_API_KEY: ${{ secrets.NUGETAPIKEY }}
75-
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
76-
GIT_AUTHOR_NAME: thygesteffensen
77-
GIT_AUTHOR_EMAIL: [email protected]
85+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
7886
run: npx semantic-release
87+
if: ${{ env.RELEASE_VERSION }}

ExpressionEngine/ExpressionGrammar.cs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@ namespace ExpressionEngine
1010
{
1111
public class ExpressionGrammar
1212
{
13+
private readonly IList<IFunctionDefinition> _functionDefinitions;
1314
private readonly Parser<IRule> _method;
1415
private readonly Parser<Task<ValueContainer>> _input;
1516

16-
public ExpressionGrammar(IEnumerable<IFunction> functions)
17+
public ExpressionGrammar(IEnumerable<FunctionMetadata> functions, IEnumerable<IFunctionDefinition> functionDefinitions, IServiceProvider serviceProvider)
1718
{
18-
var functionCollection = functions ?? throw new ArgumentNullException(nameof(functions));
19+
_functionDefinitions = functionDefinitions?.ToList();
20+
21+
var functionCollection = functions.ToList() ?? throw new ArgumentNullException(nameof(functions));
1922

2023
#region BasicAuxParsers
2124

@@ -28,10 +31,12 @@ public ExpressionGrammar(IEnumerable<IFunction> functions)
2831
constString => new ConstantRule(new ValueContainer(constString, true))
2932
);
3033

31-
Parser<IRule> decimalInvariant =
32-
Parse.DecimalInvariant.Select(x => new ConstantRule(new ValueContainer(x, true)));
33-
34-
Parser<IRule> number = decimalInvariant.Or(integer);
34+
Parser<IRule> number = // decimalInvariant.Or(integer);
35+
from sign in Parse.Char('-').Or(Parse.Char('+')).Optional()
36+
from number1 in Parse.DecimalInvariant.Or(Parse.Digit.AtLeastOnce().Text())
37+
select sign.IsDefined && sign.Get().Equals('-')
38+
? new ConstantRule(new ValueContainer('-' + number1, true))
39+
: new ConstantRule(new ValueContainer(number1, true));
3540

3641
Parser<string> simpleString =
3742
Parse.AnyChar.Except(Parse.Char('@')).AtLeastOnce().Text();
@@ -87,7 +92,7 @@ from args in argument.Token().DelimitedBy(Parse.Char(',')).Optional()
8792
from mandatoryLetter in Parse.Letter
8893
from rest in Parse.LetterOrDigit.Many().Text()
8994
from args in arguments.Contained(lParenthesis, rParenthesis)
90-
select new ExpressionRule(functionCollection, mandatoryLetter + rest,
95+
select new ExpressionRule(functionCollection, serviceProvider, mandatoryLetter + rest,
9196
args.IsEmpty
9297
? null
9398
: args.Get());
@@ -122,13 +127,25 @@ from t in simpleString.Or(allowedCharacters).Many()
122127

123128
public async ValueTask<string> EvaluateToString(string input)
124129
{
125-
var output = await _input.Parse(input);
130+
var output = await PreAnalyzeAndParse(input);
126131

127132
return output.GetValue<string>();
128133
}
129134

130135
public async ValueTask<ValueContainer> EvaluateToValueContainer(string input)
131136
{
137+
return await PreAnalyzeAndParse(input);
138+
}
139+
140+
private async ValueTask<ValueContainer> PreAnalyzeAndParse(string input)
141+
{
142+
if (_functionDefinitions != null)
143+
{
144+
input = _functionDefinitions.Aggregate(input,
145+
(current, functionDefinition) =>
146+
current.Replace(functionDefinition.From, functionDefinition.To));
147+
}
148+
132149
return await _input.Parse(input);
133150
}
134151
}
Lines changed: 122 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using ExpressionEngine.Functions.Base;
1+
using System;
2+
using ExpressionEngine.Functions.Base;
3+
using ExpressionEngine.Functions.CustomException;
24
using ExpressionEngine.Functions.Implementations.CollectionFunctions;
35
using ExpressionEngine.Functions.Implementations.ConversionFunctions;
46
using ExpressionEngine.Functions.Implementations.LogicalComparisonFunctions;
@@ -8,8 +10,15 @@
810

911
namespace ExpressionEngine
1012
{
13+
/// <summary>
14+
/// Selection of extension methods
15+
/// </summary>
1116
public static class FlowRunnerDependencyExtension
1217
{
18+
/// <summary>
19+
/// Add necessary dependencies inorder to use expression engine.
20+
/// </summary>
21+
/// <param name="services"><see cref="IServiceCollection"/> to add dependencies</param>
1322
public static void AddExpressionEngine(this IServiceCollection services)
1423
{
1524
services.AddScoped<IExpressionEngine, ExpressionEngine>();
@@ -21,81 +30,138 @@ public static void AddExpressionEngine(this IServiceCollection services)
2130
AddLogicalComparisonFunctions(services);
2231
AddMathFunctions(services);
2332

24-
services.AddTransient<IFunction, LengthFunction>();
25-
services.AddTransient<IFunction, GreaterFunction>();
33+
services.RegisterTransientFunctionAlias<LengthFunction>("length");
34+
services.RegisterTransientFunctionAlias<GreaterFunction>("greater");
35+
}
36+
37+
/// <summary>
38+
/// Register function to be used in expression, function implementation must implement <see cref="IFunction"/>.
39+
/// </summary>
40+
/// <param name="services">Services which to add function metadata</param>
41+
/// <param name="functionName">name of function used to invoke it</param>
42+
/// <typeparam name="T">Function implementation</typeparam>
43+
public static void RegisterTransientFunctionAlias<T>(this IServiceCollection services, string functionName)
44+
where T : class, IFunction
45+
{
46+
services.AddTransient<T>();
47+
services.AddSingleton(new FunctionMetadata(typeof(T), functionName));
48+
}
49+
50+
/// <summary>
51+
/// Register function to be used in expression, function implementation must implement <see cref="IFunction"/>.
52+
/// </summary>
53+
/// <param name="services">Services which to add function metadata</param>
54+
/// <param name="functionName">name of function used to invoke it</param>
55+
/// <typeparam name="T">Function implementation</typeparam>
56+
public static void RegisterScopedFunctionAlias<T>(this IServiceCollection services, string functionName)
57+
where T : class, IFunction
58+
{
59+
services.AddScoped<T>();
60+
services.AddSingleton(new FunctionMetadata(typeof(T), functionName));
61+
}
62+
63+
/// <summary>
64+
/// Register function to be used in expression, function implementation must implement <see cref="IFunction"/>.
65+
/// </summary>
66+
/// <param name="services">Services which to add function metadata</param>
67+
/// <param name="functionName">name of function used to invoke it</param>
68+
/// <param name="implementationFactory"></param>
69+
/// <typeparam name="T">Function implementation</typeparam>
70+
public static void RegisterScopedFunctionAlias<T>(this IServiceCollection services, string functionName,
71+
Func<IServiceProvider, T> implementationFactory)
72+
where T : class, IFunction
73+
{
74+
services.AddScoped(implementationFactory);
75+
services.AddSingleton(new FunctionMetadata(typeof(T), functionName));
76+
}
77+
78+
/// <summary>
79+
/// Added FunctionDefinition to service collection.
80+
/// </summary>
81+
/// <param name="services"></param>
82+
/// <param name="fromFunctionName">The name of the function, without function parenthesis</param>
83+
/// <param name="toExpression">The full expression which is inserted</param>
84+
public static void AddFunctionDefinition(this IServiceCollection services, string fromFunctionName, string toExpression)
85+
{
86+
if (fromFunctionName.EndsWith("()"))
87+
{
88+
throw new ArgumentError($"{nameof(fromFunctionName)} cannot end in ()");
89+
}
90+
91+
services.AddSingleton<IFunctionDefinition>(new FunctionDefinition{From = fromFunctionName + "()", To = toExpression});
2692
}
2793

2894
private static void AddStringFunctions(IServiceCollection services)
2995
{
30-
services.AddTransient<IFunction, ConcatFunction>();
31-
services.AddTransient<IFunction, EndsWithFunction>();
32-
services.AddTransient<IFunction, FormatNumberFunction>();
33-
services.AddTransient<IFunction, GuidFunction>();
34-
services.AddTransient<IFunction, IndexOfFunction>();
35-
services.AddTransient<IFunction, LastIndexOfFunction>();
36-
services.AddTransient<IFunction, LengthFunction>();
37-
services.AddTransient<IFunction, ReplaceFunction>();
38-
services.AddTransient<IFunction, SplitFunction>();
39-
services.AddTransient<IFunction, StartsWithFunction>();
40-
services.AddTransient<IFunction, SubstringFunction>();
41-
services.AddTransient<IFunction, ToLowerFunction>();
42-
services.AddTransient<IFunction, ToUpperFunction>();
43-
services.AddTransient<IFunction, TrimFunction>();
96+
services.RegisterTransientFunctionAlias<ConcatFunction>("concat");
97+
services.RegisterTransientFunctionAlias<EndsWithFunction>("endsWith");
98+
services.RegisterTransientFunctionAlias<FormatNumberFunction>("formatNumber");
99+
services.RegisterTransientFunctionAlias<GuidFunction>("guid");
100+
services.RegisterTransientFunctionAlias<IndexOfFunction>("indexOf");
101+
services.RegisterTransientFunctionAlias<LastIndexOfFunction>("lastIndexOf");
102+
services.RegisterTransientFunctionAlias<LengthFunction>("length");
103+
services.RegisterTransientFunctionAlias<ReplaceFunction>("replace");
104+
services.RegisterTransientFunctionAlias<SplitFunction>("split");
105+
services.RegisterTransientFunctionAlias<StartsWithFunction>("startsWith");
106+
services.RegisterTransientFunctionAlias<SubstringFunction>("substring");
107+
services.RegisterTransientFunctionAlias<ToLowerFunction>("toLower");
108+
services.RegisterTransientFunctionAlias<ToUpperFunction>("toUpper");
109+
services.RegisterTransientFunctionAlias<TrimFunction>("trim");
44110
}
45111

46112
private static void AddCollectionFunction(IServiceCollection services)
47113
{
48-
services.AddTransient<IFunction, ContainsFunction>();
49-
services.AddTransient<IFunction, EmptyFunction>();
50-
services.AddTransient<IFunction, FirstFunction>();
51-
services.AddTransient<IFunction, InterSectionFunction>();
52-
services.AddTransient<IFunction, JoinFunction>();
53-
services.AddTransient<IFunction, LastFunction>();
54-
services.AddTransient<IFunction, LengthFunction>();
55-
services.AddTransient<IFunction, SkipFunction>();
56-
services.AddTransient<IFunction, TakeFunction>();
57-
services.AddTransient<IFunction, UnionFunction>();
114+
services.RegisterTransientFunctionAlias<ContainsFunction>("contains");
115+
services.RegisterTransientFunctionAlias<EmptyFunction>("empty");
116+
services.RegisterTransientFunctionAlias<FirstFunction>("first");
117+
services.RegisterTransientFunctionAlias<InterSectionFunction>("intersection");
118+
services.RegisterTransientFunctionAlias<JoinFunction>("join");
119+
services.RegisterTransientFunctionAlias<LastFunction>("last");
120+
services.RegisterTransientFunctionAlias<LengthFunction>("length");
121+
services.RegisterTransientFunctionAlias<SkipFunction>("skip");
122+
services.RegisterTransientFunctionAlias<TakeFunction>("take");
123+
services.RegisterTransientFunctionAlias<UnionFunction>("union");
58124
}
59125

60126
private static void AddConversionFunction(IServiceCollection services)
61127
{
62-
services.AddTransient<IFunction, ArrayFunction>();
63-
services.AddTransient<IFunction, Base64Function>();
64-
services.AddTransient<IFunction, Base64ToBinaryFunction>();
65-
services.AddTransient<IFunction, Base64ToStringFunction>();
66-
services.AddTransient<IFunction, BinaryFunction>();
67-
services.AddTransient<IFunction, BoolFunction>();
68-
services.AddTransient<IFunction, CreateArrayFunction>();
69-
services.AddTransient<IFunction, DataUriFunction>();
70-
services.AddTransient<IFunction, DataUriToBinaryFunction>();
71-
services.AddTransient<IFunction, FloatFunction>();
72-
services.AddTransient<IFunction, IntFunction>();
128+
services.RegisterTransientFunctionAlias<ArrayFunction>("array");
129+
services.RegisterTransientFunctionAlias<Base64Function>("base64");
130+
services.RegisterTransientFunctionAlias<Base64ToBinaryFunction>("base64ToBinary");
131+
services.RegisterTransientFunctionAlias<Base64ToStringFunction>("base64ToString");
132+
services.RegisterTransientFunctionAlias<BinaryFunction>("binary");
133+
services.RegisterTransientFunctionAlias<BoolFunction>("bool");
134+
services.RegisterTransientFunctionAlias<CreateArrayFunction>("createArray");
135+
services.RegisterTransientFunctionAlias<DataUriFunction>("dataUri");
136+
services.RegisterTransientFunctionAlias<DataUriToBinaryFunction>("dataUriToBinary");
137+
services.RegisterTransientFunctionAlias<FloatFunction>("float");
138+
services.RegisterTransientFunctionAlias<IntFunction>("int");
73139
}
74140

75141
private static void AddLogicalComparisonFunctions(IServiceCollection services)
76142
{
77-
services.AddTransient<IFunction, AndFunction>();
78-
services.AddTransient<IFunction, EqualFunction>();
79-
services.AddTransient<IFunction, GreaterFunction>();
80-
services.AddTransient<IFunction, GreaterOrEqualsFunction>();
81-
services.AddTransient<IFunction, IfFunction>();
82-
services.AddTransient<IFunction, LessFunction>();
83-
services.AddTransient<IFunction, LessOrEqualsFunction>();
84-
services.AddTransient<IFunction, NotFunction>();
85-
services.AddTransient<IFunction, OrFunction>();
143+
services.RegisterTransientFunctionAlias<AndFunction>("and");
144+
services.RegisterTransientFunctionAlias<EqualFunction>("equal");
145+
services.RegisterTransientFunctionAlias<GreaterFunction>("greater");
146+
services.RegisterTransientFunctionAlias<GreaterOrEqualsFunction>("greaterOrEquals");
147+
services.RegisterTransientFunctionAlias<IfFunction>("if");
148+
services.RegisterTransientFunctionAlias<LessFunction>("less");
149+
services.RegisterTransientFunctionAlias<LessOrEqualsFunction>("lessOrEquals");
150+
services.RegisterTransientFunctionAlias<NotFunction>("not");
151+
services.RegisterTransientFunctionAlias<OrFunction>("or");
86152
}
87153

88154
private static void AddMathFunctions(IServiceCollection services)
89155
{
90-
services.AddTransient<IFunction, AddFunction>();
91-
services.AddTransient<IFunction, DivFunction>();
92-
services.AddTransient<IFunction, MaxFunction>();
93-
services.AddTransient<IFunction, MinFunction>();
94-
services.AddTransient<IFunction, ModFunction>();
95-
services.AddTransient<IFunction, MulFunction>();
96-
services.AddTransient<IFunction, RandFunction>();
97-
services.AddTransient<IFunction, RangeFunction>();
98-
services.AddTransient<IFunction, SubFunction>();
156+
services.RegisterTransientFunctionAlias<AddFunction>("add");
157+
services.RegisterTransientFunctionAlias<DivFunction>("div");
158+
services.RegisterTransientFunctionAlias<MaxFunction>("max");
159+
services.RegisterTransientFunctionAlias<MinFunction>("min");
160+
services.RegisterTransientFunctionAlias<ModFunction>("mod");
161+
services.RegisterTransientFunctionAlias<MulFunction>("mul");
162+
services.RegisterTransientFunctionAlias<RandFunction>("rand");
163+
services.RegisterTransientFunctionAlias<RangeFunction>("range");
164+
services.RegisterTransientFunctionAlias<SubFunction>("sub");
99165
}
100166
}
101167
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace ExpressionEngine
2+
{
3+
/// <summary>
4+
/// A Function Definition is a map to a collected set of functions.
5+
/// - currentCellValue() -> formvalue(logicalName())[idx()][attributeLogicalName()]
6+
/// </summary>
7+
public class FunctionDefinition : IFunctionDefinition
8+
{
9+
/// <summary>
10+
/// The from 'function name' which is replaced
11+
/// </summary>
12+
public string From { get; set; }
13+
/// <summary>
14+
/// The replacement
15+
/// </summary>
16+
public string To { get; set; }
17+
}
18+
}

0 commit comments

Comments
 (0)