Add many string features v0.19.0
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Tue, 10 Oct 2023 18:03:30 +0000 (14:03 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Tue, 10 Oct 2023 23:26:28 +0000 (19:26 -0400)
This patch improves the string features of Normand.

Specifically, this patch:

• Adds support for the Latin-1 to Latin-10 string encodings:

      s:latin1"bonne journée!"

      62 6f 6e 6e 65 20 6a 6f  75 72 6e e9 65 21  ┆ bonne journ•e!

  The `s:` prefix is needed and also works with existing UTF encoding
  names:

      s:u32le "yo la gang 👋"

• Adds the variable string item.

  The syntax is one of:

      u16le{some_expr}

      {some_expr : s:u16le}

  Any `bool`, `int`, `float`, or `str` variable/label is accepted in the
  expression.

  For the suffix encoding form, the `s:` prefix is required.

• Makes it possible to use a string, possibly literal, as a macro
  expansion parameter:

      m:meow(42, "mix")

• Adds the `--var-str` CLI option to add a variable having a string
  value:

      normand '--var-str=my_var=salut la gang' [...]

See the updated `README.adoc` for more details.

Adding tests and updating existing ones.

Change-Id: I01426bb5ffa53097bb8c85937f54f1b4b498ec06
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Reviewed-on: https://review.lttng.org/c/normand/+/11019
Tested-by: jenkins <jenkins@lttng.org>
101 files changed:
README.adoc
normand/normand.py
pyproject.toml
tests/fail-fl-num-empty-expr.nt
tests/fail-fl-num-eval-type.nt
tests/fail-fl-num-inval-len.nt
tests/fail-fl-num-missing-len.nt
tests/fail-lit-str-missing-suffix.nt [new file with mode: 0644]
tests/fail-macro-exp-inval-param-str.nt [deleted file]
tests/fail-sleb128-empty-expr.nt
tests/fail-str-missing-prefix.nt [new file with mode: 0644]
tests/fail-str-missing-suffix.nt [deleted file]
tests/fail-str-post-empty-expr.nt [new file with mode: 0644]
tests/fail-str-post-inval-latin-enc.nt [new file with mode: 0644]
tests/fail-str-post-inval-utf-spec.nt [new file with mode: 0644]
tests/fail-str-post-missing-enc-colon.nt [new file with mode: 0644]
tests/fail-str-post-missing-enc.nt [new file with mode: 0644]
tests/fail-str-post-missing-gen-prefix.nt [new file with mode: 0644]
tests/fail-str-post-missing-utf-spec.nt [new file with mode: 0644]
tests/fail-str-pre-inval-latin-enc.nt [new file with mode: 0644]
tests/fail-str-pre-inval-syntax.nt [new file with mode: 0644]
tests/fail-str-pre-inval-utf-spec.nt [new file with mode: 0644]
tests/fail-str-pre-missing-enc-colon.nt [new file with mode: 0644]
tests/fail-str-pre-missing-enc.nt [new file with mode: 0644]
tests/fail-str-pre-missing-gen-prefix.nt [new file with mode: 0644]
tests/fail-str-pre-missing-suffix.nt [new file with mode: 0644]
tests/fail-str-pre-missing-utf-spec.nt [new file with mode: 0644]
tests/fail-uleb128-empty-expr.nt
tests/fail-var-eval-type.nt [deleted file]
tests/fail-var-label-bo-none.nt
tests/pass-lit-str-esc-u16be.nt [new file with mode: 0644]
tests/pass-lit-str-esc-u16le.nt [new file with mode: 0644]
tests/pass-lit-str-esc-u32be.nt [new file with mode: 0644]
tests/pass-lit-str-esc-u32le.nt [new file with mode: 0644]
tests/pass-lit-str-esc-u8.nt [new file with mode: 0644]
tests/pass-lit-str-latin1.nt [new file with mode: 0644]
tests/pass-lit-str-latin10.nt [new file with mode: 0644]
tests/pass-lit-str-latin2.nt [new file with mode: 0644]
tests/pass-lit-str-latin3.nt [new file with mode: 0644]
tests/pass-lit-str-latin4.nt [new file with mode: 0644]
tests/pass-lit-str-latin5.nt [new file with mode: 0644]
tests/pass-lit-str-latin6.nt [new file with mode: 0644]
tests/pass-lit-str-latin7.nt [new file with mode: 0644]
tests/pass-lit-str-latin8.nt [new file with mode: 0644]
tests/pass-lit-str-latin9.nt [new file with mode: 0644]
tests/pass-lit-str-nl.nt [new file with mode: 0644]
tests/pass-lit-str-u16be.nt [new file with mode: 0644]
tests/pass-lit-str-u16le.nt [new file with mode: 0644]
tests/pass-lit-str-u32be.nt [new file with mode: 0644]
tests/pass-lit-str-u32le.nt [new file with mode: 0644]
tests/pass-lit-str-u8.nt [new file with mode: 0644]
tests/pass-macro-exp-param-str.nt [new file with mode: 0644]
tests/pass-readme-intro-str.nt
tests/pass-readme-learn-lit-str-1.nt [new file with mode: 0644]
tests/pass-readme-learn-lit-str-2.nt [new file with mode: 0644]
tests/pass-readme-learn-lit-str-3.nt [new file with mode: 0644]
tests/pass-readme-learn-lit-str-4.nt [new file with mode: 0644]
tests/pass-readme-learn-str-1.nt
tests/pass-readme-learn-str-2.nt
tests/pass-readme-learn-str-3.nt [deleted file]
tests/pass-rep-blk-lit-str-u16be.nt [new file with mode: 0644]
tests/pass-rep-blk-lit-str-u16le.nt [new file with mode: 0644]
tests/pass-rep-blk-lit-str-u32be.nt [new file with mode: 0644]
tests/pass-rep-blk-lit-str-u32le.nt [new file with mode: 0644]
tests/pass-rep-blk-lit-str-u8.nt [new file with mode: 0644]
tests/pass-rep-blk-str-u16be.nt [deleted file]
tests/pass-rep-blk-str-u16le.nt [deleted file]
tests/pass-rep-blk-str-u32be.nt [deleted file]
tests/pass-rep-blk-str-u32le.nt [deleted file]
tests/pass-rep-blk-str-u8.nt [deleted file]
tests/pass-rep-post-lit-str-u16be.nt [new file with mode: 0644]
tests/pass-rep-post-lit-str-u16le.nt [new file with mode: 0644]
tests/pass-rep-post-lit-str-u32be.nt [new file with mode: 0644]
tests/pass-rep-post-lit-str-u32le.nt [new file with mode: 0644]
tests/pass-rep-post-lit-str-u8.nt [new file with mode: 0644]
tests/pass-rep-post-str-u16be.nt [deleted file]
tests/pass-rep-post-str-u16le.nt [deleted file]
tests/pass-rep-post-str-u32be.nt [deleted file]
tests/pass-rep-post-str-u32le.nt [deleted file]
tests/pass-rep-post-str-u8.nt [deleted file]
tests/pass-str-esc-u16be.nt [deleted file]
tests/pass-str-esc-u16le.nt [deleted file]
tests/pass-str-esc-u32be.nt [deleted file]
tests/pass-str-esc-u32le.nt [deleted file]
tests/pass-str-esc-u8.nt [deleted file]
tests/pass-str-nl.nt [deleted file]
tests/pass-str-post-bool.nt [new file with mode: 0644]
tests/pass-str-post-expr-lower.nt [new file with mode: 0644]
tests/pass-str-post-latin.nt [new file with mode: 0644]
tests/pass-str-post-utf.nt [new file with mode: 0644]
tests/pass-str-pre-bool.nt [new file with mode: 0644]
tests/pass-str-pre-expr-upper.nt [new file with mode: 0644]
tests/pass-str-pre-float.nt [new file with mode: 0644]
tests/pass-str-pre-int.nt [new file with mode: 0644]
tests/pass-str-pre-latin.nt [new file with mode: 0644]
tests/pass-str-pre-utf.nt [new file with mode: 0644]
tests/pass-str-u16be.nt [deleted file]
tests/pass-str-u16le.nt [deleted file]
tests/pass-str-u32be.nt [deleted file]
tests/pass-str-u32le.nt [deleted file]
tests/pass-str-u8.nt [deleted file]

index c8e983990b128f2b959eec91e422b132dafa90c1..b700941c696a17f03694a5ef33d76e1959424933 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.18, meaning both the Normand
+WARNING: This version of Normand is 0.19, meaning both the Normand
 language and the module/CLI interface aren't stable.
 
 ifdef::env-github[]
@@ -98,13 +98,14 @@ Output:
 aa bb f7 a7 32 da
 ----
 
-UTF-8, UTF-16, and UTF-32 literal strings::
+Strings::
 +
 Input:
 +
 ----
 "hello world!" 00
 u16le"stress\nverdict 🤣"
+s:latin3{hex(ICITTE)}
 ----
 +
 Output:
@@ -112,7 +113,8 @@ Output:
 ----
 68 65 6c 6c 6f 20 77 6f  72 6c 64 21 00 73 00 74  ┆ hello world!•s•t
 00 72 00 65 00 73 00 73  00 0a 00 76 00 65 00 72  ┆ •r•e•s•s•••v•e•r
-00 64 00 69 00 63 00 74  00 20 00 3e d8 23 dd     ┆ •d•i•c•t• •>•#•
+00 64 00 69 00 63 00 74  00 20 00 3e d8 23 dd 30  ┆ •d•i•c•t• •>•#•0
+78 32 66                                          ┆ x2f
 ----
 
 Labels: special variables holding the offset where they're defined::
@@ -468,7 +470,7 @@ 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>>,
+number>>, <<leb-128-integer,LEB128 integer>>, <<string,string>>,
 <<filling,filling>>, <<variable-assignment,variable assignment>>,
 <<conditional-block,conditional block>>, <<repetition-block,repetition
 block>>, <<macro-expansion,macro expansion>>, and
@@ -502,7 +504,7 @@ the current byte order.
 |<<variable-assignment,Variables>>
 |Mapping of variable names to integral or floating point number values.
 |`init_variables` parameter of the `parse()` function.
-|One or more `--var` options.
+|One or more `--var` or `--var-str` options.
 |===
 
 The available items are:
@@ -510,8 +512,8 @@ The available items are:
 * 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.
+* A <<literal-string,literal string>> representing a constant sequence
+  of bytes encoding UTF-8, UTF-16, UTF-32, or Latin-1 to Latin-10 data.
 
 * A <<current-byte-order-setting,current byte order setting>> (big or
   little endian).
@@ -523,6 +525,10 @@ The available items are:
 * An <<leb128-integer,LEB128 integer>> of which the value is the result
   of a {py3} expression.
 
+* A <<string,string>> representing a sequence of bytes encoding UTF-8,
+  UTF-16, UTF-32, or Latin-1 to Latin-10 data, and of which the value is
+  the result of a {py3} expression.
+
 * A <<current-offset-setting,current offset setting>>.
 
 * A <<current-offset-alignment,current offset alignment>>.
@@ -696,22 +702,68 @@ Output:
 
 === Literal string
 
-A _literal string_ represents the UTF-8-, UTF-16-, or UTF-32-encoded
-bytes of a string.
+A _literal string_ represents the encoded bytes of a literal string
+using the UTF-8, UTF-16, UTF-32, or Latin-1 to Latin-10 encoding.
 
 The string to encode isn't implicitly null-terminated: use `\0` at the
 end of the string to add a null character.
 
 A literal string is:
 
-. **Optional**: one of the following encodings instead of UTF-8:
+. **Optional**: one of the following encodings instead of the default
+  UTF-8:
 +
 --
 [horizontal]
-`u16be`:: UTF-16BE.
-`u16le`:: UTF-16LE.
-`u32be`:: UTF-32BE.
-`u32le`:: UTF-32LE.
+`s:u8`::
+`u8`::
+    UTF-8.
+
+`s:u16be`::
+`u16be`::
+    UTF-16BE.
+
+`s:u16le`::
+`u16le`::
+    UTF-16LE.
+
+`s:u32be`::
+`u32be`::
+    UTF-32BE.
+
+`s:u32le`::
+`u32le`::
+    UTF-32LE.
+
+`s:latin1`::
+    ISO/IEC 8859-1.
+
+`s:latin2`::
+    ISO/IEC 8859-2.
+
+`s:latin3`::
+    ISO/IEC 8859-3.
+
+`s:latin4`::
+    ISO/IEC 8859-4.
+
+`s:latin5`::
+    ISO/IEC 8859-9.
+
+`s:latin6`::
+    ISO/IEC 8859-10.
+
+`s:latin7`::
+    ISO/IEC 8859-13.
+
+`s:latin8`::
+    ISO/IEC 8859-14.
+
+`s:latin9`::
+    ISO/IEC 8859-15.
+
+`s:latin10`::
+    ISO/IEC 8859-16.
 --
 
 . The ``pass:["]`` prefix.
@@ -776,7 +828,7 @@ Output:
 Input:
 
 ----
-u32be "\"illusion is the first\nof all pleasures\" 🦉"
+s:u32be "\"illusion is the first\nof all pleasures\" 🦉"
 ----
 
 Output:
@@ -796,6 +848,20 @@ Output:
 ----
 ====
 
+====
+Input:
+
+----
+s:latin1 "Paul Piché"
+----
+
+Output:
+
+----
+50 61 75 6c 20 50 69 63  68 e9  ┆ Paul Pich•
+----
+====
+
 === Current byte order setting
 
 This special item sets the <<cur-bo,_current byte order_>>.
@@ -991,6 +1057,202 @@ aa bb cc dd ee ff fd fa  8d ac 7c 68 65 6c 6c 6f  ┆ ••••••••
 ----
 ====
 
+=== String
+
+A _string_ represents a variable number of bytes encoding a string which
+is the result of evaluating a {py3} expression using the UTF-8, UTF-16,
+UTF-32, or Latin-1 to Latin-10 encoding.
+
+A string has two possible forms:
+
+Encoding prefix form:: {empty}
++
+. An encoding amongst:
++
+--
+[horizontal]
+`s:u8`::
+`u8`::
+    UTF-8.
+
+`s:u16be`::
+`u16be`::
+    UTF-16BE.
+
+`s:u16le`::
+`u16le`::
+    UTF-16LE.
+
+`s:u32be`::
+`u32be`::
+    UTF-32BE.
+
+`s:u32le`::
+`u32le`::
+    UTF-32LE.
+
+`s:latin1`::
+    ISO/IEC 8859-1.
+
+`s:latin2`::
+    ISO/IEC 8859-2.
+
+`s:latin3`::
+    ISO/IEC 8859-3.
+
+`s:latin4`::
+    ISO/IEC 8859-4.
+
+`s:latin5`::
+    ISO/IEC 8859-9.
+
+`s:latin6`::
+    ISO/IEC 8859-10.
+
+`s:latin7`::
+    ISO/IEC 8859-13.
+
+`s:latin8`::
+    ISO/IEC 8859-14.
+
+`s:latin9`::
+    ISO/IEC 8859-15.
+
+`s:latin10`::
+    ISO/IEC 8859-16.
+--
+
+. The ``pass:[{]`` prefix.
+
+. A valid {py3} expression of which the evaluation result type
+  is `bool`, `int`, `float`, or `str` (the first three automatically
+  converted to `str`).
++
+For a string 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**__.
+--
++
+The value of the special name `ICITTE` (`int` type) in this expression
+is the <<cur-offset,current offset>> (before encoding the string).
+
+. The `}` suffix.
+
+Encoding suffix form:: {empty}
++
+. The ``pass:[{]`` prefix.
+
+. A valid {py3} expression of which the evaluation result type
+  is `bool`, `int`, `float`, or `str` (the first three automatically
+  converted to `str`).
++
+For a string 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**__.
+--
++
+The value of the special name `ICITTE` (`int` type) in this expression
+is the <<cur-offset,current offset>> (before encoding the string).
+
+. The `:` character.
+
+. A string encoding amongst:
++
+--
+[horizontal]
+`s:u8`::
+    UTF-8.
+
+`s:u16be`::
+    UTF-16BE.
+
+`s:u16le`::
+    UTF-16LE.
+
+`s:u32be`::
+    UTF-32BE.
+
+`s:u32le`::
+    UTF-32LE.
+
+`s:latin1`::
+    ISO/IEC 8859-1.
+
+`s:latin2`::
+    ISO/IEC 8859-2.
+
+`s:latin3`::
+    ISO/IEC 8859-3.
+
+`s:latin4`::
+    ISO/IEC 8859-4.
+
+`s:latin5`::
+    ISO/IEC 8859-9.
+
+`s:latin6`::
+    ISO/IEC 8859-10.
+
+`s:latin7`::
+    ISO/IEC 8859-13.
+
+`s:latin8`::
+    ISO/IEC 8859-14.
+
+`s:latin9`::
+    ISO/IEC 8859-15.
+
+`s:latin10`::
+    ISO/IEC 8859-16.
+--
+
+. The `}` suffix.
+
+====
+Input:
+
+----
+{iter = 1}
+
+!repeat 10
+  {iter : s:u8} " "
+  {iter = iter + 1}
+!end
+----
+
+Output:
+
+----
+31 20 32 20 33 20 34 20  35 20 36 20 37 20 38 20  ┆ 1 2 3 4 5 6 7 8
+39 20 31 30 20                                    ┆ 9 10
+----
+====
+
+====
+Input:
+
+----
+{meow = 'salut jérémie'}
+{meow.upper() : s:latin1}
+----
+
+Output:
+
+----
+53 41 4c 55 54 20 4a c9  52 c9 4d 49 45  ┆ SALUT J•R•MIE
+----
+====
+
 === Current offset setting
 
 This special item sets the <<cur-offset,_current offset_>>.
@@ -1247,8 +1509,8 @@ A variable assignment is:
 
 . The `=` character.
 
-. A valid {py3} expression of which the evaluation result type
-  is `int`, `float`, or `bool` (automatically converted to `int`).
+. A valid {py3} expression of which the evaluation result type is `int`,
+  `float`, or `bool` (automatically converted to `int`), or `str`.
 +
 For a variable assignment at some source location{nbsp}__**L**__, this
 expression may contain:
@@ -1825,6 +2087,7 @@ A post-item repetition is:
 ** A <<literal-string,literal string>>.
 ** A <<fixed-length-number,fixed-length number>>.
 ** An <<leb128-integer,LEB128 integer>>.
+** A <<string,string>>.
 ** A <<macro-expansion,macro-expansion>>.
 ** A <<group,group>>.
 
index bb9a382d5d2bd0949b973ff39daad23e9f1ccd29..8786900524f2739f64f2ad2884f9fc7c074ea541 100644 (file)
@@ -30,7 +30,7 @@
 # Upstream repository: <https://github.com/efficios/normand>.
 
 __author__ = "Philippe Proulx"
-__version__ = "0.18.0"
+__version__ = "0.19.0"
 __all__ = [
     "__author__",
     "__version__",
@@ -129,8 +129,8 @@ class _Byte(_ScalarItem, _RepableItem):
         return "_Byte({}, {})".format(hex(self._val), repr(self._text_loc))
 
 
-# String.
-class _Str(_ScalarItem, _RepableItem):
+# Literal string.
+class _LitStr(_ScalarItem, _RepableItem):
     def __init__(self, data: bytes, text_loc: TextLocation):
         super().__init__(text_loc)
         self._data = data
@@ -145,7 +145,7 @@ class _Str(_ScalarItem, _RepableItem):
         return len(self._data)
 
     def __repr__(self):
-        return "_Str({}, {})".format(repr(self._data), repr(self._text_loc))
+        return "_LitStr({}, {})".format(repr(self._data), repr(self._text_loc))
 
 
 # Byte order.
@@ -340,6 +340,30 @@ class _SLeb128Int(_Leb128Int, _RepableItem, _ExprMixin):
     pass
 
 
+# String.
+class _Str(_Item, _RepableItem, _ExprMixin):
+    def __init__(
+        self, expr_str: str, expr: ast.Expression, codec: str, text_loc: TextLocation
+    ):
+        super().__init__(text_loc)
+        _ExprMixin.__init__(self, expr_str, expr)
+        self._codec = codec
+
+    # Codec name.
+    @property
+    def codec(self):
+        return self._codec
+
+    def __repr__(self):
+        return "_Str({}, {}, {}, {})".format(
+            self.__class__.__name__,
+            repr(self._expr_str),
+            repr(self._expr),
+            repr(self._codec),
+            repr(self._text_loc),
+        )
+
+
 # Group of items.
 class _Group(_Item, _RepableItem):
     def __init__(self, items: List[_Item], text_loc: TextLocation):
@@ -613,8 +637,19 @@ def _norm_const_int(s: str):
     return s
 
 
+# Encodes the string `s` using the codec `codec`, raising `ParseError`
+# with `text_loc` on encoding error.
+def _encode_str(s: str, codec: str, text_loc: TextLocation):
+    try:
+        return s.encode(codec)
+    except UnicodeEncodeError:
+        _raise_error(
+            "Cannot encode `{}` with the `{}` encoding".format(s, codec), text_loc
+        )
+
+
 # Variables dictionary type (for type hints).
-VariablesT = Dict[str, Union[int, float]]
+VariablesT = Dict[str, Union[int, float, str]]
 
 
 # Labels dictionary type (for type hints).
@@ -857,13 +892,8 @@ class _Parser:
         if item is not None:
             return item
 
-    # Patterns for _try_parse_str()
-    _str_prefix_pat = re.compile(r'(?:u(?P<len>16|32)(?P<bo>be|le))?\s*"')
-    _str_suffix_pat = re.compile(r'"')
-    _str_str_pat = re.compile(r'(?:(?:\\.)|[^"])*')
-
     # Strings corresponding to escape sequence characters
-    _str_escape_seq_strs = {
+    _lit_str_escape_seq_strs = {
         "0": "\0",
         "a": "\a",
         "b": "\b",
@@ -877,40 +907,157 @@ class _Parser:
         '"': '"',
     }
 
-    # Tries to parse a string, returning a string item on success.
-    def _try_parse_str(self):
-        begin_text_loc = self._text_loc
+    # Patterns for _try_parse_lit_str()
+    _lit_str_prefix_suffix_pat = re.compile(r'"')
+    _lit_str_contents_pat = re.compile(r'(?:(?:\\.)|[^"])*')
 
-        # Match prefix
-        m = self._try_parse_pat(self._str_prefix_pat)
+    # Parses a literal string between double quotes (without an encoding
+    # prefix) and returns the resulting string.
+    def _try_parse_lit_str(self, with_prefix: bool):
+        # Match prefix if needed
+        if with_prefix:
+            if self._try_parse_pat(self._lit_str_prefix_suffix_pat) is None:
+                # No match
+                return
 
-        if m is None:
+        # Expect literal string
+        m = self._expect_pat(self._lit_str_contents_pat, "Expecting a literal string")
+
+        # Expect end of string
+        self._expect_pat(
+            self._lit_str_prefix_suffix_pat, 'Expecting `"` (end of literal string)'
+        )
+
+        # Replace escape sequences
+        val = m.group(0)
+
+        for ec in '0abefnrtv"\\':
+            val = val.replace(r"\{}".format(ec), self._lit_str_escape_seq_strs[ec])
+
+        # Return string
+        return val
+
+    # Patterns for _try_parse_utf_str_encoding()
+    _str_encoding_utf_prefix_pat = re.compile(r"u")
+    _str_encoding_utf_pat = re.compile(r"(?:8|(?:(?:16|32)(?:[bl]e)))\b")
+
+    # Tries to parse a UTF encoding specification, returning the Python
+    # codec name on success.
+    def _try_parse_utf_str_encoding(self):
+        # Match prefix
+        if self._try_parse_pat(self._str_encoding_utf_prefix_pat) is None:
             # No match
             return
 
-        # Get encoding
-        encoding = "utf8"
+        # Expect UTF specification
+        m = self._expect_pat(
+            self._str_encoding_utf_pat,
+            "Expecting `8`, `16be`, `16le`, `32be` or `32le`",
+        )
+
+        # Convert to codec name
+        return {
+            "8": "utf_8",
+            "16be": "utf_16_be",
+            "16le": "utf_16_le",
+            "32be": "utf_32_be",
+            "32le": "utf_32_le",
+        }[m.group(0)]
+
+    # Patterns for _try_parse_str_encoding()
+    _str_encoding_gen_prefix_pat = re.compile(r"s")
+    _str_encoding_colon_pat = re.compile(r":")
+    _str_encoding_non_utf_pat = re.compile(r"latin(?:[1-9]|10)\b")
+
+    # Tries to parse a string encoding specification, returning the
+    # Python codec name on success.
+    #
+    # Requires the general prefix (`s:`) if `req_gen_prefix` is `True`.
+    def _try_parse_str_encoding(self, req_gen_prefix: bool = False):
+        # General prefix?
+        if self._try_parse_pat(self._str_encoding_gen_prefix_pat) is not None:
+            # Expect `:`
+            self._skip_ws()
+            self._expect_pat(self._str_encoding_colon_pat, "Expecting `:`")
 
-        if m.group("len") is not None:
-            encoding = "utf_{}_{}".format(m.group("len"), m.group("bo"))
+            # Expect encoding specification
+            self._skip_ws()
 
-        # Actual string
-        m = self._expect_pat(self._str_str_pat, "Expecting a literal string")
+            # UTF?
+            codec = self._try_parse_utf_str_encoding()
 
-        # Expect end of string
-        self._expect_pat(self._str_suffix_pat, 'Expecting `"` (end of literal string)')
+            if codec is not None:
+                return codec
 
-        # Replace escape sequences
-        val = m.group(0)
+            # Expect Latin
+            m = self._expect_pat(
+                self._str_encoding_non_utf_pat,
+                "Expecting `u8`, `u16be`, `u16le`, `u32be`, `u32le`, or `latin1` to `latin10`",
+            )
+            return m.group(0)
 
-        for ec in '0abefnrtv"\\':
-            val = val.replace(r"\{}".format(ec), self._str_escape_seq_strs[ec])
+        # UTF?
+        if not req_gen_prefix:
+            return self._try_parse_utf_str_encoding()
 
-        # Encode
-        data = val.encode(encoding)
+    # Patterns for _try_parse_str()
+    _lit_str_prefix_pat = re.compile(r'"')
+    _str_prefix_pat = re.compile(r'"|\{')
+    _str_expr_pat = re.compile(r"[^}]+")
+    _str_expr_suffix_pat = re.compile(r"\}")
 
-        # Return item
-        return _Str(data, begin_text_loc)
+    # Tries to parse a string, returning a literal string or string item
+    # on success.
+    def _try_parse_str(self):
+        begin_text_loc = self._text_loc
+
+        # Encoding
+        codec = self._try_parse_str_encoding()
+
+        # Match prefix (expect if there's an encoding specification)
+        self._skip_ws()
+
+        if codec is None:
+            # No encoding: only a literal string (UTF-8) is legal
+            m_prefix = self._try_parse_pat(self._lit_str_prefix_pat)
+
+            if m_prefix is None:
+                return
+        else:
+            # Encoding present: expect a string prefix
+            m_prefix = self._expect_pat(self._str_prefix_pat, 'Expecting `"` or `{`')
+
+        # Literal string or expression?
+        prefix = m_prefix.group(0)
+
+        if prefix == '"':
+            # Expect literal string
+            str_text_loc = self._text_loc
+            val = self._try_parse_lit_str(False)
+
+            if val is None:
+                self._raise_error("Expecting a literal string")
+
+            # Encode string
+            data = _encode_str(val, "utf_8" if codec is None else codec, str_text_loc)
+
+            # Return item
+            return _LitStr(data, begin_text_loc)
+        else:
+            # Expect expression
+            self._skip_ws()
+            expr_text_loc = self._text_loc
+            m = self._expect_pat(self._str_expr_pat, "Expecting an expression")
+
+            # Expect `}`
+            self._expect_pat(self._str_expr_suffix_pat, "Expecting `}`")
+
+            # Create an expression node from the expression string
+            expr_str, expr = self._ast_expr_from_str(m.group(0), expr_text_loc)
+
+            # Return item
+            assert codec is not None
+            return _Str(expr_str, expr, codec, begin_text_loc)
 
     # Common right parenthesis pattern
     _right_paren_pat = re.compile(r"\)")
@@ -963,14 +1110,15 @@ class _Parser:
 
         return expr_str, expr
 
-    # Patterns for _try_parse_num_and_attr()
+    # Patterns for _try_parse_val()
     _val_expr_pat = re.compile(r"([^}:]+):\s*")
-    _fl_num_len_attr_pat = re.compile(r"8|16|24|32|40|48|56|64")
-    _leb128_int_attr_pat = re.compile(r"(u|s)leb128")
+    _fl_num_len_fmt_pat = re.compile(r"8|16|24|32|40|48|56|64")
+    _leb128_int_fmt_pat = re.compile(r"(u|s)leb128")
 
-    # Tries to parse a value and attribute (fixed length in bits or
-    # `leb128`), returning a value item on success.
-    def _try_parse_num_and_attr(self):
+    # Tries to parse a value (number or string) and format (fixed length
+    # in bits, `uleb128`, `sleb128`, or `s:` followed with an encoding
+    # name), returning an item on success.
+    def _try_parse_val(self):
         begin_text_loc = self._text_loc
 
         # Match
@@ -983,33 +1131,42 @@ class _Parser:
         # Create an expression node from the expression string
         expr_str, expr = self._ast_expr_from_str(m_expr.group(1), begin_text_loc)
 
-        # Length?
-        m_attr = self._try_parse_pat(self._fl_num_len_attr_pat)
+        # Fixed length?
+        m_fmt = self._try_parse_pat(self._fl_num_len_fmt_pat)
 
-        if m_attr is None:
+        if m_fmt is None:
             # LEB128?
-            m_attr = self._try_parse_pat(self._leb128_int_attr_pat)
+            m_fmt = self._try_parse_pat(self._leb128_int_fmt_pat)
 
-            if m_attr is None:
-                # At this point it's invalid
-                self._raise_error(
-                    "Expecting a length (multiple of eight bits), `uleb128`, or `sleb128`"
-                )
+            if m_fmt is None:
+                # String encoding?
+                codec = self._try_parse_str_encoding(True)
+
+                if codec is None:
+                    # At this point it's invalid
+                    self._raise_error(
+                        "Expecting a fixed length (multiple of eight bits), `uleb128`, `sleb128`, or `s:` followed with a valid encoding (`u8`, `u16be`, `u16le`, `u32be`, `u32le`, or `latin1` to `latin10`)"
+                    )
+                else:
+                    # Return string item
+                    return _Str(expr_str, expr, codec, begin_text_loc)
 
             # Return LEB128 integer item
-            cls = _ULeb128Int if m_attr.group(1) == "u" else _SLeb128Int
+            cls = _ULeb128Int if m_fmt.group(1) == "u" else _SLeb128Int
             return cls(expr_str, expr, begin_text_loc)
         else:
             # Return fixed-length number item
             return _FlNum(
                 expr_str,
                 expr,
-                int(m_attr.group(0)),
+                int(m_fmt.group(0)),
                 begin_text_loc,
             )
 
     # Patterns for _try_parse_var_assign()
-    _var_assign_name_equal_pat = re.compile(r"({})\s*=".format(_py_name_pat.pattern))
+    _var_assign_name_equal_pat = re.compile(
+        r"({})\s*=(?!=)".format(_py_name_pat.pattern)
+    )
     _var_assign_expr_pat = re.compile(r"[^}]+")
 
     # Tries to parse a variable assignment, returning a variable
@@ -1093,8 +1250,8 @@ class _Parser:
         item = self._try_parse_var_assign()
 
         if item is None:
-            # Number item?
-            item = self._try_parse_num_and_attr()
+            # Value item?
+            item = self._try_parse_val()
 
             if item is None:
                 # Byte order setting item?
@@ -1103,7 +1260,7 @@ class _Parser:
                 if item is None:
                     # At this point it's invalid
                     self._raise_error(
-                        "Expecting a fixed-length number, a variable assignment, or a byte order setting"
+                        "Expecting a fixed-length number, a string, a variable assignment, or a byte order setting"
                     )
 
         # Expect suffix
@@ -1279,6 +1436,7 @@ class _Parser:
         accept_const_int: bool = False,
         allow_neg_int: bool = False,
         accept_const_float: bool = False,
+        accept_lit_str: bool = False,
     ):
         begin_text_loc = self._text_loc
 
@@ -1309,9 +1467,19 @@ class _Parser:
         if m is not None:
             return self._ast_expr_from_str(m.group(0), begin_text_loc)
 
+        # Literal string
+        if accept_lit_str:
+            val = self._try_parse_lit_str(True)
+
+            if val is not None:
+                return self._ast_expr_from_str(repr(val), begin_text_loc)
+
         # Expect `{`
         msg_accepted_parts = ["a name", "or `{`"]
 
+        if accept_lit_str:
+            msg_accepted_parts.insert(0, "a literal string")
+
         if accept_const_float:
             msg_accepted_parts.insert(0, "a constant floating point number")
 
@@ -1586,7 +1754,7 @@ class _Parser:
                 # End
                 break
 
-            # Expect a Value
+            # Expect a value
             if expect_comma:
                 self._expect_pat(self._macro_params_comma_pat, "Expecting `,`")
 
@@ -1598,6 +1766,7 @@ class _Parser:
                         accept_const_int=True,
                         allow_neg_int=True,
                         accept_const_float=True,
+                        accept_lit_str=True,
                     ),
                     text_loc=param_text_loc
                 )
@@ -2022,15 +2191,19 @@ class _Gen:
     # `expr_str` at the location `text_loc` considering the current
     # generation state `state`.
     #
-    # If `allow_float` is `True`, then the type of the result may be
+    # If `accept_float` is `True`, then the type of the result may be
     # `float` too.
+    #
+    # If `accept_str` is `True`, then the type of the result may be
+    # `str` too.
     @staticmethod
     def _eval_expr(
         expr_str: str,
         expr: ast.Expression,
         text_loc: TextLocation,
         state: _GenState,
-        allow_float: bool = False,
+        accept_float: bool = False,
+        accept_str: bool = False,
     ):
         syms = {}  # type: VariablesT
         syms.update(state.labels)
@@ -2059,35 +2232,46 @@ class _Gen:
 
         # Validate result type
         expected_types = {int}  # type: Set[type]
-        type_msg = "`int`"
 
-        if allow_float:
+        if accept_float:
             expected_types.add(float)
-            type_msg += " or `float`"
+
+        if accept_str:
+            expected_types.add(str)
 
         if type(val) not in expected_types:
+            expected_types_str = sorted(
+                ["`{}`".format(t.__name__) for t in expected_types]
+            )
+
+            if len(expected_types_str) == 1:
+                msg_expected = expected_types_str[0]
+            elif len(expected_types_str) == 2:
+                msg_expected = " or ".join(expected_types_str)
+            else:
+                expected_types_str[-1] = "or {}".format(expected_types_str[-1])
+                msg_expected = ", ".join(expected_types_str)
+
             _raise_error(
                 "Invalid expression `{}`: expecting result type {}, not `{}`".format(
-                    expr_str, type_msg, type(val).__name__
+                    expr_str, msg_expected, type(val).__name__
                 ),
                 text_loc,
             )
 
         return val
 
-    # Evaluates the expression of `item` considering the current
-    # generation state `state`.
-    #
-    # If `allow_float` is `True`, then the type of the result may be
-    # `float` too.
+    # Forwards to _eval_expr() with the expression and text location of
+    # `item`.
     @staticmethod
     def _eval_item_expr(
-        item: Union[_FlNum, _Leb128Int, _FillUntil, _VarAssign, _Rep, _Cond],
+        item: Union[_Cond, _FillUntil, _FlNum, _Leb128Int, _Rep, _Str, _VarAssign],
         state: _GenState,
-        allow_float: bool = False,
+        accept_float: bool = False,
+        accept_str: bool = False,
     ):
         return _Gen._eval_expr(
-            item.expr_str, item.expr, item.text_loc, state, allow_float
+            item.expr_str, item.expr, item.text_loc, state, accept_float, accept_str
         )
 
     # Handles the byte item `item`.
@@ -2095,8 +2279,8 @@ class _Gen:
         self._data.append(item.val)
         state.offset += item.size
 
-    # Handles the string item `item`.
-    def _handle_str_item(self, item: _Str, state: _GenState):
+    # Handles the literal string item `item`.
+    def _handle_lit_str_item(self, item: _LitStr, state: _GenState):
         self._data += item.data
         state.offset += item.size
 
@@ -2108,7 +2292,9 @@ class _Gen:
     # Handles the variable assignment item `item`.
     def _handle_var_assign_item(self, item: _VarAssign, state: _GenState):
         # Update variable
-        state.variables[item.name] = self._eval_item_expr(item, state, True)
+        state.variables[item.name] = self._eval_item_expr(
+            item, state, accept_float=True, accept_str=True
+        )
 
     # Handles the fixed-length number item `item`.
     def _handle_fl_num_item(self, item: _FlNum, state: _GenState):
@@ -2167,7 +2353,7 @@ class _Gen:
     # Handles the LEB128 integer item `item`.
     def _handle_leb128_int_item(self, item: _Leb128Int, state: _GenState):
         # Compute value
-        val = self._eval_item_expr(item, state, False)
+        val = self._eval_item_expr(item, state)
 
         # Size in bytes
         size = self._leb128_size_for_val(val, type(item) is _SLeb128Int)
@@ -2184,6 +2370,20 @@ class _Gen:
         # Update offset
         state.offset += size
 
+    # Handles the string item `item`.
+    def _handle_str_item(self, item: _Str, state: _GenState):
+        # Compute value
+        val = str(self._eval_item_expr(item, state, accept_float=True, accept_str=True))
+
+        # Encode
+        data = _encode_str(val, item.codec, item.text_loc)
+
+        # Add to data
+        self._data += data
+
+        # Update offset
+        state.offset += len(data)
+
     # Handles the group item `item`, removing the immediate labels from
     # `state` at the end if `remove_immediate_labels` is `True`.
     def _handle_group_item(
@@ -2251,7 +2451,12 @@ class _Gen:
 
         for param_name, param in zip(macro_def.param_names, item.params):
             exp_state.variables[param_name] = _Gen._eval_expr(
-                param.expr_str, param.expr, param.text_loc, init_state, True
+                param.expr_str,
+                param.expr,
+                param.text_loc,
+                init_state,
+                accept_float=True,
+                accept_str=True,
             )
 
         return exp_state
@@ -2423,6 +2628,7 @@ class _Gen:
             _FlNum: self._handle_fl_num_item,
             _Group: self._handle_group_item,
             _Label: self._handle_label_item,
+            _LitStr: self._handle_lit_str_item,
             _MacroExp: self._handle_macro_exp_item,
             _Rep: self._handle_rep_item,
             _SetBo: self._handle_set_bo_item,
@@ -2516,19 +2722,24 @@ def _val_from_assign_val_str(s: str, is_label: bool):
 
 # Returns a dictionary of string to numbers from the list of strings
 # `args` containing `NAME=VAL` entries.
-def _dict_from_arg(args: Optional[List[str]], is_label: bool):
+def _dict_from_arg(args: Optional[List[str]], is_label: bool, is_str_only: bool):
     d = {}  # type: VariablesT
 
     if args is None:
         return d
 
     for arg in args:
-        m = re.match(r"({})\s*=\s*(.+)$".format(_py_name_pat.pattern), arg)
+        m = re.match(r"({})\s*=\s*(.*)$".format(_py_name_pat.pattern), arg)
 
         if m is None:
             _raise_cli_error("Invalid assignment `{}`".format(arg))
 
-        d[m.group(1)] = _val_from_assign_val_str(m.group(2), is_label)
+        if is_str_only:
+            val = m.group(2)
+        else:
+            val = _val_from_assign_val_str(m.group(2), is_label)
+
+        d[m.group(1)] = val
 
     return d
 
@@ -2567,7 +2778,14 @@ def _parse_cli_args():
         "--var",
         metavar="NAME=VAL",
         action="append",
-        help="add an initial variable (may be repeated)",
+        help="add an initial numeric variable (may be repeated)",
+    )
+    ap.add_argument(
+        "-s",
+        "--var-str",
+        metavar="NAME=VAL",
+        action="append",
+        help="add an initial string variable (may be repeated)",
     )
     ap.add_argument(
         "-l",
@@ -2598,8 +2816,9 @@ def _parse_cli_args():
             normand = f.read()
 
     # Variables and labels
-    variables = _dict_from_arg(args.var, False)
-    labels = _dict_from_arg(args.label, True)
+    variables = _dict_from_arg(args.var, False, False)
+    variables.update(_dict_from_arg(args.var_str, False, True))
+    labels = _dict_from_arg(args.label, True, False)
 
     # Validate offset
     if args.offset < 0:
index 4749fd456aea6dbd6d8f6d66bf65e3ab6e6930ed..1c45be3aff5c7b88a7b5199c24b640354dc9770c 100644 (file)
@@ -23,7 +23,7 @@
 
 [tool.poetry]
 name = 'normand'
-version = '0.18.0'
+version = '0.19.0'
 description = 'Text-to-binary processor with its own language'
 license = 'MIT'
 authors = ['Philippe Proulx <eeppeliteloop@gmail.com>']
index 8b6b9573b96ed404d81b5589fafed9188d522457..378a896f8141d96c1f018d8795cddc08c0a6810e 100644 (file)
@@ -1,3 +1,3 @@
 { : 8 }
 ---
-1:3 - Expecting a fixed-length number, a variable assignment, or a byte order setting
+1:3 - Expecting a fixed-length number, a string, a variable assignment, or a byte order setting
index 5269ef1a75cf35350e6fa263b1aef2866bab8bba..96b6aa26f37faf1707e7982a9c3e80927b99c37a 100644 (file)
@@ -1,3 +1,3 @@
 { 'salut' : 8 }
 ---
-1:3 - Invalid expression `'salut'`: expecting result type `int` or `float`, not `str`
+1:3 - Invalid expression `'salut'`: expecting result type `float` or `int`, not `str`
index 7c578efc374c7713a1a3c6d5478ce28a65d845bb..79d465b09a7c97a34fdf25dbf57c4853645f66e2 100644 (file)
@@ -1,3 +1,3 @@
 { 23 : 17 }
 ---
-1:8 - Expecting a length (multiple of eight bits), `uleb128`, or `sleb128`
+1:8 - Expecting a fixed length (multiple of eight bits), `uleb128`, `sleb128`, or `s:` followed with a valid encoding (`u8`, `u16be`, `u16le`, `u32be`, `u32le`, or `latin1` to `latin10`)
index d59bbe6e983250483bfd271512f870b778159f93..000e873a47efc0a9b190be74723d2a41a4ce8302 100644 (file)
@@ -1,3 +1,3 @@
 { 23 :  }
 ---
-1:9 - Expecting a length (multiple of eight bits), `uleb128`, or `sleb128`
+1:9 - Expecting a fixed length (multiple of eight bits), `uleb128`, `sleb128`, or `s:` followed with a valid encoding (`u8`, `u16be`, `u16le`, `u32be`, `u32le`, or `latin1` to `latin10`)
diff --git a/tests/fail-lit-str-missing-suffix.nt b/tests/fail-lit-str-missing-suffix.nt
new file mode 100644 (file)
index 0000000..5a8385e
--- /dev/null
@@ -0,0 +1,3 @@
+"the string
+---
+2:1 - Expecting `"` (end of literal string)
diff --git a/tests/fail-macro-exp-inval-param-str.nt b/tests/fail-macro-exp-inval-param-str.nt
deleted file mode 100644 (file)
index 4fb486a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-!macro salut(a, b, c)
-  "meow" 23 42
-!end
-
-aa bb m:salut(42, "yo", 12) ff
----
-5:19 - Expecting a constant integer, a constant floating point number, a name, or `{`
index c6d2cc9247b0e0b681ea3b91dfa8a5dbcafa3020..f08bb470bcb1a0b07aa9826200591fee3728f0f3 100644 (file)
@@ -1,3 +1,3 @@
 { : sleb128 }
 ---
-1:3 - Expecting a fixed-length number, a variable assignment, or a byte order setting
+1:3 - Expecting a fixed-length number, a string, a variable assignment, or a byte order setting
diff --git a/tests/fail-str-missing-prefix.nt b/tests/fail-str-missing-prefix.nt
new file mode 100644 (file)
index 0000000..bcdd0c0
--- /dev/null
@@ -0,0 +1,3 @@
+ff u16be ee
+---
+1:10 - Expecting `"` or `{`
diff --git a/tests/fail-str-missing-suffix.nt b/tests/fail-str-missing-suffix.nt
deleted file mode 100644 (file)
index 5a8385e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-"the string
----
-2:1 - Expecting `"` (end of literal string)
diff --git a/tests/fail-str-post-empty-expr.nt b/tests/fail-str-post-empty-expr.nt
new file mode 100644 (file)
index 0000000..de98769
--- /dev/null
@@ -0,0 +1,3 @@
+{ : s:u8}
+---
+1:3 - Expecting a fixed-length number, a string, a variable assignment, or a byte order setting
diff --git a/tests/fail-str-post-inval-latin-enc.nt b/tests/fail-str-post-inval-latin-enc.nt
new file mode 100644 (file)
index 0000000..c8e2686
--- /dev/null
@@ -0,0 +1,3 @@
+{"a string" : s:latin11}
+---
+1:17 - Expecting `u8`, `u16be`, `u16le`, `u32be`, `u32le`, or `latin1` to `latin10`
diff --git a/tests/fail-str-post-inval-utf-spec.nt b/tests/fail-str-post-inval-utf-spec.nt
new file mode 100644 (file)
index 0000000..f1033d3
--- /dev/null
@@ -0,0 +1,3 @@
+{"a string" : s:u24be}
+---
+1:18 - Expecting `8`, `16be`, `16le`, `32be` or `32le`
diff --git a/tests/fail-str-post-missing-enc-colon.nt b/tests/fail-str-post-missing-enc-colon.nt
new file mode 100644 (file)
index 0000000..f2b89f0
--- /dev/null
@@ -0,0 +1,3 @@
+{"a string" : slatin1}
+---
+1:16 - Expecting `:`
diff --git a/tests/fail-str-post-missing-enc.nt b/tests/fail-str-post-missing-enc.nt
new file mode 100644 (file)
index 0000000..ef0e407
--- /dev/null
@@ -0,0 +1,3 @@
+{"a string" : }
+---
+1:15 - Expecting a fixed length (multiple of eight bits), `uleb128`, `sleb128`, or `s:` followed with a valid encoding (`u8`, `u16be`, `u16le`, `u32be`, `u32le`, or `latin1` to `latin10`)
diff --git a/tests/fail-str-post-missing-gen-prefix.nt b/tests/fail-str-post-missing-gen-prefix.nt
new file mode 100644 (file)
index 0000000..5273052
--- /dev/null
@@ -0,0 +1,3 @@
+{"a string" : latin1}
+---
+1:15 - Expecting a fixed length (multiple of eight bits), `uleb128`, `sleb128`, or `s:` followed with a valid encoding (`u8`, `u16be`, `u16le`, `u32be`, `u32le`, or `latin1` to `latin10`)
diff --git a/tests/fail-str-post-missing-utf-spec.nt b/tests/fail-str-post-missing-utf-spec.nt
new file mode 100644 (file)
index 0000000..30c5472
--- /dev/null
@@ -0,0 +1,3 @@
+{"a string" : s:u}
+---
+1:18 - Expecting `8`, `16be`, `16le`, `32be` or `32le`
diff --git a/tests/fail-str-pre-inval-latin-enc.nt b/tests/fail-str-pre-inval-latin-enc.nt
new file mode 100644 (file)
index 0000000..e7632ac
--- /dev/null
@@ -0,0 +1,3 @@
+s:latin11{"a string"}
+---
+1:3 - Expecting `u8`, `u16be`, `u16le`, `u32be`, `u32le`, or `latin1` to `latin10`
diff --git a/tests/fail-str-pre-inval-syntax.nt b/tests/fail-str-pre-inval-syntax.nt
new file mode 100644 (file)
index 0000000..d7888e7
--- /dev/null
@@ -0,0 +1,3 @@
+s:latin3 {"hello " 23}
+---
+1:11 - Invalid expression `"hello " 23`: invalid syntax
diff --git a/tests/fail-str-pre-inval-utf-spec.nt b/tests/fail-str-pre-inval-utf-spec.nt
new file mode 100644 (file)
index 0000000..76d5d4a
--- /dev/null
@@ -0,0 +1,3 @@
+u24be{"a string"}
+---
+1:2 - Expecting `8`, `16be`, `16le`, `32be` or `32le`
diff --git a/tests/fail-str-pre-missing-enc-colon.nt b/tests/fail-str-pre-missing-enc-colon.nt
new file mode 100644 (file)
index 0000000..6c8f8e8
--- /dev/null
@@ -0,0 +1,3 @@
+slatin1{"a string"}
+---
+1:2 - Expecting `:`
diff --git a/tests/fail-str-pre-missing-enc.nt b/tests/fail-str-pre-missing-enc.nt
new file mode 100644 (file)
index 0000000..415005f
--- /dev/null
@@ -0,0 +1,3 @@
+{"a string"}
+---
+1:2 - Expecting a fixed-length number, a string, a variable assignment, or a byte order setting
diff --git a/tests/fail-str-pre-missing-gen-prefix.nt b/tests/fail-str-pre-missing-gen-prefix.nt
new file mode 100644 (file)
index 0000000..a9af6dd
--- /dev/null
@@ -0,0 +1,3 @@
+latin1{"a string"}
+---
+1:1 - Unexpected character `l`
diff --git a/tests/fail-str-pre-missing-suffix.nt b/tests/fail-str-pre-missing-suffix.nt
new file mode 100644 (file)
index 0000000..dfc1f2f
--- /dev/null
@@ -0,0 +1,3 @@
+s:latin5 {some_string
+---
+2:1 - Expecting `}`
diff --git a/tests/fail-str-pre-missing-utf-spec.nt b/tests/fail-str-pre-missing-utf-spec.nt
new file mode 100644 (file)
index 0000000..254bcde
--- /dev/null
@@ -0,0 +1,3 @@
+u{"a string"}
+---
+1:2 - Expecting `8`, `16be`, `16le`, `32be` or `32le`
index fe15ea4120310c51c74af16e8b878019acfeea15..daa73c9369f86f704b0ab9e6f5da058c3bd2e013 100644 (file)
@@ -1,3 +1,3 @@
 { : uleb128 }
 ---
-1:3 - Expecting a fixed-length number, a variable assignment, or a byte order setting
+1:3 - Expecting a fixed-length number, a string, a variable assignment, or a byte order setting
diff --git a/tests/fail-var-eval-type.nt b/tests/fail-var-eval-type.nt
deleted file mode 100644 (file)
index 23d04d6..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{ meow = 'salut' }
----
-1:3 - Invalid expression `'salut'`: expecting result type `int` or `float`, not `str`
index 89f1d51724519433ac00f4a7efb6f74bbb308409..0f7314d83323826dedbf431fe390192962ddd032 100644 (file)
@@ -1,3 +1,3 @@
 { hello }
 ---
-1:3 - Expecting a fixed-length number, a variable assignment, or a byte order setting
+1:3 - Expecting a fixed-length number, a string, a variable assignment, or a byte order setting
diff --git a/tests/pass-lit-str-esc-u16be.nt b/tests/pass-lit-str-esc-u16be.nt
new file mode 100644 (file)
index 0000000..726bab3
--- /dev/null
@@ -0,0 +1,5 @@
+u16be"\0 \a \b \e \f \n \r \t \v \" \\"
+---
+00 00 00 20 00 07 00 20 00 08 00 20 00 1b 00 20
+00 0c 00 20 00 0a 00 20 00 0d 00 20 00 09 00 20
+00 0b 00 20 00 22 00 20 00 5c
diff --git a/tests/pass-lit-str-esc-u16le.nt b/tests/pass-lit-str-esc-u16le.nt
new file mode 100644 (file)
index 0000000..3c5a43f
--- /dev/null
@@ -0,0 +1,5 @@
+u16le"\0 \a \b \e \f \n \r \t \v \" \\"
+---
+00 00 20 00 07 00 20 00 08 00 20 00 1b 00 20 00
+0c 00 20 00 0a 00 20 00 0d 00 20 00 09 00 20 00
+0b 00 20 00 22 00 20 00 5c 00
diff --git a/tests/pass-lit-str-esc-u32be.nt b/tests/pass-lit-str-esc-u32be.nt
new file mode 100644 (file)
index 0000000..107d8f8
--- /dev/null
@@ -0,0 +1,8 @@
+u32be"\0 \a \b \e \f \n \r \t \v \" \\"
+---
+00 00 00 00 00 00 00 20 00 00 00 07 00 00 00 20
+00 00 00 08 00 00 00 20 00 00 00 1b 00 00 00 20
+00 00 00 0c 00 00 00 20 00 00 00 0a 00 00 00 20
+00 00 00 0d 00 00 00 20 00 00 00 09 00 00 00 20
+00 00 00 0b 00 00 00 20 00 00 00 22 00 00 00 20
+00 00 00 5c
diff --git a/tests/pass-lit-str-esc-u32le.nt b/tests/pass-lit-str-esc-u32le.nt
new file mode 100644 (file)
index 0000000..3de1c73
--- /dev/null
@@ -0,0 +1,8 @@
+u32le"\0 \a \b \e \f \n \r \t \v \" \\"
+---
+00 00 00 00 20 00 00 00 07 00 00 00 20 00 00 00
+08 00 00 00 20 00 00 00 1b 00 00 00 20 00 00 00
+0c 00 00 00 20 00 00 00 0a 00 00 00 20 00 00 00
+0d 00 00 00 20 00 00 00 09 00 00 00 20 00 00 00
+0b 00 00 00 20 00 00 00 22 00 00 00 20 00 00 00
+5c 00 00 00
diff --git a/tests/pass-lit-str-esc-u8.nt b/tests/pass-lit-str-esc-u8.nt
new file mode 100644 (file)
index 0000000..58b2092
--- /dev/null
@@ -0,0 +1,3 @@
+"\0 \a \b \e \f \n \r \t \v \" \\"
+---
+00 20 07 20 08 20 1b 20 0c 20 0a 20 0d 20 09 20 0b 20 22 20 5c
diff --git a/tests/pass-lit-str-latin1.nt b/tests/pass-lit-str-latin1.nt
new file mode 100644 (file)
index 0000000..2597f36
--- /dev/null
@@ -0,0 +1,25 @@
+s:latin1 " !\"#$%&'()*+,-./"
+s:latin1 "0123456789:;<=>?"
+s:latin1 "@ABCDEFGHIJKLMNO"
+s:latin1 "PQRSTUVWXYZ[\]^_"
+s:latin1 "`abcdefghijklmno"
+s:latin1 "pqrstuvwxyz{|}~¡"
+s:latin1 "¢£¤¥¦§¨©ª«¬®¯°±²"
+s:latin1 "³´µ¶·¸¹º»¼½¾¿ÀÁÂ"
+s:latin1 "ÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒ"
+s:latin1 "ÓÔÕÖ×ØÙÚÛÜÝÞßàáâ"
+s:latin1 "ãäåæçèéêëìíîïðñò"
+s:latin1 "óôõö÷øùúûüýþÿ"
+---
+20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
+30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
+40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
+60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
+70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e a1
+a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ae af b0 b1 b2
+b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2
+c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2
+d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
diff --git a/tests/pass-lit-str-latin10.nt b/tests/pass-lit-str-latin10.nt
new file mode 100644 (file)
index 0000000..6f276df
--- /dev/null
@@ -0,0 +1,25 @@
+s:latin10 " !\"#$%&'()*+,-./"
+s:latin10 "0123456789:;<=>?"
+s:latin10 "@ABCDEFGHIJKLMNO"
+s:latin10 "PQRSTUVWXYZ[\]^_"
+s:latin10 "`abcdefghijklmno"
+s:latin10 "pqrstuvwxyz{|}~Ą"
+s:latin10 "ąŁ€„Š§š©Ș«ŹźŻ°±Č"
+s:latin10 "łŽ”¶·žčș»ŒœŸżÀÁÂ"
+s:latin10 "ĂÄĆÆÇÈÉÊËÌÍÎÏĐŃÒ"
+s:latin10 "ÓÔŐÖŚŰÙÚÛÜĘȚßàáâ"
+s:latin10 "ăäćæçèéêëìíîïđńò"
+s:latin10 "óôőöśűùúûüęțÿ"
+---
+20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
+30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
+40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
+60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
+70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e a1
+a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ae af b0 b1 b2
+b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2
+c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2
+d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
diff --git a/tests/pass-lit-str-latin2.nt b/tests/pass-lit-str-latin2.nt
new file mode 100644 (file)
index 0000000..e873824
--- /dev/null
@@ -0,0 +1,25 @@
+s:latin2 " !\"#$%&'()*+,-./"
+s:latin2 "0123456789:;<=>?"
+s:latin2 "@ABCDEFGHIJKLMNO"
+s:latin2 "PQRSTUVWXYZ[\]^_"
+s:latin2 "`abcdefghijklmno"
+s:latin2 "pqrstuvwxyz{|}~Ą"
+s:latin2 "˘Ł¤ĽŚ§¨ŠŞŤŹŽŻ°ą˛"
+s:latin2 "ł´ľśˇ¸šşťź˝žżŔÁÂ"
+s:latin2 "ĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇ"
+s:latin2 "ÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâ"
+s:latin2 "ăäĺćçčéęëěíîďđńň"
+s:latin2 "óôőö÷řůúűüýţ˙"
+---
+20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
+30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
+40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
+60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
+70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e a1
+a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ae af b0 b1 b2
+b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2
+c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2
+d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
diff --git a/tests/pass-lit-str-latin3.nt b/tests/pass-lit-str-latin3.nt
new file mode 100644 (file)
index 0000000..4cdcdcc
--- /dev/null
@@ -0,0 +1,25 @@
+s:latin3 " !\"#$%&'()*+,-./"
+s:latin3 "0123456789:;<=>?"
+s:latin3 "@ABCDEFGHIJKLMNO"
+s:latin3 "PQRSTUVWXYZ[\]^_"
+s:latin3 "`abcdefghijklmno"
+s:latin3 "pqrstuvwxyz{|}~Ħ"
+s:latin3 "˘£¤Ĥ§¨İŞĞĴŻ°ħ²³´"
+s:latin3 "µĥ·¸ışğĵ½żÀÁÂÄĊĈ"
+s:latin3 "ÇÈÉÊËÌÍÎÏÑÒÓÔĠÖ×"
+s:latin3 "ĜÙÚÛÜŬŜßàáâäċĉçè"
+s:latin3 "éêëìíîïñòóôġö÷ĝù"
+s:latin3 "úûüŭŝ˙"
+---
+20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
+30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
+40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
+60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
+70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e a1
+a2 a3 a4 a6 a7 a8 a9 aa ab ac af b0 b1 b2 b3 b4
+b5 b6 b7 b8 b9 ba bb bc bd bf c0 c1 c2 c4 c5 c6
+c7 c8 c9 ca cb cc cd ce cf d1 d2 d3 d4 d5 d6 d7
+d8 d9 da db dc dd de df e0 e1 e2 e4 e5 e6 e7 e8
+e9 ea eb ec ed ee ef f1 f2 f3 f4 f5 f6 f7 f8 f9
+fa fb fc fd fe ff
diff --git a/tests/pass-lit-str-latin4.nt b/tests/pass-lit-str-latin4.nt
new file mode 100644 (file)
index 0000000..8724942
--- /dev/null
@@ -0,0 +1,25 @@
+s:latin4 " !\"#$%&'()*+,-./"
+s:latin4 "0123456789:;<=>?"
+s:latin4 "@ABCDEFGHIJKLMNO"
+s:latin4 "PQRSTUVWXYZ[\]^_"
+s:latin4 "`abcdefghijklmno"
+s:latin4 "pqrstuvwxyz{|}~Ą"
+s:latin4 "ĸŖ¤ĨĻ§¨ŠĒĢŦŽ¯°ą˛"
+s:latin4 "ŗ´ĩļˇ¸šēģŧŊžŋĀÁÂ"
+s:latin4 "ÃÄÅÆĮČÉĘËĖÍÎĪĐŅŌ"
+s:latin4 "ĶÔÕÖ×ØŲÚÛÜŨŪßāáâ"
+s:latin4 "ãäåæįčéęëėíîīđņō"
+s:latin4 "ķôõö÷øųúûüũū˙"
+---
+20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
+30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
+40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
+60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
+70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e a1
+a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ae af b0 b1 b2
+b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2
+c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2
+d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
diff --git a/tests/pass-lit-str-latin5.nt b/tests/pass-lit-str-latin5.nt
new file mode 100644 (file)
index 0000000..70b1f1b
--- /dev/null
@@ -0,0 +1,25 @@
+s:latin5 " !\"#$%&'()*+,-./"
+s:latin5 "0123456789:;<=>?"
+s:latin5 "@ABCDEFGHIJKLMNO"
+s:latin5 "PQRSTUVWXYZ[\]^_"
+s:latin5 "`abcdefghijklmno"
+s:latin5 "pqrstuvwxyz{|}~¡"
+s:latin5 "¢£¤¥¦§¨©ª«¬®¯°±²"
+s:latin5 "³´µ¶·¸¹º»¼½¾¿ÀÁÂ"
+s:latin5 "ÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒ"
+s:latin5 "ÓÔÕÖ×ØÙÚÛÜİŞßàáâ"
+s:latin5 "ãäåæçèéêëìíîïğñò"
+s:latin5 "óôõö÷øùúûüışÿ"
+---
+20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
+30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
+40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
+60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
+70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e a1
+a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ae af b0 b1 b2
+b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2
+c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2
+d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
diff --git a/tests/pass-lit-str-latin6.nt b/tests/pass-lit-str-latin6.nt
new file mode 100644 (file)
index 0000000..04c59d3
--- /dev/null
@@ -0,0 +1,25 @@
+s:latin6 " !\"#$%&'()*+,-./"
+s:latin6 "0123456789:;<=>?"
+s:latin6 "@ABCDEFGHIJKLMNO"
+s:latin6 "PQRSTUVWXYZ[\]^_"
+s:latin6 "`abcdefghijklmno"
+s:latin6 "pqrstuvwxyz{|}~Ą"
+s:latin6 "ĒĢĪĨĶ§ĻĐŠŦŽŪŊ°ąē"
+s:latin6 "ģīĩķ·ļđšŧž―ūŋĀÁÂ"
+s:latin6 "ÃÄÅÆĮČÉĘËĖÍÎÏÐŅŌ"
+s:latin6 "ÓÔÕÖŨØŲÚÛÜÝÞßāáâ"
+s:latin6 "ãäåæįčéęëėíîïðņō"
+s:latin6 "óôõöũøųúûüýþĸ"
+---
+20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
+30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
+40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
+60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
+70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e a1
+a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ae af b0 b1 b2
+b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2
+c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2
+d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
diff --git a/tests/pass-lit-str-latin7.nt b/tests/pass-lit-str-latin7.nt
new file mode 100644 (file)
index 0000000..5719924
--- /dev/null
@@ -0,0 +1,25 @@
+s:latin7 " !\"#$%&'()*+,-./"
+s:latin7 "0123456789:;<=>?"
+s:latin7 "@ABCDEFGHIJKLMNO"
+s:latin7 "PQRSTUVWXYZ[\]^_"
+s:latin7 "`abcdefghijklmno"
+s:latin7 "pqrstuvwxyz{|}~”"
+s:latin7 "¢£¤„¦§Ø©Ŗ«¬®Æ°±²"
+s:latin7 "³“µ¶·ø¹ŗ»¼½¾æĄĮĀ"
+s:latin7 "ĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅ"
+s:latin7 "ÓŌÕÖ×ŲŁŚŪÜŻŽßąįā"
+s:latin7 "ćäåęēčéźėģķīļšńņ"
+s:latin7 "óōõö÷ųłśūüżž’"
+---
+20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
+30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
+40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
+60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
+70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e a1
+a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ae af b0 b1 b2
+b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2
+c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2
+d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
diff --git a/tests/pass-lit-str-latin8.nt b/tests/pass-lit-str-latin8.nt
new file mode 100644 (file)
index 0000000..6c260fa
--- /dev/null
@@ -0,0 +1,25 @@
+s:latin8 " !\"#$%&'()*+,-./"
+s:latin8 "0123456789:;<=>?"
+s:latin8 "@ABCDEFGHIJKLMNO"
+s:latin8 "PQRSTUVWXYZ[\]^_"
+s:latin8 "`abcdefghijklmno"
+s:latin8 "pqrstuvwxyz{|}~Ḃ"
+s:latin8 "ḃ£ĊċḊ§Ẁ©ẂḋỲ®ŸḞḟĠ"
+s:latin8 "ġṀṁ¶ṖẁṗẃṠỳẄẅṡÀÁÂ"
+s:latin8 "ÃÄÅÆÇÈÉÊËÌÍÎÏŴÑÒ"
+s:latin8 "ÓÔÕÖṪØÙÚÛÜÝŶßàáâ"
+s:latin8 "ãäåæçèéêëìíîïŵñò"
+s:latin8 "óôõöṫøùúûüýŷÿ"
+---
+20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
+30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
+40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
+60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
+70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e a1
+a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ae af b0 b1 b2
+b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2
+c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2
+d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
diff --git a/tests/pass-lit-str-latin9.nt b/tests/pass-lit-str-latin9.nt
new file mode 100644 (file)
index 0000000..8d7fec0
--- /dev/null
@@ -0,0 +1,25 @@
+s:latin9 " !\"#$%&'()*+,-./"
+s:latin9 "0123456789:;<=>?"
+s:latin9 "@ABCDEFGHIJKLMNO"
+s:latin9 "PQRSTUVWXYZ[\]^_"
+s:latin9 "`abcdefghijklmno"
+s:latin9 "pqrstuvwxyz{|}~¡"
+s:latin9 "¢£€¥Š§š©ª«¬®¯°±²"
+s:latin9 "³Žµ¶·ž¹º»ŒœŸ¿ÀÁÂ"
+s:latin9 "ÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒ"
+s:latin9 "ÓÔÕÖ×ØÙÚÛÜÝÞßàáâ"
+s:latin9 "ãäåæçèéêëìíîïðñò"
+s:latin9 "óôõö÷øùúûüýþÿ"
+---
+20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
+30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
+40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
+60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
+70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e a1
+a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ae af b0 b1 b2
+b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2
+c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2
+d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
diff --git a/tests/pass-lit-str-nl.nt b/tests/pass-lit-str-nl.nt
new file mode 100644 (file)
index 0000000..85499d0
--- /dev/null
@@ -0,0 +1,4 @@
+"begin
+end"
+---
+62 65 67 69 6e 0a 65 6e 64
diff --git a/tests/pass-lit-str-u16be.nt b/tests/pass-lit-str-u16be.nt
new file mode 100644 (file)
index 0000000..b4edc74
--- /dev/null
@@ -0,0 +1,5 @@
+u16be"sébastien diaz 🌻"
+---
+00 73 00 e9 00 62 00 61 00 73 00 74 00 69 00 65
+00 6e 00 20 00 64 00 69 00 61 00 7a 00 20 d8 3c
+df 3b
diff --git a/tests/pass-lit-str-u16le.nt b/tests/pass-lit-str-u16le.nt
new file mode 100644 (file)
index 0000000..4efdb01
--- /dev/null
@@ -0,0 +1,5 @@
+u16le "sébastien diaz 🌻"
+---
+73 00 e9 00 62 00 61 00 73 00 74 00 69 00 65 00
+6e 00 20 00 64 00 69 00 61 00 7a 00 20 00 3c d8
+3b df
diff --git a/tests/pass-lit-str-u32be.nt b/tests/pass-lit-str-u32be.nt
new file mode 100644 (file)
index 0000000..8a95653
--- /dev/null
@@ -0,0 +1,6 @@
+u32be "sébastien diaz 🌻"
+---
+00 00 00 73 00 00 00 e9 00 00 00 62 00 00 00 61
+00 00 00 73 00 00 00 74 00 00 00 69 00 00 00 65
+00 00 00 6e 00 00 00 20 00 00 00 64 00 00 00 69
+00 00 00 61 00 00 00 7a 00 00 00 20 00 01 f3 3b
diff --git a/tests/pass-lit-str-u32le.nt b/tests/pass-lit-str-u32le.nt
new file mode 100644 (file)
index 0000000..fc0f86f
--- /dev/null
@@ -0,0 +1,6 @@
+u32le "sébastien diaz 🌻"
+---
+73 00 00 00 e9 00 00 00 62 00 00 00 61 00 00 00
+73 00 00 00 74 00 00 00 69 00 00 00 65 00 00 00
+6e 00 00 00 20 00 00 00 64 00 00 00 69 00 00 00
+61 00 00 00 7a 00 00 00 20 00 00 00 3b f3 01 00
diff --git a/tests/pass-lit-str-u8.nt b/tests/pass-lit-str-u8.nt
new file mode 100644 (file)
index 0000000..01e32f8
--- /dev/null
@@ -0,0 +1,3 @@
+"sébastien" u8" diaz 🌻"
+---
+73 c3 a9 62 61 73 74 69 65 6e 20 64 69 61 7a 20 f0 9f 8c bb
diff --git a/tests/pass-macro-exp-param-str.nt b/tests/pass-macro-exp-param-str.nt
new file mode 100644 (file)
index 0000000..5b8ab83
--- /dev/null
@@ -0,0 +1,16 @@
+!macro salut(zoom)
+  "meow " {zoom : s:latin1}
+!end
+
+{be}
+aa bb
+m:salut("mix\n")
+m:salut("meow")
+ff
+---
+aa bb
+
+6d 65 6f 77 20 6d 69 78 0a
+6d 65 6f 77 20 6d 65 6f 77
+
+ff
index 619d23631701304948e659658d097f3afaf34b0b..59742b6467ff8b8e67ce71bd9a76d9bd0784172f 100644 (file)
@@ -1,6 +1,8 @@
 "hello world!" 00
 u16le"stress\nverdict 🤣"
+s:latin3{hex(ICITTE)}
 ---
 68 65 6c 6c 6f 20 77 6f 72 6c 64 21 00 73 00 74
 00 72 00 65 00 73 00 73 00 0a 00 76 00 65 00 72
-00 64 00 69 00 63 00 74 00 20 00 3e d8 23 dd
+00 64 00 69 00 63 00 74 00 20 00 3e d8 23 dd 30
+78 32 66
diff --git a/tests/pass-readme-learn-lit-str-1.nt b/tests/pass-readme-learn-lit-str-1.nt
new file mode 100644 (file)
index 0000000..6a8143e
--- /dev/null
@@ -0,0 +1,4 @@
+"coucou tout le monde!"
+---
+63 6f 75 63 6f 75 20 74 6f 75 74 20 6c 65 20 6d
+6f 6e 64 65 21
diff --git a/tests/pass-readme-learn-lit-str-2.nt b/tests/pass-readme-learn-lit-str-2.nt
new file mode 100644 (file)
index 0000000..19dc882
--- /dev/null
@@ -0,0 +1,8 @@
+u16le"I am not young enough to know everything."
+---
+49 00 20 00 61 00 6d 00 20 00 6e 00 6f 00 74 00
+20 00 79 00 6f 00 75 00 6e 00 67 00 20 00 65 00
+6e 00 6f 00 75 00 67 00 68 00 20 00 74 00 6f 00
+20 00 6b 00 6e 00 6f 00 77 00 20 00 65 00 76 00
+65 00 72 00 79 00 74 00 68 00 69 00 6e 00 67 00
+2e 00
diff --git a/tests/pass-readme-learn-lit-str-3.nt b/tests/pass-readme-learn-lit-str-3.nt
new file mode 100644 (file)
index 0000000..f369d84
--- /dev/null
@@ -0,0 +1,13 @@
+s:u32be "\"illusion is the first\nof all pleasures\" 🦉"
+---
+00 00 00 22 00 00 00 69 00 00 00 6c 00 00 00 6c
+00 00 00 75 00 00 00 73 00 00 00 69 00 00 00 6f
+00 00 00 6e 00 00 00 20 00 00 00 69 00 00 00 73
+00 00 00 20 00 00 00 74 00 00 00 68 00 00 00 65
+00 00 00 20 00 00 00 66 00 00 00 69 00 00 00 72
+00 00 00 73 00 00 00 74 00 00 00 0a 00 00 00 6f
+00 00 00 66 00 00 00 20 00 00 00 61 00 00 00 6c
+00 00 00 6c 00 00 00 20 00 00 00 70 00 00 00 6c
+00 00 00 65 00 00 00 61 00 00 00 73 00 00 00 75
+00 00 00 72 00 00 00 65 00 00 00 73 00 00 00 22
+00 00 00 20 00 01 f9 89
diff --git a/tests/pass-readme-learn-lit-str-4.nt b/tests/pass-readme-learn-lit-str-4.nt
new file mode 100644 (file)
index 0000000..196b109
--- /dev/null
@@ -0,0 +1,3 @@
+s:latin1 "Paul Piché"
+---
+50 61 75 6c 20 50 69 63 68 e9
index 6a8143e00ac4f043545e70a7155c0e0f8ea9e476..89d39621ed9a50d4bf68317137f2af95d9d71393 100644 (file)
@@ -1,4 +1,9 @@
-"coucou tout le monde!"
+{iter = 1}
+
+!repeat 10
+  {iter : s:u8} " "
+  {iter = iter + 1}
+!end
 ---
-63 6f 75 63 6f 75 20 74 6f 75 74 20 6c 65 20 6d
-6f 6e 64 65 21
+31 20 32 20 33 20 34 20 35 20 36 20 37 20 38 20
+39 20 31 30 20
index 19dc882dfc1d4a798972400dc526996e0be71516..99d9240120192dc8b3d370ba5713d6fa01ffaef7 100644 (file)
@@ -1,8 +1,4 @@
-u16le"I am not young enough to know everything."
+{meow = 'salut jérémie'}
+{meow.upper() : s:latin1}
 ---
-49 00 20 00 61 00 6d 00 20 00 6e 00 6f 00 74 00
-20 00 79 00 6f 00 75 00 6e 00 67 00 20 00 65 00
-6e 00 6f 00 75 00 67 00 68 00 20 00 74 00 6f 00
-20 00 6b 00 6e 00 6f 00 77 00 20 00 65 00 76 00
-65 00 72 00 79 00 74 00 68 00 69 00 6e 00 67 00
-2e 00
+53 41 4c 55 54 20 4a c9 52 c9 4d 49 45
diff --git a/tests/pass-readme-learn-str-3.nt b/tests/pass-readme-learn-str-3.nt
deleted file mode 100644 (file)
index 72de004..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-u32be "\"illusion is the first\nof all pleasures\" 🦉"
----
-00 00 00 22 00 00 00 69 00 00 00 6c 00 00 00 6c
-00 00 00 75 00 00 00 73 00 00 00 69 00 00 00 6f
-00 00 00 6e 00 00 00 20 00 00 00 69 00 00 00 73
-00 00 00 20 00 00 00 74 00 00 00 68 00 00 00 65
-00 00 00 20 00 00 00 66 00 00 00 69 00 00 00 72
-00 00 00 73 00 00 00 74 00 00 00 0a 00 00 00 6f
-00 00 00 66 00 00 00 20 00 00 00 61 00 00 00 6c
-00 00 00 6c 00 00 00 20 00 00 00 70 00 00 00 6c
-00 00 00 65 00 00 00 61 00 00 00 73 00 00 00 75
-00 00 00 72 00 00 00 65 00 00 00 73 00 00 00 22
-00 00 00 20 00 01 f9 89
diff --git a/tests/pass-rep-blk-lit-str-u16be.nt b/tests/pass-rep-blk-lit-str-u16be.nt
new file mode 100644 (file)
index 0000000..8f68aec
--- /dev/null
@@ -0,0 +1,5 @@
+!repeat 3 u16be"yo" !end
+---
+00 79 00 6f
+00 79 00 6f
+00 79 00 6f
diff --git a/tests/pass-rep-blk-lit-str-u16le.nt b/tests/pass-rep-blk-lit-str-u16le.nt
new file mode 100644 (file)
index 0000000..9290579
--- /dev/null
@@ -0,0 +1,5 @@
+!repeat 3 u16le"yo" !end
+---
+79 00 6f 00
+79 00 6f 00
+79 00 6f 00
diff --git a/tests/pass-rep-blk-lit-str-u32be.nt b/tests/pass-rep-blk-lit-str-u32be.nt
new file mode 100644 (file)
index 0000000..04c6962
--- /dev/null
@@ -0,0 +1,5 @@
+!repeat 3 u32be"yo" !end
+---
+00 00 00 79 00 00 00 6f
+00 00 00 79 00 00 00 6f
+00 00 00 79 00 00 00 6f
diff --git a/tests/pass-rep-blk-lit-str-u32le.nt b/tests/pass-rep-blk-lit-str-u32le.nt
new file mode 100644 (file)
index 0000000..e874539
--- /dev/null
@@ -0,0 +1,5 @@
+!repeat 3 u32le"yo" !end
+---
+79 00 00 00 6f 00 00 00
+79 00 00 00 6f 00 00 00
+79 00 00 00 6f 00 00 00
diff --git a/tests/pass-rep-blk-lit-str-u8.nt b/tests/pass-rep-blk-lit-str-u8.nt
new file mode 100644 (file)
index 0000000..12e85c6
--- /dev/null
@@ -0,0 +1,5 @@
+!repeat 3 "yo" !end
+---
+79 6f
+79 6f
+79 6f
diff --git a/tests/pass-rep-blk-str-u16be.nt b/tests/pass-rep-blk-str-u16be.nt
deleted file mode 100644 (file)
index 8f68aec..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-!repeat 3 u16be"yo" !end
----
-00 79 00 6f
-00 79 00 6f
-00 79 00 6f
diff --git a/tests/pass-rep-blk-str-u16le.nt b/tests/pass-rep-blk-str-u16le.nt
deleted file mode 100644 (file)
index 9290579..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-!repeat 3 u16le"yo" !end
----
-79 00 6f 00
-79 00 6f 00
-79 00 6f 00
diff --git a/tests/pass-rep-blk-str-u32be.nt b/tests/pass-rep-blk-str-u32be.nt
deleted file mode 100644 (file)
index 04c6962..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-!repeat 3 u32be"yo" !end
----
-00 00 00 79 00 00 00 6f
-00 00 00 79 00 00 00 6f
-00 00 00 79 00 00 00 6f
diff --git a/tests/pass-rep-blk-str-u32le.nt b/tests/pass-rep-blk-str-u32le.nt
deleted file mode 100644 (file)
index e874539..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-!repeat 3 u32le"yo" !end
----
-79 00 00 00 6f 00 00 00
-79 00 00 00 6f 00 00 00
-79 00 00 00 6f 00 00 00
diff --git a/tests/pass-rep-blk-str-u8.nt b/tests/pass-rep-blk-str-u8.nt
deleted file mode 100644 (file)
index 12e85c6..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-!repeat 3 "yo" !end
----
-79 6f
-79 6f
-79 6f
diff --git a/tests/pass-rep-post-lit-str-u16be.nt b/tests/pass-rep-post-lit-str-u16be.nt
new file mode 100644 (file)
index 0000000..a43f1b1
--- /dev/null
@@ -0,0 +1,5 @@
+u16be"yo"*3
+---
+00 79 00 6f
+00 79 00 6f
+00 79 00 6f
diff --git a/tests/pass-rep-post-lit-str-u16le.nt b/tests/pass-rep-post-lit-str-u16le.nt
new file mode 100644 (file)
index 0000000..8577499
--- /dev/null
@@ -0,0 +1,5 @@
+u16le"yo"*3
+---
+79 00 6f 00
+79 00 6f 00
+79 00 6f 00
diff --git a/tests/pass-rep-post-lit-str-u32be.nt b/tests/pass-rep-post-lit-str-u32be.nt
new file mode 100644 (file)
index 0000000..cd4efc0
--- /dev/null
@@ -0,0 +1,5 @@
+u32be"yo"*3
+---
+00 00 00 79 00 00 00 6f
+00 00 00 79 00 00 00 6f
+00 00 00 79 00 00 00 6f
diff --git a/tests/pass-rep-post-lit-str-u32le.nt b/tests/pass-rep-post-lit-str-u32le.nt
new file mode 100644 (file)
index 0000000..33ef354
--- /dev/null
@@ -0,0 +1,5 @@
+u32le"yo"*3
+---
+79 00 00 00 6f 00 00 00
+79 00 00 00 6f 00 00 00
+79 00 00 00 6f 00 00 00
diff --git a/tests/pass-rep-post-lit-str-u8.nt b/tests/pass-rep-post-lit-str-u8.nt
new file mode 100644 (file)
index 0000000..84100a6
--- /dev/null
@@ -0,0 +1,5 @@
+"yo"*3
+---
+79 6f
+79 6f
+79 6f
diff --git a/tests/pass-rep-post-str-u16be.nt b/tests/pass-rep-post-str-u16be.nt
deleted file mode 100644 (file)
index a43f1b1..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-u16be"yo"*3
----
-00 79 00 6f
-00 79 00 6f
-00 79 00 6f
diff --git a/tests/pass-rep-post-str-u16le.nt b/tests/pass-rep-post-str-u16le.nt
deleted file mode 100644 (file)
index 8577499..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-u16le"yo"*3
----
-79 00 6f 00
-79 00 6f 00
-79 00 6f 00
diff --git a/tests/pass-rep-post-str-u32be.nt b/tests/pass-rep-post-str-u32be.nt
deleted file mode 100644 (file)
index cd4efc0..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-u32be"yo"*3
----
-00 00 00 79 00 00 00 6f
-00 00 00 79 00 00 00 6f
-00 00 00 79 00 00 00 6f
diff --git a/tests/pass-rep-post-str-u32le.nt b/tests/pass-rep-post-str-u32le.nt
deleted file mode 100644 (file)
index 33ef354..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-u32le"yo"*3
----
-79 00 00 00 6f 00 00 00
-79 00 00 00 6f 00 00 00
-79 00 00 00 6f 00 00 00
diff --git a/tests/pass-rep-post-str-u8.nt b/tests/pass-rep-post-str-u8.nt
deleted file mode 100644 (file)
index 84100a6..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-"yo"*3
----
-79 6f
-79 6f
-79 6f
diff --git a/tests/pass-str-esc-u16be.nt b/tests/pass-str-esc-u16be.nt
deleted file mode 100644 (file)
index 726bab3..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-u16be"\0 \a \b \e \f \n \r \t \v \" \\"
----
-00 00 00 20 00 07 00 20 00 08 00 20 00 1b 00 20
-00 0c 00 20 00 0a 00 20 00 0d 00 20 00 09 00 20
-00 0b 00 20 00 22 00 20 00 5c
diff --git a/tests/pass-str-esc-u16le.nt b/tests/pass-str-esc-u16le.nt
deleted file mode 100644 (file)
index 3c5a43f..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-u16le"\0 \a \b \e \f \n \r \t \v \" \\"
----
-00 00 20 00 07 00 20 00 08 00 20 00 1b 00 20 00
-0c 00 20 00 0a 00 20 00 0d 00 20 00 09 00 20 00
-0b 00 20 00 22 00 20 00 5c 00
diff --git a/tests/pass-str-esc-u32be.nt b/tests/pass-str-esc-u32be.nt
deleted file mode 100644 (file)
index 107d8f8..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-u32be"\0 \a \b \e \f \n \r \t \v \" \\"
----
-00 00 00 00 00 00 00 20 00 00 00 07 00 00 00 20
-00 00 00 08 00 00 00 20 00 00 00 1b 00 00 00 20
-00 00 00 0c 00 00 00 20 00 00 00 0a 00 00 00 20
-00 00 00 0d 00 00 00 20 00 00 00 09 00 00 00 20
-00 00 00 0b 00 00 00 20 00 00 00 22 00 00 00 20
-00 00 00 5c
diff --git a/tests/pass-str-esc-u32le.nt b/tests/pass-str-esc-u32le.nt
deleted file mode 100644 (file)
index 3de1c73..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-u32le"\0 \a \b \e \f \n \r \t \v \" \\"
----
-00 00 00 00 20 00 00 00 07 00 00 00 20 00 00 00
-08 00 00 00 20 00 00 00 1b 00 00 00 20 00 00 00
-0c 00 00 00 20 00 00 00 0a 00 00 00 20 00 00 00
-0d 00 00 00 20 00 00 00 09 00 00 00 20 00 00 00
-0b 00 00 00 20 00 00 00 22 00 00 00 20 00 00 00
-5c 00 00 00
diff --git a/tests/pass-str-esc-u8.nt b/tests/pass-str-esc-u8.nt
deleted file mode 100644 (file)
index 58b2092..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-"\0 \a \b \e \f \n \r \t \v \" \\"
----
-00 20 07 20 08 20 1b 20 0c 20 0a 20 0d 20 09 20 0b 20 22 20 5c
diff --git a/tests/pass-str-nl.nt b/tests/pass-str-nl.nt
deleted file mode 100644 (file)
index 85499d0..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-"begin
-end"
----
-62 65 67 69 6e 0a 65 6e 64
diff --git a/tests/pass-str-post-bool.nt b/tests/pass-str-post-bool.nt
new file mode 100644 (file)
index 0000000..df32e1a
--- /dev/null
@@ -0,0 +1,5 @@
+{False : s:latin1}
+{True : s:latin1}
+---
+30
+31
diff --git a/tests/pass-str-post-expr-lower.nt b/tests/pass-str-post-expr-lower.nt
new file mode 100644 (file)
index 0000000..89313fb
--- /dev/null
@@ -0,0 +1,7 @@
+{meow = 'LÉGIFÉRER'}
+
+{meow.lower() : s:latin1}
+{ICITTE == len(meow) : 8}
+---
+6c e9 67 69 66 e9 72 65 72
+01
diff --git a/tests/pass-str-post-latin.nt b/tests/pass-str-post-latin.nt
new file mode 100644 (file)
index 0000000..70b96ea
--- /dev/null
@@ -0,0 +1,21 @@
+{"ãäåæçèéêëìíîïðñò" : s:latin1}
+{"ăäĺćçčéęëěíîďđńň" : s:latin2}
+{"µĥ·¸ışğĵ½żÀÁÂÄĊĈ" : s:latin3}
+{"ãäåæįčéęëėíîīđņō" : s:latin4}
+{"ãäåæçèéêëìíîïğñò" : s:latin5}
+{"ÃÄÅÆĮČÉĘËĖÍÎÏÐŅŌ" : s:latin6}
+{"ÓŌÕÖ×ŲŁŚŪÜŻŽßąįā" : s:latin7}
+{"ãäåæçèéêëìíîïŵñò" : s:latin8}
+{"ÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒ" : s:latin9}
+{"łŽ”¶·žčș»ŒœŸżÀÁÂ" : s:latin10}
+---
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+b5 b6 b7 b8 b9 ba bb bc bd bf c0 c1 c2 c4 c5 c6
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2
+d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2
+b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2
diff --git a/tests/pass-str-post-utf.nt b/tests/pass-str-post-utf.nt
new file mode 100644 (file)
index 0000000..4c74156
--- /dev/null
@@ -0,0 +1,15 @@
+{zoom = 'hello 🦊'}
+
+{zoom : s:u8}
+{zoom : s:u16be}
+{zoom : s:u16le}
+{zoom : s:u32be}
+{zoom : s:u32le}
+---
+68 65 6c 6c 6f 20 f0 9f a6 8a 00 68 00 65 00 6c
+00 6c 00 6f 00 20 d8 3e dd 8a 68 00 65 00 6c 00
+6c 00 6f 00 20 00 3e d8 8a dd 00 00 00 68 00 00
+00 65 00 00 00 6c 00 00 00 6c 00 00 00 6f 00 00
+00 20 00 01 f9 8a 68 00 00 00 65 00 00 00 6c 00
+00 00 6c 00 00 00 6f 00 00 00 20 00 00 00 8a f9
+01 00
diff --git a/tests/pass-str-pre-bool.nt b/tests/pass-str-pre-bool.nt
new file mode 100644 (file)
index 0000000..37b25cd
--- /dev/null
@@ -0,0 +1,5 @@
+s:latin1{False}
+s:latin1{True}
+---
+30
+31
diff --git a/tests/pass-str-pre-expr-upper.nt b/tests/pass-str-pre-expr-upper.nt
new file mode 100644 (file)
index 0000000..0b80279
--- /dev/null
@@ -0,0 +1,5 @@
+{meow = 'légiférer'}
+
+u8{meow.upper()}
+---
+4c c3 89 47 49 46 c3 89 52 45 52
diff --git a/tests/pass-str-pre-float.nt b/tests/pass-str-pre-float.nt
new file mode 100644 (file)
index 0000000..bbd95af
--- /dev/null
@@ -0,0 +1,3 @@
+{-23.42 : s:latin1}
+---
+2d 32 33 2e 34 32
diff --git a/tests/pass-str-pre-int.nt b/tests/pass-str-pre-int.nt
new file mode 100644 (file)
index 0000000..4c3cd16
--- /dev/null
@@ -0,0 +1,3 @@
+{-42 : s:latin1}
+---
+2d 34 32
diff --git a/tests/pass-str-pre-latin.nt b/tests/pass-str-pre-latin.nt
new file mode 100644 (file)
index 0000000..3f431ed
--- /dev/null
@@ -0,0 +1,21 @@
+s:latin1 {"ãäåæçèéêëìíîïðñò"}
+s:latin2 {"ăäĺćçčéęëěíîďđńň"}
+s:latin3 {"µĥ·¸ışğĵ½żÀÁÂÄĊĈ"}
+s:latin4 {"ãäåæįčéęëėíîīđņō"}
+s:latin5 {"ãäåæçèéêëìíîïğñò"}
+s:latin6 {"ÃÄÅÆĮČÉĘËĖÍÎÏÐŅŌ"}
+s:latin7 {"ÓŌÕÖ×ŲŁŚŪÜŻŽßąįā"}
+s:latin8 {"ãäåæçèéêëìíîïŵñò"}
+s:latin9 {"ÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒ"}
+s:latin10 {"łŽ”¶·žčș»ŒœŸżÀÁÂ"}
+---
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+b5 b6 b7 b8 b9 ba bb bc bd bf c0 c1 c2 c4 c5 c6
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2
+d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2
+e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2
+c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2
+b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2
diff --git a/tests/pass-str-pre-utf.nt b/tests/pass-str-pre-utf.nt
new file mode 100644 (file)
index 0000000..a3739cf
--- /dev/null
@@ -0,0 +1,15 @@
+{zoom = 'hello 🦊'}
+
+u8{zoom}
+u16be{zoom}
+u16le{zoom}
+u32be{zoom}
+u32le{zoom}
+---
+68 65 6c 6c 6f 20 f0 9f a6 8a 00 68 00 65 00 6c
+00 6c 00 6f 00 20 d8 3e dd 8a 68 00 65 00 6c 00
+6c 00 6f 00 20 00 3e d8 8a dd 00 00 00 68 00 00
+00 65 00 00 00 6c 00 00 00 6c 00 00 00 6f 00 00
+00 20 00 01 f9 8a 68 00 00 00 65 00 00 00 6c 00
+00 00 6c 00 00 00 6f 00 00 00 20 00 00 00 8a f9
+01 00
diff --git a/tests/pass-str-u16be.nt b/tests/pass-str-u16be.nt
deleted file mode 100644 (file)
index b4edc74..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-u16be"sébastien diaz 🌻"
----
-00 73 00 e9 00 62 00 61 00 73 00 74 00 69 00 65
-00 6e 00 20 00 64 00 69 00 61 00 7a 00 20 d8 3c
-df 3b
diff --git a/tests/pass-str-u16le.nt b/tests/pass-str-u16le.nt
deleted file mode 100644 (file)
index 4efdb01..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-u16le "sébastien diaz 🌻"
----
-73 00 e9 00 62 00 61 00 73 00 74 00 69 00 65 00
-6e 00 20 00 64 00 69 00 61 00 7a 00 20 00 3c d8
-3b df
diff --git a/tests/pass-str-u32be.nt b/tests/pass-str-u32be.nt
deleted file mode 100644 (file)
index 8a95653..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-u32be "sébastien diaz 🌻"
----
-00 00 00 73 00 00 00 e9 00 00 00 62 00 00 00 61
-00 00 00 73 00 00 00 74 00 00 00 69 00 00 00 65
-00 00 00 6e 00 00 00 20 00 00 00 64 00 00 00 69
-00 00 00 61 00 00 00 7a 00 00 00 20 00 01 f3 3b
diff --git a/tests/pass-str-u32le.nt b/tests/pass-str-u32le.nt
deleted file mode 100644 (file)
index fc0f86f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-u32le "sébastien diaz 🌻"
----
-73 00 00 00 e9 00 00 00 62 00 00 00 61 00 00 00
-73 00 00 00 74 00 00 00 69 00 00 00 65 00 00 00
-6e 00 00 00 20 00 00 00 64 00 00 00 69 00 00 00
-61 00 00 00 7a 00 00 00 20 00 00 00 3b f3 01 00
diff --git a/tests/pass-str-u8.nt b/tests/pass-str-u8.nt
deleted file mode 100644 (file)
index fea1b0b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-"sébastien diaz 🌻"
----
-73 c3 a9 62 61 73 74 69 65 6e 20 64 69 61 7a 20 f0 9f 8c bb
This page took 0.066323 seconds and 4 git commands to generate.