Add the directive form of a group (`!group`) v0.10.0
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Mon, 2 Oct 2023 16:02:02 +0000 (12:02 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Mon, 2 Oct 2023 16:04:10 +0000 (12:04 -0400)
This is to add some consistency regarding items which may contain other
items: I want all of them to have an available `!xyz` form.

Normand already has `!if` and `!repeat`, not it has `!group` (and the
alias `!g`).

The following two groups are equivalent:

    (
      aa bb cc
    ) * 5

    !group
      aa bb cc
    !end * 5

Change-Id: I00b2789c078c9b9216ab9b732bc3adeff39b0642
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
22 files changed:
README.adoc
normand/normand.py
pyproject.toml
tests/fail-group-blk-missing-end.nt [new file with mode: 0644]
tests/fail-group-blk-wrong-end.nt [new file with mode: 0644]
tests/fail-group-missing-suffix.nt [deleted file]
tests/fail-group-paren-missing-end.nt [new file with mode: 0644]
tests/fail-group-paren-wrong-end.nt [new file with mode: 0644]
tests/pass-group-blk-g.nt [new file with mode: 0644]
tests/pass-group-blk-label-1.nt [new file with mode: 0644]
tests/pass-group-blk-label-2.nt [new file with mode: 0644]
tests/pass-group-blk-label-3.nt [new file with mode: 0644]
tests/pass-group-blk-no-rep.nt [new file with mode: 0644]
tests/pass-group-label-1.nt [deleted file]
tests/pass-group-label-2.nt [deleted file]
tests/pass-group-label-3.nt [deleted file]
tests/pass-group-no-rep.nt [deleted file]
tests/pass-group-paren-label-1.nt [new file with mode: 0644]
tests/pass-group-paren-label-2.nt [new file with mode: 0644]
tests/pass-group-paren-label-3.nt [new file with mode: 0644]
tests/pass-group-paren-no-rep.nt [new file with mode: 0644]
tests/pass-readme-learn-group-2.nt

index fe99d829db78cf3c2ae475977afc069c50b93356..c865f0faabb9f4c2e90163716a9805e0fb377896 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.9, meaning both the Normand
+WARNING: This version of Normand is 0.10, meaning both the Normand
 language and the module/CLI interface aren't stable.
 
 ifdef::env-github[]
@@ -411,10 +411,10 @@ A Normand comment may exist:
 * Between the last item and the ``pass:[*]`` character of a post-item
   repetition, and between that ``pass:[*]`` character and the following
   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.
+* Between the ``!repeat``/``!r`` block opening and the following
+  constant integer, name, or expression of a repetition block.
+* Between the ``!if`` block opening 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
@@ -998,11 +998,20 @@ than a single item and to isolate labels.
 
 A group is:
 
-. The `(` prefix.
+. The `(`, `!group`, or `!g` opening.
 
 . Zero or more items.
 
-. The `)` suffix.
+. Depending on the group opening:
++
+--
+`(`::
+    The `)` closing.
+
+`!group`::
+`!g`::
+    The `!end` closing.
+--
 
 ====
 Input:
@@ -1022,7 +1031,9 @@ aa bb cc dd ee 6c 65 63  6c 65 72 63  ┆ •••••leclerc
 Input:
 
 ----
-((aa bb cc) * 3 dd ee) * 5
+!group
+  (aa bb cc) * 3 dd ee
+!end * 5
 ----
 
 Output:
@@ -1067,7 +1078,7 @@ if some expression is true, or no bytes at all if it's false.
 
 A conditional block is:
 
-. The `!if` prefix.
+. The `!if` opening.
 
 . One of:
 
@@ -1097,7 +1108,7 @@ For the name `__NAME__`, this is equivalent to the
 
 . Zero or more items.
 
-. The `!end` suffix.
+. The `!end` closing.
 
 ====
 Input:
@@ -1157,7 +1168,7 @@ a given number of times.
 
 A repetition block is:
 
-. The `!repeat` or `!r` prefix.
+. The `!repeat` or `!r` opening.
 
 . One of:
 
@@ -1190,7 +1201,7 @@ For the name `__NAME__`, this is equivalent to the
 
 . Zero or more items.
 
-. The `!end` suffix.
+. The `!end` closing.
 
 You may also use a <<post-item-repetition,post-item repetition>> after
 some items. The form ``!repeat{nbsp}__X__{nbsp}__ITEMS__{nbsp}!end``
index b2f3069f8b8e55aee7f8a608741df75fc56b4660..e2dbe0f3d8d2acd4678f5ddd1534018364865800 100644 (file)
@@ -30,7 +30,7 @@
 # Upstream repository: <https://github.com/efficios/normand>.
 
 __author__ = "Philippe Proulx"
-__version__ = "0.9.0"
+__version__ = "0.10.0"
 __all__ = [
     "ByteOrder",
     "parse",
@@ -665,15 +665,17 @@ class _Parser:
         return _Str(data, begin_text_loc)
 
     # Patterns for _try_parse_group()
-    _group_prefix_pat = re.compile(r"\(")
-    _group_suffix_pat = re.compile(r"\)")
+    _group_prefix_pat = re.compile(r"\(|!g(roup)?\b")
+    _group_suffix_paren_pat = re.compile(r"\)")
 
     # Tries to parse a group, returning a group item on success.
     def _try_parse_group(self):
         begin_text_loc = self._text_loc
 
         # Match prefix
-        if self._try_parse_pat(self._group_prefix_pat) is None:
+        m_open = self._try_parse_pat(self._group_prefix_pat)
+
+        if m_open is None:
             # No match
             return
 
@@ -682,9 +684,15 @@ class _Parser:
 
         # Expect end of group
         self._skip_ws_and_comments()
-        self._expect_pat(
-            self._group_suffix_pat, "Expecting an item or `)` (end of group)"
-        )
+
+        if m_open.group(0) == "(":
+            pat = self._group_suffix_paren_pat
+            exp = ")"
+        else:
+            pat = self._block_end_pat
+            exp = "!end"
+
+        self._expect_pat(pat, "Expecting an item or `{}` (end of group)".format(exp))
 
         # Return item
         return _Group(items, begin_text_loc)
index 2d8f3c3fe6e96c35187e2398c15feec8c6683a5a..737d511abdb12bffd6fabf1098055ba8835a967c 100644 (file)
@@ -23,7 +23,7 @@
 
 [tool.poetry]
 name = 'normand'
-version = '0.9.0'
+version = '0.10.0'
 description = 'Text-to-binary processor with its own language'
 license = 'MIT'
 authors = ['Philippe Proulx <eeppeliteloop@gmail.com>']
diff --git a/tests/fail-group-blk-missing-end.nt b/tests/fail-group-blk-missing-end.nt
new file mode 100644 (file)
index 0000000..3bdc2f8
--- /dev/null
@@ -0,0 +1,3 @@
+!group aa bb cc "yeah"
+---
+2:1 - Expecting an item or `!end` (end of group)
diff --git a/tests/fail-group-blk-wrong-end.nt b/tests/fail-group-blk-wrong-end.nt
new file mode 100644 (file)
index 0000000..c12360a
--- /dev/null
@@ -0,0 +1,3 @@
+!group aa bb cc )
+---
+1:17 - Expecting an item or `!end` (end of group)
diff --git a/tests/fail-group-missing-suffix.nt b/tests/fail-group-missing-suffix.nt
deleted file mode 100644 (file)
index e2eae33..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-( aa bb cc "yeah"
----
-2:1 - Expecting an item or `)` (end of group)
diff --git a/tests/fail-group-paren-missing-end.nt b/tests/fail-group-paren-missing-end.nt
new file mode 100644 (file)
index 0000000..e2eae33
--- /dev/null
@@ -0,0 +1,3 @@
+( aa bb cc "yeah"
+---
+2:1 - Expecting an item or `)` (end of group)
diff --git a/tests/fail-group-paren-wrong-end.nt b/tests/fail-group-paren-wrong-end.nt
new file mode 100644 (file)
index 0000000..bd49980
--- /dev/null
@@ -0,0 +1,3 @@
+( aa bb cc !end
+---
+1:12 - Expecting an item or `)` (end of group)
diff --git a/tests/pass-group-blk-g.nt b/tests/pass-group-blk-g.nt
new file mode 100644 (file)
index 0000000..37fad30
--- /dev/null
@@ -0,0 +1,4 @@
+!g $1 $2 $3 !end * 2
+---
+01 02 03
+01 02 03
diff --git a/tests/pass-group-blk-label-1.nt b/tests/pass-group-blk-label-1.nt
new file mode 100644 (file)
index 0000000..1d83d60
--- /dev/null
@@ -0,0 +1,6 @@
+00 !group 11 <meow> 22 {mix-meow:8} 33 <mix> 44 !end * 2 55
+---
+00
+11 22 03 33 44
+11 22 03 33 44
+55
diff --git a/tests/pass-group-blk-label-2.nt b/tests/pass-group-blk-label-2.nt
new file mode 100644 (file)
index 0000000..2285e9d
--- /dev/null
@@ -0,0 +1,25 @@
+00
+!group
+  11 {mix:8} 22 <mix>
+  !group
+    <meow> {meow + mix : 8}
+  !end * 3
+  33
+!end * 2
+44
+---
+00
+
+11 04 22
+  08
+  09
+  0a
+33
+
+11 0b 22
+  16
+  17
+  18
+33
+
+44
diff --git a/tests/pass-group-blk-label-3.nt b/tests/pass-group-blk-label-3.nt
new file mode 100644 (file)
index 0000000..1f8b421
--- /dev/null
@@ -0,0 +1,11 @@
+00 <outer>
+!group
+  11 <inner> 22 {outer:8} {inner:8} {end:8}
+!end * 3
+<end> ff
+---
+00
+  11 22 01 02 10
+  11 22 01 07 10
+  11 22 01 0c 10
+ff
diff --git a/tests/pass-group-blk-no-rep.nt b/tests/pass-group-blk-no-rep.nt
new file mode 100644 (file)
index 0000000..82881f9
--- /dev/null
@@ -0,0 +1,10 @@
+00
+!group
+  11 22 33
+  !group
+    aa bb cc
+  !end
+!end
+dd
+---
+00 11 22 33 aa bb cc dd
diff --git a/tests/pass-group-label-1.nt b/tests/pass-group-label-1.nt
deleted file mode 100644 (file)
index dbfa2d8..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-00 (11 <meow> 22 {mix-meow:8} 33 <mix> 44) * 2 55
----
-00
-11 22 03 33 44
-11 22 03 33 44
-55
diff --git a/tests/pass-group-label-2.nt b/tests/pass-group-label-2.nt
deleted file mode 100644 (file)
index 7eff18e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-00 (11 {mix:8} 22 <mix> (<meow> {meow + mix : 8}) * 3 33) * 2 44
----
-00
-
-11 04 22
-  08
-  09
-  0a
-33
-
-11 0b 22
-  16
-  17
-  18
-33
-
-44
diff --git a/tests/pass-group-label-3.nt b/tests/pass-group-label-3.nt
deleted file mode 100644 (file)
index 57928b1..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-00 <outer> (11 <inner> 22 {outer:8} {inner:8} {end:8}) * 3 <end> ff
----
-00
-  11 22 01 02 10
-  11 22 01 07 10
-  11 22 01 0c 10
-ff
diff --git a/tests/pass-group-no-rep.nt b/tests/pass-group-no-rep.nt
deleted file mode 100644 (file)
index 1afdc87..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-00 (11 22 33 (aa bb cc)) dd
----
-00 11 22 33 aa bb cc dd
diff --git a/tests/pass-group-paren-label-1.nt b/tests/pass-group-paren-label-1.nt
new file mode 100644 (file)
index 0000000..dbfa2d8
--- /dev/null
@@ -0,0 +1,6 @@
+00 (11 <meow> 22 {mix-meow:8} 33 <mix> 44) * 2 55
+---
+00
+11 22 03 33 44
+11 22 03 33 44
+55
diff --git a/tests/pass-group-paren-label-2.nt b/tests/pass-group-paren-label-2.nt
new file mode 100644 (file)
index 0000000..7eff18e
--- /dev/null
@@ -0,0 +1,17 @@
+00 (11 {mix:8} 22 <mix> (<meow> {meow + mix : 8}) * 3 33) * 2 44
+---
+00
+
+11 04 22
+  08
+  09
+  0a
+33
+
+11 0b 22
+  16
+  17
+  18
+33
+
+44
diff --git a/tests/pass-group-paren-label-3.nt b/tests/pass-group-paren-label-3.nt
new file mode 100644 (file)
index 0000000..57928b1
--- /dev/null
@@ -0,0 +1,7 @@
+00 <outer> (11 <inner> 22 {outer:8} {inner:8} {end:8}) * 3 <end> ff
+---
+00
+  11 22 01 02 10
+  11 22 01 07 10
+  11 22 01 0c 10
+ff
diff --git a/tests/pass-group-paren-no-rep.nt b/tests/pass-group-paren-no-rep.nt
new file mode 100644 (file)
index 0000000..1afdc87
--- /dev/null
@@ -0,0 +1,3 @@
+00 (11 22 33 (aa bb cc)) dd
+---
+00 11 22 33 aa bb cc dd
index 2e37b36881ed2f3f181c9e238bc4fddd5e6fe2c7..cb93612f38b2fa74e3b9bb154960de7d62c84422 100644 (file)
@@ -1,4 +1,6 @@
-((aa bb cc) * 3 dd ee) * 5
+!group
+  (aa bb cc) * 3 dd ee
+!end * 5
 ---
 aa bb cc aa bb cc aa bb cc dd ee aa bb cc aa bb
 cc aa bb cc dd ee aa bb cc aa bb cc aa bb cc dd
This page took 0.031716 seconds and 4 git commands to generate.