This package offers both a portable {py3} module and a command-line
tool.
-WARNING: This version of Normand is 0.15, meaning both the Normand
+WARNING: This version of Normand is 0.16, meaning both the Normand
language and the module/CLI interface aren't stable.
ifdef::env-github[]
The available items are:
-* A <<byte-constant,constant integer>> representing a single byte.
+* A <<byte-constant,constant integer>> representing one or more
+ constant bytes.
* A <<literal-string,literal string>> representing a sequence of bytes
encoding UTF-8, UTF-16, or UTF-32 data.
=== Byte constant
-A _byte constant_ represents a single byte.
+A _byte constant_ represents one or more constant bytes.
A byte constant is:
Hexadecimal form::
- Two consecutive hexadecimal digits.
+ Two consecutive hexadecimal digits representing a single byte.
Decimal form::
- One or more digits after the `$` prefix.
+ One or more digits after the `$` prefix representing a single byte.
-Binary form::
- Eight bits after the `%` prefix.
+Binary form:: {empty}
++
+--
+. __**N**__ `%` prefixes (at least one).
++
+The number of `%` characters is the number of subsequent expected bytes.
+
+. __**N**__{nbsp}×{nbsp}8 bits (`0` or `1`).
+--
====
Input:
----
%01110011 %01100001 %01101100 %01110101 %01110100
+%%%1101:0010 11111111 #A#11 #B#00 #C#011 #D#1
----
Output:
----
-73 61 6c 75 74 ┆ salut
+73 61 6c 75 74 d2 ff c7 ┆ salut•••
----
====
# Upstream repository: <https://github.com/efficios/normand>.
__author__ = "Philippe Proulx"
-__version__ = "0.15.0"
+__version__ = "0.16.0"
__all__ = [
"__author__",
"__version__",
# Patterns for _try_parse_bin_byte()
_bin_byte_bit_pat = re.compile(r"[01]")
- _bin_byte_prefix_pat = re.compile(r"%")
+ _bin_byte_prefix_pat = re.compile(r"%+")
# Tries to parse a binary byte, returning a byte item on success.
def _try_parse_bin_byte(self):
begin_text_loc = self._text_loc
# Match prefix
- if self._try_parse_pat(self._bin_byte_prefix_pat) is None:
+ m = self._try_parse_pat(self._bin_byte_prefix_pat)
+
+ if m is None:
# No match
return
- # Expect eight bits
- bits = [] # type: List[str]
+ # Expect as many bytes as there are `%` prefixes
+ items = [] # type: List[_Item]
- for _ in range(8):
+ for _ in range(len(m.group(0))):
self._skip_ws_and_comments()
- m = self._expect_pat(self._bin_byte_bit_pat, "Expecting a bit (`0` or `1`)")
- bits.append(m.group(0))
+ byte_text_loc = self._text_loc
+ bits = [] # type: List[str]
+
+ # Expect eight bits
+ for _ in range(8):
+ self._skip_ws_and_comments()
+ m = self._expect_pat(
+ self._bin_byte_bit_pat, "Expecting a bit (`0` or `1`)"
+ )
+ bits.append(m.group(0))
+
+ items.append(_Byte(int("".join(bits), 2), byte_text_loc))
# Return item
- return _Byte(int("".join(bits), 2), begin_text_loc)
+ if len(items) == 1:
+ return items[0]
+
+ # As group
+ return _Group(items, begin_text_loc)
# Patterns for _try_parse_dec_byte()
_dec_byte_prefix_pat = re.compile(r"\$")
param_text_loc = self._text_loc
params.append(
_MacroExpParam(
- *self._expect_const_int_name_expr(True, True), param_text_loc
+ *self._expect_const_int_name_expr(True, True),
+ text_loc=param_text_loc
)
)
expect_comma = True
rep_ret = self._try_parse_rep_post()
if rep_ret is not None:
- item = _Rep(item, *rep_ret, rep_text_loc)
+ item = _Rep(item, *rep_ret, text_loc=rep_text_loc)
items.append(item)
return True