Add conditional block support
[normand.git] / README.adoc
index f0852d140d8067831406377f96d932fa15fa8381..fe99d829db78cf3c2ae475977afc069c50b93356 100644 (file)
@@ -29,7 +29,7 @@ _**Normand**_ is a text-to-binary processor with its own language.
 This package offers both a portable {py3} module and a command-line
 tool.
 
-WARNING: This version of Normand is 0.8, meaning both the Normand
+WARNING: This version of Normand is 0.9, meaning both the Normand
 language and the module/CLI interface aren't stable.
 
 ifdef::env-github[]
@@ -172,6 +172,29 @@ aa bb cc b7 70 dd ee ff e3 07
 The encoded integer is the evaluation of a valid {py3} expression which
 may include label and variable names.
 
+Conditional::
++
+Input:
++
+----
+aa bb cc
+
+(
+  "foo"
+
+  !if {ICITTE > 10}
+    "bar"
+  !end
+) * 4
+----
++
+Output:
++
+----
+aa bb cc 66 6f 6f 66 6f  6f 66 6f 6f 62 61 72 66  ┆ •••foofoofoobarf
+6f 6f 62 61 72                                    ┆ oobar
+----
+
 Repetition::
 +
 Input:
@@ -304,8 +327,11 @@ current state:
 |
 The current offset has an effect on the value of <<label,labels>> and of
 the special `ICITTE` name in <<fixed-length-number,fixed-length
-number>>, <<leb-128-integer,LEB128 integer>>, and
-<<variable-assignment,variable assignment>> expression evaluation.
+number>>, <<leb-128-integer,LEB128 integer>>,
+<<variable-assignment,variable assignment>>,
+<<conditional-block,conditional block>>, <<repetition-block,repetition
+block>>, and <<post-item-repetition,post-item repetition>> expression
+evaluation.
 
 Each generated byte increments the current offset.
 
@@ -333,7 +359,7 @@ the current byte order.
 |One or more `--label` options.
 
 |<<variable-assignment,Variables>>
-|Mapping of variable names to integral values.
+|Mapping of variable names to integral or floating point number values.
 |`init_variables` parameter of the `parse()` function.
 |One or more `--var` options.
 |===
@@ -369,6 +395,8 @@ This is similar to an assembly label.
 
 * A <<group,group>>, that is, a scoped sequence of items.
 
+* A <<conditional-block,conditional block>>.
+
 * A <<repetition-block,repetition block>>.
 
 Moreover, you can repeat many items above a constant or variable number
@@ -385,6 +413,8 @@ A Normand comment may exist:
   number or expression.
 * Between the ``!repeat``/``!r`` prefix and the following constant
   integer, name, or expression of a repetition block.
+* Between the ``!if`` prefix and the following name or expression of a
+  conditional block.
 
 A comment is anything between two ``pass:[#]`` characters on the same
 line, or from ``pass:[#]`` until the end of the line. Whitespaces and
@@ -629,8 +659,10 @@ is the <<cur-offset,current offset>> (before encoding the number).
 . An encoding length in bits amongst:
 +
 --
-The expression evaluates to an `int` value::
+The expression evaluates to an `int` or `bool` value::
     `8`, `16`, `24`, `32`, `40`, `48`, `56`, and `64`.
++
+NOTE: Normand automatically converts a `bool` value to `int`.
 
 The expression evaluates to a `float` value::
     `32` and `64`.
@@ -715,7 +747,8 @@ An LEB128 integer is:
 
 . The ``pass:[{]`` prefix.
 
-. A valid {py3} expression.
+. A valid {py3} expression of which the evaluation result type
+  is `int` or `bool` (automatically converted to `int`).
 +
 For an LEB128 integer at some source location{nbsp}__**L**__, this
 expression may contain:
@@ -907,9 +940,7 @@ A label is:
 
 . The `<` prefix.
 
-. A valid {py3} name which is not `ICITTE` (see
-  <<fixed-length-number>>, <<leb128-integer>>, and
-  <<variable-assignment>> to learn more).
+. A valid {py3} name which is not `ICITTE`.
 
 . The `>` suffix.
 
@@ -922,13 +953,12 @@ A variable assignment is:
 
 . The ``pass:[{]`` prefix.
 
-. A valid {py3} name which is not `ICITTE` (see
-  <<fixed-length-number>>, <<leb128-integer>>, and
-  <<variable-assignment>> to learn more).
+. A valid {py3} name which is not `ICITTE`.
 
 . The `=` character.
 
-. A valid {py3} expression.
+. A valid {py3} expression of which the evaluation result type
+  is `int`, `float`, or `bool` (automatically converted to `int`).
 +
 For a variable assignment at some source location{nbsp}__**L**__, this
 expression may contain the name of any accessible <<label,label>> (not
@@ -1030,6 +1060,96 @@ Output:
 ----
 ====
 
+=== Conditional block
+
+A _conditional block_ represents either the bytes of one or more items
+if some expression is true, or no bytes at all if it's false.
+
+A conditional block is:
+
+. The `!if` prefix.
+
+. One of:
+
+** The ``pass:[{]`` prefix, a valid {py3} expression of which the
+   evaluation result type is `int` or `bool` (automatically converted to
+   `int`), and the ``pass:[}]`` suffix.
++
+For a repetition at some source location{nbsp}__**L**__, this expression
+may contain:
++
+--
+* The name of any <<label,label>> defined before{nbsp}__**L**__
+  which isn't within a nested group.
+* The name of any <<variable-assignment,variable>> known
+  at{nbsp}__**L**__ which doesn't, directly or indirectly, refer to a
+  label defined after{nbsp}__**L**__.
+--
++
+The value of the special name `ICITTE` (`int` type) in this expression
+is the <<cur-offset,current offset>> (before handling the contained
+items).
+
+** A valid {py3} name.
++
+For the name `__NAME__`, this is equivalent to the
+`pass:[{]__NAME__pass:[}]` form above.
+
+. Zero or more items.
+
+. The `!end` suffix.
+
+====
+Input:
+
+----
+{at = 1}
+{rep_count = 9}
+
+!repeat rep_count
+  "meow "
+
+  !if {ICITTE > 25}
+    "mix"
+
+    !if {at < rep_count} 20 !end
+  !end
+
+  {at = at + 1}
+!end
+----
+
+Output:
+
+----
+6d 65 6f 77 20 6d 65 6f  77 20 6d 65 6f 77 20 6d  ┆ meow meow meow m
+65 6f 77 20 6d 65 6f 77  20 6d 65 6f 77 20 6d 69  ┆ eow meow meow mi
+78 20 6d 65 6f 77 20 6d  69 78 20 6d 65 6f 77 20  ┆ x meow mix meow
+6d 69 78 20 6d 65 6f 77  20 6d 69 78              ┆ mix meow mix
+----
+====
+
+====
+Input:
+
+----
+<str_beg>
+u16le"meow mix!"
+<str_end>
+
+!if {str_end - str_beg > 10}
+  " BIG"
+!end
+----
+
+Output:
+
+----
+6d 00 65 00 6f 00 77 00  20 00 6d 00 69 00 78 00  ┆ m•e•o•w• •m•i•x•
+21 00 20 42 49 47                                 ┆ !• BIG
+----
+====
+
 === Repetition block
 
 A _repetition block_ represents the bytes of one or more items repeated
@@ -1044,14 +1164,16 @@ A repetition block is:
 ** A positive integer (hexadecimal starting with `0x` or `0X` accepted)
    which is the number of times to repeat the previous item.
 
-** The ``pass:[{]`` prefix, a valid {py3} expression, and the
-   ``pass:[}]`` suffix.
+** The ``pass:[{]`` prefix, a valid {py3} expression of which the
+   evaluation result type is `int` or `bool` (automatically converted to
+   `int`), and the ``pass:[}]`` suffix.
 +
 For a repetition at some source location{nbsp}__**L**__, this expression
 may contain:
 +
 --
-* The name of any <<label,label>> defined before{nbsp}__**L**__.
+* The name of any <<label,label>> defined before{nbsp}__**L**__
+  which isn't within a nested group.
 * The name of any <<variable-assignment,variable>> known
   at{nbsp}__**L**__ which doesn't, directly or indirectly, refer to a
   label defined after{nbsp}__**L**__.
@@ -1148,36 +1270,6 @@ ff ee ff ee ff ee ff ee  ff ee ff ee ff 11 22 33  ┆ ••••••••
 ----
 ====
 
-====
-This example shows how to use a repetition block as a conditional
-section depending on some predefined variable.
-
-Input:
-
-----
-aa bb cc dd
-
-!repeat cond
-  ee ff "meow mix" 00
-!end
-
-{be} {-1993:16}
-----
-
-Output (`cond` is 0):
-
-----
-aa bb cc dd f8 37
-----
-
-Output (`cond` is 1):
-
-----
-aa bb cc dd ee ff 6d 65  6f 77 20 6d 69 78 00 f8  ┆ ••••••meow mix••
-37                                                ┆ 7
-----
-====
-
 === Post-item repetition
 
 A _post-item repetition_ represents the bytes of an item repeated a
@@ -1185,14 +1277,13 @@ given number of times.
 
 A post-item repetition is:
 
-. Any item except:
+. One of those items:
 
-** A <<current-byte-order-setting,current byte order setting>>.
-** A <<current-offset-setting,current offset setting>>.
-** A <<label,label>>.
-** A <<offset-alignment,offset alignment>>.
-** A <<variable-assignment,variable assignment>>.
-** A <<repetition-block,repetition block>>.
+** A <<byte-constant,byte constant>>.
+** A <<literal-string,literal string>>.
+** A <<fixed-length-number,fixed-length number>>.
+** An <<leb128-integer,LEB128 integer>>.
+** A <<group,group>>.
 
 . The ``pass:[*]`` character.
 
@@ -1201,15 +1292,17 @@ A post-item repetition is:
 ** A positive integer (hexadecimal starting with `0x` or `0X` accepted)
    which is the number of times to repeat the previous item.
 
-** The ``pass:[{]`` prefix, a valid {py3} expression, and the
-   ``pass:[}]`` suffix.
+** The ``pass:[{]`` prefix, a valid {py3} expression of which the
+   evaluation result type is `int` or `bool` (automatically converted to
+   `int`), and the ``pass:[}]`` suffix.
 +
 For a repetition at some source location{nbsp}__**L**__, this expression
 may contain:
 +
 --
-* The name of any <<label,label>> defined before{nbsp}__**L**__ and
-  which isn't part of its repeated item.
+* The name of any <<label,label>> defined before{nbsp}__**L**__
+  which isn't within a nested group and
+  which isn't part of the repeated item.
 * The name of any <<variable-assignment,variable>> known
   at{nbsp}__**L**__, which isn't part of its repeated item, and which
   doesn't, directly or indirectly, refer to a label defined
This page took 0.026114 seconds and 4 git commands to generate.