aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarshall Lochbaum <mwlochbaum@gmail.com>2021-11-30 22:18:41 -0500
committerMarshall Lochbaum <mwlochbaum@gmail.com>2021-11-30 22:18:41 -0500
commitfca88d6e38968ec300100b0d919ae49df5d810a0 (patch)
tree8014711619d0b02086f8700c9e32fbd5854ef76c
parentda6694e6cb0755d6a232676808ee96cd5c06ef55 (diff)
Update block grammar
-rw-r--r--docs/spec/grammar.html59
-rw-r--r--spec/grammar.md59
2 files changed, 60 insertions, 58 deletions
diff --git a/docs/spec/grammar.html b/docs/spec/grammar.html
index 8c002fb6..66814649 100644
--- a/docs/spec/grammar.html
+++ b/docs/spec/grammar.html
@@ -61,39 +61,40 @@
<span class='Function'>|</span> <span class='Value'>lhs</span> <span class='Function'>ASGN</span> <span class='Value'>subExpr</span>
<span class='Function'>|</span> <span class='Value'>lhs</span> <span class='Function'>Derv</span> <span class='String'>&quot;↩&quot;</span> <span class='Value'>subExpr?</span> <span class='Comment'># Modified assignment
</span></pre>
-<p>A header looks like a name for the thing being headed, or its application to inputs (possibly twice in the case of modifiers). As with assignment, it is restricted to a simple form with no extra parentheses. The full list syntax is allowed for arguments. As a special rule, a monadic function header specifically can omit the function when the argument is not just a name (as this would conflict with a subject label). The following cases define only headers with arguments, which are assumed to be special cases; there can be any number of these. Headers without arguments can only refer to the general caseβ€”note that operands are not pattern matchedβ€”so there can be at most two of these kinds of headers, indicating the monadic and dyadic cases.</p>
+<p>A header looks like a name for the thing being headed, or its application to inputs (possibly twice in the case of modifiers). As with assignment, it is restricted to a simple form with no extra parentheses. The full list syntax is allowed for arguments. A plain name is called a label and can be used for a block with or without arguments. First we define headers <code><span class='Function'>IMM_HEAD</span></code> that include no arguments.</p>
<pre><span class='Value'>headW</span> <span class='Function'>=</span> <span class='Value'>subject</span> <span class='Function'>|</span> <span class='String'>&quot;𝕨&quot;</span>
<span class='Value'>headX</span> <span class='Function'>=</span> <span class='Value'>subject</span> <span class='Function'>|</span> <span class='String'>&quot;𝕩&quot;</span>
<span class='Function'>HeadF</span> <span class='Function'>=</span> <span class='Function'>F</span> <span class='Function'>|</span> <span class='String'>&quot;𝕗&quot;</span> <span class='Function'>|</span> <span class='String'>&quot;𝔽&quot;</span>
<span class='Function'>HeadG</span> <span class='Function'>=</span> <span class='Function'>F</span> <span class='Function'>|</span> <span class='String'>&quot;π•˜&quot;</span> <span class='Function'>|</span> <span class='String'>&quot;𝔾&quot;</span>
-<span class='Function'>Mod1H1</span> <span class='Function'>=</span> <span class='Function'>HeadF</span> <span class='Paren'>(</span> <span class='Modifier'>_m</span> <span class='Function'>|</span> <span class='String'>&quot;_𝕣&quot;</span> <span class='Paren'>)</span>
-<span class='Function'>Mod2H1</span> <span class='Function'>=</span> <span class='Function'>HeadF</span> <span class='Paren'>(</span> <span class='Modifier2'>_c_</span> <span class='Function'>|</span> <span class='String'>&quot;_𝕣_&quot;</span> <span class='Paren'>)</span> <span class='Function'>HeadG</span>
-<span class='Function'>FuncHead</span> <span class='Function'>=</span> <span class='Value'>headW?</span> <span class='Paren'>(</span> <span class='Function'>F</span> <span class='Function'>|</span> <span class='String'>&quot;π•Š&quot;</span> <span class='Paren'>)</span> <span class='Value'>headX</span>
- <span class='Function'>|</span> <span class='Value'>sl</span> <span class='Function'>|</span> <span class='String'>&quot;(&quot;</span> <span class='Value'>subExpr</span> <span class='String'>&quot;)&quot;</span> <span class='Function'>|</span> <span class='Value'>brSub</span> <span class='Function'>|</span> <span class='Value'>list</span> <span class='Comment'># subject,
-</span> <span class='Function'>|</span> <span class='Function'>ANY</span> <span class='Paren'>(</span> <span class='String'>&quot;β€Ώ&quot;</span> <span class='Function'>ANY</span> <span class='Paren'>)</span><span class='Function'>+</span> <span class='Comment'># but not s
-</span> <span class='Function'>|</span> <span class='Function'>UndoHead</span>
-<span class='Modifier'>_m1Head</span> <span class='Function'>=</span> <span class='Value'>headW?</span> <span class='Function'>Mod1H1</span> <span class='Value'>headX</span>
-<span class='Modifier2'>_m2Head_</span> <span class='Function'>=</span> <span class='Value'>headW?</span> <span class='Function'>Mod2H1</span> <span class='Value'>headX</span>
-</pre>
-<p>Additionally, an inference header doesn't affect evaluation of the function, but describes how an inferred property (<a href="inferred.html#undo">Undo</a>) should be computed. Here <code><span class='String'>&quot;˜&quot;</span></code> and <code><span class='String'>&quot;⁼&quot;</span></code> are both specific instances of the <code><span class='Modifier'>_ml</span></code> token.</p>
-<pre><span class='Function'>UndoHead</span> <span class='Function'>=</span> <span class='Value'>headW?</span> <span class='Paren'>(</span> <span class='Function'>F</span> <span class='Function'>|</span> <span class='String'>&quot;π•Š&quot;</span> <span class='Paren'>)</span> <span class='String'>&quot;⁼&quot;</span> <span class='Value'>headX</span>
- <span class='Function'>|</span> <span class='Value'>headW</span> <span class='Paren'>(</span> <span class='Function'>F</span> <span class='Function'>|</span> <span class='String'>&quot;π•Š&quot;</span> <span class='Paren'>)</span> <span class='String'>&quot;˜&quot;</span> <span class='String'>&quot;⁼&quot;</span> <span class='Value'>headX</span>
- <span class='Function'>|</span> <span class='Paren'>(</span> <span class='Function'>F</span> <span class='Function'>|</span> <span class='String'>&quot;π•Š&quot;</span> <span class='Paren'>)</span> <span class='String'>&quot;˜&quot;</span><span class='Value'>?</span> <span class='String'>&quot;⁼&quot;</span>
+<span class='Function'>FuncLab</span> <span class='Function'>=</span> <span class='Function'>F</span> <span class='Function'>|</span> <span class='String'>&quot;π•Š&quot;</span>
+<span class='Function'>Mod1Lab</span> <span class='Function'>=</span> <span class='Modifier'>_m</span> <span class='Function'>|</span> <span class='String'>&quot;_𝕣&quot;</span>
+<span class='Function'>Mod2Lab</span> <span class='Function'>=</span> <span class='Modifier2'>_c_</span> <span class='Function'>|</span> <span class='String'>&quot;_𝕣_&quot;</span>
+<span class='Function'>FuncName</span> <span class='Function'>=</span> <span class='Function'>FuncLab</span>
+<span class='Function'>Mod1Name</span> <span class='Function'>=</span> <span class='Function'>HeadF</span> <span class='Function'>Mod1Lab</span>
+<span class='Function'>Mod2Name</span> <span class='Function'>=</span> <span class='Function'>HeadF</span> <span class='Function'>Mod2Lab</span> <span class='Function'>HeadG</span>
+<span class='Function'>LABEL</span> <span class='Function'>=</span> <span class='Function'>FuncLab</span> <span class='Function'>|</span> <span class='Function'>Mod1Lab</span> <span class='Function'>|</span> <span class='Function'>Mod2Lab</span>
+<span class='Function'>IMM_HEAD</span> <span class='Function'>=</span> <span class='Function'>LABEL</span> <span class='Function'>|</span> <span class='Function'>FuncName</span> <span class='Function'>|</span> <span class='Function'>Mod1Name</span> <span class='Function'>|</span> <span class='Function'>Mod2Name</span>
</pre>
-<p>A braced block contains bodies, which are lists of statements, separated by semicolons and possibly preceded by headers, which are separated from the body with a colon. A non-final expression can be made into a predicate by following it with the separator-like <code><span class='Value'>?</span></code>. Multiple bodies allow different handling for various cases, which are pattern-matched by headers. For an immediate block there are no inputs, so there can only be one possible case and one body. Functions and modifiers allow any number of &quot;matched&quot; bodies, with headers that have arguments, followed by at most two &quot;main&quot; bodies with either no headers or headers without arguments. If there is one main body, it is ambivalent, but two main bodies refer to the monadic and dyadic cases.</p>
+<p>There are some extra possibilities for a header that specifies arguments. As a special rule, a monadic function header specifically can omit the function when the argument is not just a name (as this would conflict with a subject label). Additionally, an inference header doesn't affect evaluation of the function, but describes how an inferred property (<a href="inferred.html#undo">Undo</a>) should be computed. Here <code><span class='String'>&quot;˜&quot;</span></code> and <code><span class='String'>&quot;⁼&quot;</span></code> are both specific instances of the <code><span class='Modifier'>_ml</span></code> token.</p>
+<pre><span class='Function'>ARG_HEAD</span> <span class='Function'>=</span> <span class='Function'>LABEL</span>
+ <span class='Function'>|</span> <span class='Value'>headW?</span> <span class='Function'>IMM_HEAD</span> <span class='String'>&quot;⁼&quot;</span><span class='Value'>?</span> <span class='Value'>headX</span>
+ <span class='Function'>|</span> <span class='Value'>headW</span> <span class='Function'>IMM_HEAD</span> <span class='String'>&quot;˜&quot;</span> <span class='String'>&quot;⁼&quot;</span> <span class='Value'>headX</span>
+ <span class='Function'>|</span> <span class='Function'>FuncName</span> <span class='String'>&quot;˜&quot;</span><span class='Value'>?</span> <span class='String'>&quot;⁼&quot;</span>
+ <span class='Function'>|</span> <span class='Function'>CaseHead</span>
+<span class='Function'>CaseHead</span> <span class='Function'>=</span> <span class='Value'>sl</span> <span class='Function'>|</span> <span class='String'>&quot;(&quot;</span> <span class='Value'>subExpr</span> <span class='String'>&quot;)&quot;</span> <span class='Function'>|</span> <span class='Value'>brSub</span> <span class='Function'>|</span> <span class='Value'>list</span> <span class='Comment'># subject,
+</span> <span class='Function'>|</span> <span class='Function'>ANY</span> <span class='Paren'>(</span> <span class='String'>&quot;β€Ώ&quot;</span> <span class='Function'>ANY</span> <span class='Paren'>)</span><span class='Function'>+</span> <span class='Comment'># but not s
+</span></pre>
+<p>A braced block contains bodies, which are lists of statements, separated by semicolons and possibly preceded by headers, which are separated from the body with a colon. A non-final expression can be made into a predicate by following it with the separator-like <code><span class='Value'>?</span></code>. Multiple bodies allow different handling for various cases, which are pattern-matched by headers. A block can have any number of bodies with headers. After these there can be bodies without headersβ€”up to one for an immediate block and up to two for a block with arguments. If a block with arguments has one such body, it's ambivalent, but two of them refer to the monadic and dyadic cases.</p>
<pre><span class='Function'>BODY</span> <span class='Function'>=</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='Paren'>(</span> <span class='Function'>STMT</span> <span class='Separator'>β‹„</span> <span class='Function'>|</span> <span class='Function'>EXPR</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='String'>&quot;?&quot;</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='Paren'>)</span><span class='Value'>*</span> <span class='Function'>STMT</span> <span class='Separator'>β‹„</span><span class='Value'>?</span>
-<span class='Function'>FCase</span> <span class='Function'>=</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='Function'>FuncHead</span> <span class='String'>&quot;:&quot;</span> <span class='Function'>BODY</span>
-<span class='Modifier'>_mCase</span> <span class='Function'>=</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='Modifier'>_m1Head</span> <span class='String'>&quot;:&quot;</span> <span class='Function'>BODY</span>
-<span class='Modifier2'>_cCase_</span> <span class='Function'>=</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='Modifier2'>_m2Head_</span> <span class='String'>&quot;:&quot;</span> <span class='Function'>BODY</span>
-<span class='Function'>FMain</span> <span class='Function'>=</span> <span class='Paren'>(</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='Paren'>(</span> <span class='Function'>F</span> <span class='Function'>|</span> <span class='String'>&quot;π•Š&quot;</span> <span class='Paren'>)</span> <span class='String'>&quot;:&quot;</span> <span class='Paren'>)</span><span class='Value'>?</span> <span class='Function'>BODY</span>
-<span class='Modifier'>_mMain</span> <span class='Function'>=</span> <span class='Paren'>(</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='Paren'>(</span> <span class='Modifier'>_m</span> <span class='Function'>|</span> <span class='String'>&quot;_𝕣&quot;</span> <span class='Function'>|</span> <span class='Function'>Mod1H1</span> <span class='Paren'>)</span> <span class='String'>&quot;:&quot;</span> <span class='Paren'>)</span><span class='Value'>?</span> <span class='Function'>BODY</span>
-<span class='Modifier2'>_cMain_</span> <span class='Function'>=</span> <span class='Paren'>(</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='Paren'>(</span> <span class='Modifier2'>_c_</span> <span class='Function'>|</span> <span class='String'>&quot;_𝕣_&quot;</span> <span class='Function'>|</span> <span class='Function'>Mod2H1</span> <span class='Paren'>)</span> <span class='String'>&quot;:&quot;</span> <span class='Paren'>)</span><span class='Value'>?</span> <span class='Function'>BODY</span>
+<span class='Function'>IMM_BLK</span> <span class='Function'>=</span> <span class='String'>&quot;{&quot;</span> <span class='Paren'>(</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='Function'>IMM_HEAD</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='String'>&quot;:&quot;</span> <span class='Function'>BODY</span> <span class='String'>&quot;;&quot;</span> <span class='Paren'>)</span><span class='Value'>*</span> <span class='Function'>BODY</span><span class='Value'>?</span> <span class='String'>&quot;}&quot;</span>
+<span class='Function'>ARG_BLK</span> <span class='Function'>=</span> <span class='String'>&quot;{&quot;</span> <span class='Paren'>(</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='Function'>ARG_HEAD</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='String'>&quot;:&quot;</span> <span class='Function'>BODY</span> <span class='String'>&quot;;&quot;</span> <span class='Paren'>)</span><span class='Value'>*</span> <span class='Paren'>(</span> <span class='Function'>BODY</span> <span class='Paren'>(</span> <span class='String'>&quot;;&quot;</span> <span class='Function'>BODY</span> <span class='Paren'>)</span><span class='Value'>?</span> <span class='Paren'>)</span><span class='Value'>?</span> <span class='String'>&quot;}&quot;</span>
+<span class='Function'>BLOCK</span> <span class='Function'>=</span> <span class='Function'>IMM_BLOCK</span> <span class='Function'>|</span> <span class='Function'>ARG_BLOCK</span>
<span class='Value'>brSub</span> <span class='Function'>=</span> <span class='String'>&quot;{&quot;</span> <span class='Paren'>(</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='Value'>s</span> <span class='String'>&quot;:&quot;</span> <span class='Paren'>)</span><span class='Value'>?</span> <span class='Function'>BODY</span> <span class='String'>&quot;}&quot;</span>
-<span class='Function'>BrFunc</span> <span class='Function'>=</span> <span class='String'>&quot;{&quot;</span> <span class='Paren'>(</span> <span class='Function'>FCase</span> <span class='String'>&quot;;&quot;</span> <span class='Paren'>)</span><span class='Value'>*</span> <span class='Paren'>(</span> <span class='Function'>FCase</span> <span class='Function'>|</span> <span class='Function'>FMain</span> <span class='Paren'>(</span> <span class='String'>&quot;;&quot;</span> <span class='Function'>FMain</span> <span class='Paren'>)</span><span class='Value'>?</span> <span class='Paren'>)</span> <span class='String'>&quot;}&quot;</span>
-<span class='Modifier'>_brMod1</span> <span class='Function'>=</span> <span class='String'>&quot;{&quot;</span> <span class='Paren'>(</span> <span class='Modifier'>_mCase</span> <span class='String'>&quot;;&quot;</span> <span class='Paren'>)</span><span class='Value'>*</span> <span class='Paren'>(</span> <span class='Modifier'>_mCase</span> <span class='Function'>|</span> <span class='Modifier'>_mMain</span> <span class='Paren'>(</span> <span class='String'>&quot;;&quot;</span> <span class='Modifier'>_mMain</span> <span class='Paren'>)</span><span class='Value'>?</span> <span class='Paren'>)</span> <span class='String'>&quot;}&quot;</span>
-<span class='Modifier2'>_brMod2_</span> <span class='Function'>=</span> <span class='String'>&quot;{&quot;</span> <span class='Paren'>(</span> <span class='Modifier2'>_cCase_</span> <span class='String'>&quot;;&quot;</span> <span class='Paren'>)</span><span class='Value'>*</span> <span class='Paren'>(</span> <span class='Modifier2'>_cCase_</span> <span class='Function'>|</span> <span class='Modifier2'>_cMan_</span> <span class='Paren'>(</span> <span class='String'>&quot;;&quot;</span> <span class='Modifier2'>_cMan_</span> <span class='Paren'>)</span><span class='Value'>?</span> <span class='Paren'>)</span> <span class='String'>&quot;}&quot;</span>
+<span class='Function'>BrFunc</span> <span class='Function'>=</span> <span class='Function'>BLOCK</span>
+<span class='Modifier'>_brMod1</span> <span class='Function'>=</span> <span class='Function'>BLOCK</span>
+<span class='Modifier2'>_brMod2_</span> <span class='Function'>=</span> <span class='Function'>BLOCK</span>
</pre>
-<p>Two additional rules apply to blocks, based on the special name associations in the table below. First, each block allows the special names in its column to be used as the given token types within <code><span class='Function'>BODY</span></code> terms (not headers). Except for the spaces labelled &quot;None&quot;, each column is cumulative and a given entry also includes all the entries above it. Second, for <code><span class='Function'>BrFunc</span></code>, <code><span class='Modifier'>_brMod1</span></code>, and <code><span class='Modifier2'>_brMod2_</span></code> terms, if no header is given, then at least one <code><span class='Function'>BODY</span></code> term in it <em>must</em> contain one of the names on, and not above, the corresponding row. Otherwise the syntax would be ambiguous, since for example a simple <code><span class='String'>&quot;{&quot;</span> <span class='Function'>BODY</span> <span class='String'>&quot;}&quot;</span></code> sequence could have any type.</p>
+<p>Three additional rules apply to blocks, allowing the ambiguous grammar above to be disambiguated. They are shown in the table below. First, each block type allows the special names in its row to be used as the given token types within <code><span class='Function'>BODY</span></code> terms (not headers). Except for the spaces labelled &quot;None&quot;, each of these four columns is cumulative, so that a given entry also includes all the entries above it. Second, a block can't contain one of the tokens from the &quot;label&quot; column of a different row. Third, each <code><span class='Function'>BrFunc</span></code>, <code><span class='Modifier'>_brMod1</span></code>, and <code><span class='Modifier2'>_brMod2_</span></code> term <em>must</em> contain one of the names on, and not above, the corresponding row (including the &quot;label&quot; column).</p>
<table>
<thead>
<tr>
@@ -102,7 +103,7 @@
<th><code><span class='Function'>F</span></code></th>
<th><code><span class='Modifier'>_m</span></code></th>
<th><code><span class='Modifier2'>_c_</span></code></th>
-<th>other</th>
+<th>label</th>
</tr>
</thead>
<tbody>
@@ -120,7 +121,7 @@
<td><code><span class='Function'>π•Žπ•π•Š</span></code></td>
<td></td>
<td></td>
-<td><code><span class='String'>&quot;;&quot;</span></code></td>
+<td><code><span class='Function'>FuncLab</span></code></td>
</tr>
<tr>
<td><code><span class='Modifier'>_brMod1</span></code></td>
@@ -128,7 +129,7 @@
<td><code><span class='Function'>𝔽</span></code></td>
<td><code><span class='Modifier'>_𝕣</span></code></td>
<td></td>
-<td></td>
+<td><code><span class='Function'>Mod1Lab</span></code></td>
</tr>
<tr>
<td><code><span class='Modifier2'>_brMod2_</span></code></td>
@@ -136,7 +137,7 @@
<td><code><span class='Function'>𝔾</span></code></td>
<td>None</td>
<td><code><span class='Modifier2'>_𝕣_</span></code></td>
-<td></td>
+<td><code><span class='Function'>Mod2Lab</span></code></td>
</tr>
</tbody>
</table>
diff --git a/spec/grammar.md b/spec/grammar.md
index dfe7f9c2..5167dac9 100644
--- a/spec/grammar.md
+++ b/spec/grammar.md
@@ -65,49 +65,50 @@ Subject expressions are complicated by the possibility of list and namespace ass
| lhs ASGN subExpr
| lhs Derv "↩" subExpr? # Modified assignment
-A header looks like a name for the thing being headed, or its application to inputs (possibly twice in the case of modifiers). As with assignment, it is restricted to a simple form with no extra parentheses. The full list syntax is allowed for arguments. As a special rule, a monadic function header specifically can omit the function when the argument is not just a name (as this would conflict with a subject label). The following cases define only headers with arguments, which are assumed to be special cases; there can be any number of these. Headers without arguments can only refer to the general caseβ€”note that operands are not pattern matchedβ€”so there can be at most two of these kinds of headers, indicating the monadic and dyadic cases.
+A header looks like a name for the thing being headed, or its application to inputs (possibly twice in the case of modifiers). As with assignment, it is restricted to a simple form with no extra parentheses. The full list syntax is allowed for arguments. A plain name is called a label and can be used for a block with or without arguments. First we define headers `IMM_HEAD` that include no arguments.
headW = subject | "𝕨"
headX = subject | "𝕩"
HeadF = F | "𝕗" | "𝔽"
HeadG = F | "π•˜" | "𝔾"
- Mod1H1 = HeadF ( _m | "_𝕣" )
- Mod2H1 = HeadF ( _c_ | "_𝕣_" ) HeadG
- FuncHead = headW? ( F | "π•Š" ) headX
- | sl | "(" subExpr ")" | brSub | list # subject,
+ FuncLab = F | "π•Š"
+ Mod1Lab = _m | "_𝕣"
+ Mod2Lab = _c_ | "_𝕣_"
+ FuncName = FuncLab
+ Mod1Name = HeadF Mod1Lab
+ Mod2Name = HeadF Mod2Lab HeadG
+ LABEL = FuncLab | Mod1Lab | Mod2Lab
+ IMM_HEAD = LABEL | FuncName | Mod1Name | Mod2Name
+
+There are some extra possibilities for a header that specifies arguments. As a special rule, a monadic function header specifically can omit the function when the argument is not just a name (as this would conflict with a subject label). Additionally, an inference header doesn't affect evaluation of the function, but describes how an inferred property ([Undo](inferred.md#undo)) should be computed. Here `"˜"` and `"⁼"` are both specific instances of the `_ml` token.
+
+ ARG_HEAD = LABEL
+ | headW? IMM_HEAD "⁼"? headX
+ | headW IMM_HEAD "˜" "⁼" headX
+ | FuncName "˜"? "⁼"
+ | CaseHead
+ CaseHead = sl | "(" subExpr ")" | brSub | list # subject,
| ANY ( "β€Ώ" ANY )+ # but not s
- | UndoHead
- _m1Head = headW? Mod1H1 headX
- _m2Head_ = headW? Mod2H1 headX
-Additionally, an inference header doesn't affect evaluation of the function, but describes how an inferred property ([Undo](inferred.md#undo)) should be computed. Here `"˜"` and `"⁼"` are both specific instances of the `_ml` token.
-
- UndoHead = headW? ( F | "π•Š" ) "⁼" headX
- | headW ( F | "π•Š" ) "˜" "⁼" headX
- | ( F | "π•Š" ) "˜"? "⁼"
-
-A braced block contains bodies, which are lists of statements, separated by semicolons and possibly preceded by headers, which are separated from the body with a colon. A non-final expression can be made into a predicate by following it with the separator-like `?`. Multiple bodies allow different handling for various cases, which are pattern-matched by headers. For an immediate block there are no inputs, so there can only be one possible case and one body. Functions and modifiers allow any number of "matched" bodies, with headers that have arguments, followed by at most two "main" bodies with either no headers or headers without arguments. If there is one main body, it is ambivalent, but two main bodies refer to the monadic and dyadic cases.
+A braced block contains bodies, which are lists of statements, separated by semicolons and possibly preceded by headers, which are separated from the body with a colon. A non-final expression can be made into a predicate by following it with the separator-like `?`. Multiple bodies allow different handling for various cases, which are pattern-matched by headers. A block can have any number of bodies with headers. After these there can be bodies without headersβ€”up to one for an immediate block and up to two for a block with arguments. If a block with arguments has one such body, it's ambivalent, but two of them refer to the monadic and dyadic cases.
BODY = β‹„? ( STMT β‹„ | EXPR β‹„? "?" β‹„? )* STMT β‹„?
- FCase = β‹„? FuncHead ":" BODY
- _mCase = β‹„? _m1Head ":" BODY
- _cCase_ = β‹„? _m2Head_ ":" BODY
- FMain = ( β‹„? ( F | "π•Š" ) ":" )? BODY
- _mMain = ( β‹„? ( _m | "_𝕣" | Mod1H1 ) ":" )? BODY
- _cMain_ = ( β‹„? ( _c_ | "_𝕣_" | Mod2H1 ) ":" )? BODY
+ IMM_BLK = "{" ( β‹„? IMM_HEAD β‹„? ":" BODY ";" )* BODY? "}"
+ ARG_BLK = "{" ( β‹„? ARG_HEAD β‹„? ":" BODY ";" )* ( BODY ( ";" BODY )? )? "}"
+ BLOCK = IMM_BLOCK | ARG_BLOCK
brSub = "{" ( β‹„? s ":" )? BODY "}"
- BrFunc = "{" ( FCase ";" )* ( FCase | FMain ( ";" FMain )? ) "}"
- _brMod1 = "{" ( _mCase ";" )* ( _mCase | _mMain ( ";" _mMain )? ) "}"
- _brMod2_ = "{" ( _cCase_ ";" )* ( _cCase_ | _cMan_ ( ";" _cMan_ )? ) "}"
+ BrFunc = BLOCK
+ _brMod1 = BLOCK
+ _brMod2_ = BLOCK
-Two additional rules apply to blocks, based on the special name associations in the table below. First, each block allows the special names in its column to be used as the given token types within `BODY` terms (not headers). Except for the spaces labelled "None", each column is cumulative and a given entry also includes all the entries above it. Second, for `BrFunc`, `_brMod1`, and `_brMod2_` terms, if no header is given, then at least one `BODY` term in it *must* contain one of the names on, and not above, the corresponding row. Otherwise the syntax would be ambiguous, since for example a simple `"{" BODY "}"` sequence could have any type.
+Three additional rules apply to blocks, allowing the ambiguous grammar above to be disambiguated. They are shown in the table below. First, each block type allows the special names in its row to be used as the given token types within `BODY` terms (not headers). Except for the spaces labelled "None", each of these four columns is cumulative, so that a given entry also includes all the entries above it. Second, a block can't contain one of the tokens from the "label" column of a different row. Third, each `BrFunc`, `_brMod1`, and `_brMod2_` term *must* contain one of the names on, and not above, the corresponding row (including the "label" column).
-| Term | `s` | `F` | `_m` | `_c_` | other
+| Term | `s` | `F` | `_m` | `_c_` | label
|--------------------|--------|--------|---------|----------|-------
| `brSub`, `PROGRAM` | None | None | None | None | None
-| `BrFunc` | `𝕨𝕩𝕀` | `π•Žπ•π•Š` | | | `";"`
-| `_brMod1` | `𝕗𝕣` | `𝔽` | `_𝕣` | |
-| `_brMod2_` | `π•˜` | `𝔾` | None | `_𝕣_` |
+| `BrFunc` | `𝕨𝕩𝕀` | `π•Žπ•π•Š` | | | `FuncLab`
+| `_brMod1` | `𝕗𝕣` | `𝔽` | `_𝕣` | | `Mod1Lab`
+| `_brMod2_` | `π•˜` | `𝔾` | None | `_𝕣_` | `Mod2Lab`
The rules for special name can be expressed in BNF by making many copies of all expression rules above. For each "level", or row in the table, a new version of every rule should be made that allows that level but not higher ones, and another version should be made that requires exactly that level. The values themselves should be included in `s`, `F`, `_m`, and `_c_` for these copies. Then the "allowed" rules are made simply by replacing the terms they contain (excluding `brSub` and so on) with the same "allowed" versions, and "required" rules are constructed using both "allowed" and "required" rules. For every part of a production rule, an alternative should be created that requires the relevant name in that part while allowing it in the others. For example, `( subject | nothing )? Derv arg` would be transformed to