You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Flow Expressions are defined by a structure of *FexElements* built via a Fluent API. This defines the logical flow and operations of the flow expression in a very readable format closely resembling a flow *grammar*:
@@ -39,47 +36,58 @@ mechanism with methods of the following basic form:
39
36
> - The details of each element type are documented below.
40
37
> -**Note:** Only elements marked with an Astrix * may be constructed via the FlowExpression factory.
41
38
39
+
40
+
<aid="id-toc"></a>
41
+
42
42
| Fex Element | Brief |
43
43
| :---------- | :---- |
44
44
|[`Seq(s => s...)*`](#id-seq)|**Sequence:** Series of steps that must complete in full in order to pass. |
45
+
|**Operators:**|*Perform an operation on the context producing a boolean result.<br> (see also [FexScanner operator extensions](Docs/FexScannerExt.md) when using FexScanner as the context)*|
45
46
|[`Op(Func<Ctx, bool> op)`](#id-op)|**Operator:** Perform an operation on the Context returning a boolean result. |
46
47
|[`ValidOp(Action<Ctx> action)`](#id-validop)|**Always valid operator:** Perform and operation on the Context and always returns true. |
47
-
|[`ActValue<V>(Action<V> valueAction)`](#id-value)|**Value Action:** Bind and action to an operator that records a value. |
48
+
|[`GlobalPreOp(Action<Ctx> preOp)`<br/>`PreOp(Action<T> preOp)`](#id-preop)|**Pre-Operators:** Attach pre-operations to operators. |
49
+
|**Flow Control:**|*These elements control the flow of an expression.*|
|[`OneOf(o => o...)*`](#id-oneof)|**One Of:** Set of sequences that are *Or'd* together and one of them must succeed to pass. |
50
52
|[`OptOneOf(o => o...)`*](#id-optoneof)|**Optional One Of:** Optionally perform a OneOf. |
51
53
|[`NotOneOf(o => o...)*`](#id-notoneof)|**Not One Of:** Inverse of OneOf. |
52
54
|[`BreakOn(o => o...)`](#id-notoneof)|**Alias for NotOneOf:** Reads better in loops. |
53
55
|[`Rep(repMin, repMax, r => r...)*`<br/>`Rep(count, r => r...)*`<br/>`Rep0N(r => r...)*`<br/>`Rep1N(r => r...)`*](#id-rep)|**Repeat:** Repeated sequences. |
54
56
|[`RepOneOf(repMin, repMax, r => r...)`*](#id-reponeof)|**Repeat One Of:** Repeated a OneOf expression. |
55
-
|[`Fex(FexElement1, FexElement2, ...)`](#id-fex)|**Include FexElements:**Include a set of previously defined FexElements.|
57
+
|**Actions:**|*Perform actions based on the current state of a production.<br> (see also [FexScanner action extensions](Docs/FexScannerExt.md) when using FexScanner as the context)*|
56
58
|[`Act(Action<Ctx> action)`](#id-act)|**Action:** Perform any external Action based on the current state of the production. |
59
+
|[`ActValue<V>(Action<V> valueAction)`](#id-value)|**Value Action:** Bind and action to an operator that records a value. |
57
60
|[`RepAct(int repeat, Action<Ctx, int> action)`](#id-repact)|**Repeat Action:** Perform any external repeated Action based on the current state of the production. |
61
+
|**Error Handling:**||
58
62
|[`OnFail(Action<Ctx> failAction)`](#id-onfail)|**Fail Action:** Perform an Action if the last operator or production failed. |
59
63
|[`Fail(Action<Ctx> failAction)`](#id-fail)|**Force Fail Action:** Force a failure and perform an Action. |
60
64
|[`Assert(Func<Ctx, bool> assert, Action<Ctx> failAction)`](#id-assert)|**Assert** if a condition is true else performs failAction. |
65
+
|**Inclusion, Forward referencing and Recursion:**||
66
+
|[`Fex(FexElement1, FexElement2, ...)`](#id-fex)|**Include FexElements:** Include a set of previously defined FexElements. |
61
67
|[`RefName(string name), Ref(string refName)`](#id-ref)| Forward Referencing and inclusion.|
62
68
|[`OptSelf()`](#id-optself)| Optional recursive inclusion of the current production sequence within itself. |
63
-
|[`GlobalPreOp(Action<Ctx> preOp)`<br/>`PreOp(Action<T> preOp)`](#id-preop)|**Pre-Operators:**Attach pre-operations to operators.|
69
+
|**Tracing:**|*Debugging aid.*|
64
70
|[`Trace(Func<Ctx, string> traceMessage, int level = 0)`<br/>`TraceOp(Func<Ctx, string> traceMessage, int level = 0)`<br/>`TraceOp(Func<Ctx, object, string> traceMessage, int level)`](#id-trace)| Tracing utilities. |
@@ -257,6 +289,16 @@ Define a set of Sequences, where it fails if any sequence passes (inverse of One
257
289
- If any of the sequences pass then the production fails.
258
290
-`BreakOn(o => o...)` is an alias for NotOneOf that reads better in loops.
259
291
292
+
```mermaid
293
+
graph LR
294
+
subgraph NotOneOf
295
+
subgraph "Not!"
296
+
direction LR
297
+
A[Seq 1] -->|or| B[Seq 2] -.->|or| C[Seq 3];
298
+
end
299
+
end
300
+
```
301
+
260
302
In the example below if any of the steps in the BreakOn sequence passes, then BreakOn/NotOneOf fails and the loop is terminated because it was the first step in the Rep inner-sequence (see Rep rules).
261
303
262
304
```csharp
@@ -290,6 +332,14 @@ For convenience, several Repeat configurations are available:
290
332
-`Rep0N(r => r...) -> Rep(0, -1, r => r...)`
291
333
-`Rep1N(r => r...) -> Rep(1, -1, r => r...)`
292
334
335
+
```mermaid
336
+
graph LR
337
+
subgraph "Rep (min, max)"
338
+
direction LR
339
+
A[Seq];
340
+
end
341
+
```
342
+
293
343
```csharp
294
344
Rep(3, -1, r=>r.Ch('a').Ch('b'));
295
345
Rep(3, 9, r=>r.Ch('a').Ch('b');)
@@ -311,6 +361,14 @@ Repeat a OneOf construct and the following rules apply:
311
361
- repMax = -1: Repeat repMin to N times.Treats the OneOf, after repMin, as an optional (see Opt rules).<br/>
312
362
- repMax > 0: Repeat repMin to repMax times and then terminates the loop.
A Flow expressions implement recursion via Forward Referencing, OptSelf or Fex inclusion.
468
549
469
-
> **Note** Flow Expressions do not support [*Left Recursion*](https://en.wikipedia.org/wiki/Left_recursion) (which will cause an endless loop and possibly a stack overflow)
550
+
> **Note:** Flow Expressions do not support [*Left Recursion*](https://en.wikipedia.org/wiki/Left_recursion) (which will cause an endless loop and possibly a stack overflow)
470
551
471
552
472
-
[`TOC`](#id-toc)
473
-
474
-
---
475
-
<aid="id-preop"></a>
476
-
### Pre-Operators:
477
-
478
-
Pre-operators execute before an Op (operator) as and Action on the context:
479
-
- Typically used to skip spaces, comments and newlines etc. before tokens when parsing scripts.
480
-
- Pre-operators are efficient an only execute once while trying several lookahead operations.
481
-
482
-
<br/>
483
-
484
-
> **`GlobalPreOp(Action<Ctx> preOp)`**
485
-
> - Binds a pre-operator to all subsequent operators.
486
-
487
-
<br/>
488
-
489
-
> **`PreOp(Action<Ctx> preOp)`**
490
-
> - Use directly after an operator to bind a pre-operator to the preceding operator:
491
-
> - The preOp may be null if no PreOp should be executed.
492
-
> - The above mechanism could be used to *switch off* the GlobalPreOp's for selected Op's.
493
-
494
-
See the Expression example which uses a GlobalPreOp to skip all spaces before the *tokens*.
495
-
496
553
[`TOC`](#id-toc)
497
554
498
555
---
@@ -561,7 +618,6 @@ public class ConsoleTracer : IFexTracer
561
618
562
619
**Example usage of the above:**
563
620
```csharp
564
-
565
621
// Enable tracing via an IFexTracer in the FlowExpression constructor.
0 commit comments