Skip to content

Commit 8bc5d7a

Browse files
committed
Skip feature and documentation
1 parent 3d69a07 commit 8bc5d7a

File tree

4 files changed

+56
-14
lines changed

4 files changed

+56
-14
lines changed

Docs/FexElementsRef.md

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,24 @@ Flow Expressions are defined by a structure of *FexElements* built via a Fluent
88
## Factory: `FlowExpression<T>`
99

1010
The `FlowExpression<T>` class operates as a *factory* to build and return FexElements which are used in other productions or as the *Axiom* (root) to be run.
11-
> The innards of each element are built via the encapsulated `FexBuilder<T>` class.
11+
> - The innards of each element are built via the encapsulated `FexBuilder<T>` class.
12+
> - **`Skip()` feature:** Sometimes when parsing spaces/white-space/other needs to be skipped between tokens:
13+
> - FexBuilder provides a common Skip() action that can be placed anywhere for this purpose.
14+
> - FlowExpression has a method `DefSkip(Action<Ctx> skipAction)` to define what this skip action must be and must be defined before creating any elements.
1215
1316
**Basic mechanism:**
1417
```csharp
1518
using Psw.FlowExpressions;
1619

1720
// Create a FlowEpression factory using FexScanner as the context:
1821
var fex = new FlowExpression<FexScanner>();
22+
fex.DefSkip(Action<T> skipAction) // Optionally define the Skip action.
1923
20-
// Create a sequence element (element is of type FexElement<T>):
24+
// Create a sequence element (returned element is of type FexElement<T>):
2125
var element = fex.Seq(Action<FexBuilder<T>> buildFex);
2226

2327
// Run the element (axiom) with supplied context and process result.
24-
bool result = element.Run(new FexScanner("text to process"));
28+
bool result = element.Run(new FexScanner("text to parse"));
2529

2630
// Handle pass or failure:
2731
```
@@ -46,6 +50,7 @@ mechanism with methods of the following basic form:
4650
| [`Op(Func<Ctx, bool> op)`](#id-op) | **Operator:** Perform an operation on the Context returning a boolean result. |
4751
| [`ValidOp(Action<Ctx> action)`](#id-validop) | **Always valid operator:** Perform and operation on the Context and always returns true. |
4852
| [`GlobalPreOp(Action<Ctx> preOp)`<br/>`PreOp(Action<T> preOp)`](#id-preop) | **Pre-Operators:** Attach pre-operations to operators. |
53+
| [`Skip()`<br/>`GlobalSkip()`](#id-skip) | **Skip Action:** Perform a common Skip action previously defined via `FexScanner.DefSkip(...)`. |
4954
| **Flow Control:** | *These elements control the flow of an expression.* |
5055
| [`Opt(o => o...)*` ](#id-opt) | **Optional:** Optional sequence. |
5156
| [`OneOf(o => o...)*`](#id-oneof) | **One Of:** Set of sequences that are *Or'd* together and one of them must succeed to pass. |
@@ -189,6 +194,39 @@ See the Expression example which uses a GlobalPreOp to skip all spaces before th
189194

190195
[`TOC`](#id-toc)
191196

197+
---
198+
<a id="id-skip"></a>
199+
### Skip Actions:
200+
201+
Used when a common skipping action is required between tokens:
202+
- Typically used to skip spaces, comments and newlines etc. between tokens when parsing scripts.
203+
- The action to perform must be pre-defined via `FexExpression.DefSkip(Action<Ctx> skipAction)` and must be defined before any other productions.
204+
- The Skip operation may be placed anywhere and runs as an action that does not affects the validity of a sequence. If no skip action is define it's just ignored.
205+
206+
<br/>
207+
208+
> **`GlobalSkip()`**
209+
> - Sets the skip action as a GlobalPreOp.
210+
211+
```csharp
212+
var fex = new FlowExpression<FexScanner>(); // Flow Expression using FexScanner.
213+
fex.DefSkip(c => c.SkipSp()); // Define a Skip operation to skip spaces.
214+
string dcode = "", acode = "", number = ""; // Will record values in here.
215+
216+
// Build the flow expression with 'Axiom' tnumber:
217+
var tnumber = fex.Seq(s => s
218+
.Ch('(').OnFail("( expected")
219+
.Rep(3, -1, r => r.Digit(v => dcode += v)).OnFail("3+ digit dialing code expected")
220+
.Ch(')').OnFail(") expected")
221+
.Skip() // Perform the previously defined skip operation
222+
.Rep(3, r => r.Digit(v => acode += v)).OnFail("3 digit area code expected")
223+
.AnyCh("- ").OnFail("- or space expected")
224+
.Rep(4, r => r.Digit(v => number += v)).OnFail("4 digit number expected")
225+
);
226+
```
227+
228+
[`TOC`](#id-toc)
229+
192230
---
193231
<a id="id-opt"></a>
194232
### `Optional: Opt(o => o...)`

FexSampleSet/Program.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ void RunSamplesFex() {
5757
new Sample("Simple Scanner 2 (valid)", () => SSDemo.DemoSimpleScanner2(" N3 N1N3-abc")),
5858
new Sample("Simple Scanner 2 (invalid)", () => SSDemo.DemoSimpleScanner2(" N3 N1N2-ac")),
5959
new Sample("Expression Eval", () => ExpressionEval()),
60+
new Sample("Expression Eval (with tracing)", () => TraceExpressionEval()),
6061
new Sample("Expression REPL", () => ExpressionREPL()),
6162
};
6263

@@ -96,7 +97,7 @@ void QuickStart() {
9697
*/
9798

9899
var fex = new FlowExpression<FexScanner>(); // Flow Expression using FexScanner.
99-
fex.DefSkip(c => c.SkipSp()); // Define the Skip operation to skip spaces.
100+
fex.DefSkip(c => c.SkipSp()); // Define a Skip operation to skip spaces.
100101

101102
string dcode = "", acode = "", number = ""; // Will record values in here.
102103

@@ -198,7 +199,7 @@ void ExpressionEval(string calc = "9 - (5.5 + 3) * 6 - 4 / ( 9 - 1 )")
198199
: scn.ErrorLog.AsConsoleError("Expression Error:"));
199200
}
200201

201-
// Expression Evaluation - using FexParser
202+
// Expression Evaluation with Tracing example - using FexParser
202203
void TraceExpressionEval(string calc = "9 - (5.5 + 3) * 6 - 4 / ( 9 - 1 )")
203204
{
204205
// Expression Grammar:
@@ -426,6 +427,9 @@ public Sample(string name, Action action) {
426427
}
427428
}
428429

430+
/// <summary>
431+
/// IFexTracer implementation for Console output
432+
/// </summary>
429433
public class ConsoleTracer : IFexTracer
430434
{
431435
public void Trace(string message, int level) {

Psw.FlowExpressions/FexBuilder.cs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -247,11 +247,10 @@ public FexBuilder<T> ActValue<V>(Action<V> valueAction) {
247247
}
248248

249249
/// <summary>
250-
/// Perform the previously defined (via FlowExpression.DefSkip(...)) skip operation:<br/>
251-
/// - Typically used to skip spaces etc.<br/>
252-
/// - Runs if defined and does no affect the validity of a sequence.
250+
/// Perform the previously defined Skip action (define via FlowExpression.DefSkip(...)):<br/>
251+
/// - Typically used to skip spaces/white-space etc.<br/>
252+
/// - Runs, if defined, as an action and does no affect the validity of a sequence.
253253
/// </summary>
254-
/// <returns></returns>
255254
public FexBuilder<T> Skip() => Act(_buildState.SkipOp);
256255

257256

@@ -267,12 +266,12 @@ public FexBuilder<T> GlobalPreOp(Action<T>? preOp) {
267266
}
268267

269268
/// <summary>
270-
/// Binds the previously defined (via FlowExpression.DefSkip(...)) skip operation as pre-operator to all subsequent operators:<br/>
269+
/// Binds the previously defined Skip action (define via FlowExpression.DefSkip(...)) as pre-operator to all subsequent operators:<br/>
271270
/// - A pre-operator executes before an operator as an action on the context:<br/>
272-
/// - Typically used to skip spaces etc. before tokens when parsing.<br/>
271+
/// - Typically used to skip spaces/white-space etc. before tokens when parsing.<br/>
273272
/// - Pre-operators are efficient an only execute once while trying several lookahead operations.
274273
/// </summary>
275-
public FexBuilder<T> SkipGlobalPreOp() => GlobalPreOp(_buildState.SkipOp);
274+
public FexBuilder<T> GlobalSkip() => GlobalPreOp(_buildState.SkipOp);
276275

277276

278277
/// <summary>

Psw.FlowExpressions/Psw.FlowExpressions.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212
<Copyright>2023 Promic Software</Copyright>
1313
<PackageProjectUrl>https://github.com/promicsw/flow-expressions</PackageProjectUrl>
1414
<RepositoryUrl>https://github.com/promicsw/flow-expressions</RepositoryUrl>
15-
<PackageTags>parser;parser builder;flow logic;c#;</PackageTags>
16-
<PackageReleaseNotes>Initial release.</PackageReleaseNotes>
15+
<PackageTags>parser;parser-builder;flow-logic;c#;flow-expression;</PackageTags>
16+
<PackageReleaseNotes>Skip feature added for common skipping actions during parsing.</PackageReleaseNotes>
1717
<PackageLicenseExpression>MIT</PackageLicenseExpression>
1818
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
1919
<PackageReadmeFile>Nuget.md</PackageReadmeFile>
2020
<PackageOutputPath>d:\PromicSW_GitHub\LocalNuget\</PackageOutputPath>
2121
<PackageIcon>PswLogo.png</PackageIcon>
22+
<Version>1.0.1</Version>
2223
</PropertyGroup>
2324

2425
<ItemGroup>

0 commit comments

Comments
 (0)