From 64051d72dd4c226fe0e87d28f040425849ee7999 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Sun, 26 Sep 2021 23:51:21 +0200
Subject: [PATCH] git subrepo clone (merge) --branch=main
 git@github.com:taocpp/PEGTL.git packages/PEGTL

subrepo:
  subdir:   "packages/PEGTL"
  merged:   "fbfebc50d"
upstream:
  origin:   "git@github.com:taocpp/PEGTL.git"
  branch:   "main"
  commit:   "fbfebc50d"
git-subrepo:
  version:  "0.4.3"
  origin:   "git@github.com:ingydotnet/git-subrepo.git"
  commit:   "2f68596"
---
 packages/PEGTL/.github/workflows/android.yml  |  10 +-
 .../PEGTL/.github/workflows/clang-analyze.yml |  12 +-
 .../PEGTL/.github/workflows/clang-format.yml  |  14 +-
 .../PEGTL/.github/workflows/clang-tidy.yml    |  12 +-
 .../PEGTL/.github/workflows/code-coverage.yml |  10 +-
 .../.github/workflows/codeql-analysis.yml     |  10 +-
 packages/PEGTL/.github/workflows/linux.yml    |  18 +-
 packages/PEGTL/.github/workflows/macos.yml    |  10 +-
 .../PEGTL/.github/workflows/no-exceptions.yml |  10 +-
 .../PEGTL/.github/workflows/sanitizer.yml     |  10 +-
 packages/PEGTL/.github/workflows/windows.yml  |  10 +-
 packages/PEGTL/.gitrepo                       |   6 +-
 packages/PEGTL/README.md                      |   2 +-
 packages/PEGTL/doc/Changelog.md               |   4 +-
 packages/PEGTL/doc/Contrib-and-Examples.md    |   6 +
 packages/PEGTL/doc/Installing-and-Using.md    |   2 -
 packages/PEGTL/doc/Parse-Tree.md              |   4 +-
 .../PEGTL/include/tao/pegtl/argv_input.hpp    |   6 +-
 .../PEGTL/include/tao/pegtl/buffer_input.hpp  |   2 +-
 .../tao/pegtl/change_action_and_state.hpp     |  30 +-
 .../PEGTL/include/tao/pegtl/change_state.hpp  |  31 +-
 .../include/tao/pegtl/contrib/add_state.hpp   |  69 +++++
 .../include/tao/pegtl/contrib/analyze.hpp     |   2 +-
 .../PEGTL/include/tao/pegtl/contrib/http.hpp  |   6 +-
 .../include/tao/pegtl/contrib/integer.hpp     |  60 +++-
 .../PEGTL/include/tao/pegtl/contrib/peg.hpp   | 220 +++++++--------
 .../tao/pegtl/internal/file_mapper_posix.hpp  |   4 +-
 packages/PEGTL/include/tao/pegtl/position.hpp |   6 +-
 .../PEGTL/src/example/pegtl/CMakeLists.txt    |   2 -
 .../PEGTL/src/example/pegtl/abnf2pegtl.cpp    |  24 +-
 .../PEGTL/src/example/pegtl/expression.cpp    | 267 ++++++------------
 .../PEGTL/src/example/pegtl/indent_aware.cpp  |   2 -
 .../PEGTL/src/example/pegtl/json_errors.hpp   |   8 +-
 .../src/example/pegtl/lua53_print_debug.cpp   |  25 --
 .../src/example/pegtl/lua53_print_names.cpp   |  25 --
 .../PEGTL/src/example/pegtl/peg2pegtl.cpp     |  12 +-
 packages/PEGTL/src/example/pegtl/proto3.cpp   |  98 ++++---
 .../PEGTL/src/test/pegtl/contrib_analyze.cpp  |   1 +
 .../src/test/pegtl/contrib_control_action.cpp |   8 +-
 .../PEGTL/src/test/pegtl/contrib_if_then.cpp  |   2 +-
 .../PEGTL/src/test/pegtl/contrib_integer.cpp  |  65 ++---
 packages/PEGTL/src/test/pegtl/contrib_uri.cpp |  36 +--
 .../PEGTL/src/test/pegtl/error_message.cpp    |  12 +-
 .../src/test/pegtl/internal_file_mapper.cpp   |   4 +-
 .../src/test/pegtl/internal_file_opener.cpp   |   2 +-
 packages/PEGTL/src/test/pegtl/rule_apply.cpp  |   2 +-
 packages/PEGTL/src/test/pegtl/rule_apply0.cpp |   2 +-
 .../PEGTL/src/test/pegtl/rule_if_apply.cpp    |   2 +-
 packages/PEGTL/src/test/pegtl/verify_impl.hpp |   2 +-
 49 files changed, 652 insertions(+), 535 deletions(-)
 create mode 100644 packages/PEGTL/include/tao/pegtl/contrib/add_state.hpp
 delete mode 100644 packages/PEGTL/src/example/pegtl/lua53_print_debug.cpp
 delete mode 100644 packages/PEGTL/src/example/pegtl/lua53_print_names.cpp

diff --git a/packages/PEGTL/.github/workflows/android.yml b/packages/PEGTL/.github/workflows/android.yml
index 8cf72544e..44515ed7c 100644
--- a/packages/PEGTL/.github/workflows/android.yml
+++ b/packages/PEGTL/.github/workflows/android.yml
@@ -1,6 +1,14 @@
 name: Android
 
-on: [push, pull_request]
+on:
+  push:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
+  pull_request:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
 
 jobs:
   android:
diff --git a/packages/PEGTL/.github/workflows/clang-analyze.yml b/packages/PEGTL/.github/workflows/clang-analyze.yml
index 523b10556..3919398d2 100644
--- a/packages/PEGTL/.github/workflows/clang-analyze.yml
+++ b/packages/PEGTL/.github/workflows/clang-analyze.yml
@@ -1,6 +1,14 @@
 name: clang-analyze
 
-on: [push, pull_request]
+on:
+  push:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
+  pull_request:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
 
 jobs:
   clang-analyze:
@@ -9,6 +17,8 @@ jobs:
     steps:
     - uses: actions/checkout@v2
 
+    - run: sudo apt-get update -yq
+
     - run: sudo apt-get install -yq clang-tools
 
     - run: scan-build cmake -E make_directory build
diff --git a/packages/PEGTL/.github/workflows/clang-format.yml b/packages/PEGTL/.github/workflows/clang-format.yml
index ac69e2ed6..a6aae1ae7 100644
--- a/packages/PEGTL/.github/workflows/clang-format.yml
+++ b/packages/PEGTL/.github/workflows/clang-format.yml
@@ -1,6 +1,14 @@
 name: clang-format
 
-on: [push, pull_request]
+on:
+  push:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
+  pull_request:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
 
 jobs:
   clang-format:
@@ -8,7 +16,7 @@ jobs:
 
     steps:
     - uses: actions/checkout@v2
-    - uses: DoozyX/clang-format-lint-action@v0.11
+    - uses: DoozyX/clang-format-lint-action@v0.12
       with:
         extensions: 'hpp,cpp'
-        clangFormatVersion: 11
+        clangFormatVersion: 12
diff --git a/packages/PEGTL/.github/workflows/clang-tidy.yml b/packages/PEGTL/.github/workflows/clang-tidy.yml
index 4da8af6ff..6f640820a 100644
--- a/packages/PEGTL/.github/workflows/clang-tidy.yml
+++ b/packages/PEGTL/.github/workflows/clang-tidy.yml
@@ -1,6 +1,14 @@
 name: clang-tidy
 
-on: [push, pull_request]
+on:
+  push:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
+  pull_request:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
 
 jobs:
   clang-tidy:
@@ -9,6 +17,8 @@ jobs:
     steps:
     - uses: actions/checkout@v2
 
+    - run: sudo apt-get update -yq
+
     - run: sudo apt-get install -yq clang-tidy
 
     - run: find include/ -name '*.hpp' | grep -vF file_mapper_win32.hpp | grep -vF endian_win.hpp | xargs -I '{}' clang-tidy --quiet '{}' -- --std=c++17 -Iinclude
diff --git a/packages/PEGTL/.github/workflows/code-coverage.yml b/packages/PEGTL/.github/workflows/code-coverage.yml
index 320e77d8c..537752ad0 100644
--- a/packages/PEGTL/.github/workflows/code-coverage.yml
+++ b/packages/PEGTL/.github/workflows/code-coverage.yml
@@ -1,6 +1,14 @@
 name: Code Coverage
 
-on: [push, pull_request]
+on:
+  push:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
+  pull_request:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
 
 jobs:
   code-coverage:
diff --git a/packages/PEGTL/.github/workflows/codeql-analysis.yml b/packages/PEGTL/.github/workflows/codeql-analysis.yml
index a2d930ad8..d0f90dfac 100644
--- a/packages/PEGTL/.github/workflows/codeql-analysis.yml
+++ b/packages/PEGTL/.github/workflows/codeql-analysis.yml
@@ -13,10 +13,16 @@ name: "CodeQL"
 
 on:
   push:
-    branches: [ master ]
+    branches: [ main ]
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
   pull_request:
     # The branches below must be a subset of the branches above
-    branches: [ master ]
+    branches: [ main ]
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
   schedule:
     - cron: '31 6 * * 0'
 
diff --git a/packages/PEGTL/.github/workflows/linux.yml b/packages/PEGTL/.github/workflows/linux.yml
index 139982af1..d6f6d6ef7 100644
--- a/packages/PEGTL/.github/workflows/linux.yml
+++ b/packages/PEGTL/.github/workflows/linux.yml
@@ -1,6 +1,14 @@
 name: Linux
 
-on: [push, pull_request]
+on:
+  push:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
+  pull_request:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
 
 jobs:
   linux:
@@ -10,9 +18,10 @@ jobs:
         compiler:
           - g++-9
           - g++-10
-          - clang++-9
+          #- g++-11
           - clang++-10
           - clang++-11
+          - clang++-12
         build_type: [Debug, Release]
 
     runs-on: ubuntu-latest
@@ -44,6 +53,7 @@ jobs:
           - clang++-6.0
           - clang++-7
           - clang++-8
+          - clang++-9
         build_type: [Debug, Release]
 
     runs-on: ubuntu-latest
@@ -54,9 +64,9 @@ jobs:
     steps:
     - uses: actions/checkout@v2
 
-    - run: sudo apt-get update
+    - run: sudo apt-get update -yq
 
-    - run: sudo apt-get install -y ${{ matrix.compiler }}
+    - run: sudo apt-get install -yq ${{ matrix.compiler }}
 
     - run: cmake -E make_directory build
 
diff --git a/packages/PEGTL/.github/workflows/macos.yml b/packages/PEGTL/.github/workflows/macos.yml
index 78c479511..a2dfade49 100644
--- a/packages/PEGTL/.github/workflows/macos.yml
+++ b/packages/PEGTL/.github/workflows/macos.yml
@@ -1,6 +1,14 @@
 name: macOS
 
-on: [push, pull_request]
+on:
+  push:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
+  pull_request:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
 
 jobs:
   xcode:
diff --git a/packages/PEGTL/.github/workflows/no-exceptions.yml b/packages/PEGTL/.github/workflows/no-exceptions.yml
index eeb964f25..25c49e0c5 100644
--- a/packages/PEGTL/.github/workflows/no-exceptions.yml
+++ b/packages/PEGTL/.github/workflows/no-exceptions.yml
@@ -1,6 +1,14 @@
 name: No-Exceptions
 
-on: [push, pull_request]
+on:
+  push:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
+  pull_request:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
 
 jobs:
   no-exceptions:
diff --git a/packages/PEGTL/.github/workflows/sanitizer.yml b/packages/PEGTL/.github/workflows/sanitizer.yml
index 61d61aebd..5bcb8a9b0 100644
--- a/packages/PEGTL/.github/workflows/sanitizer.yml
+++ b/packages/PEGTL/.github/workflows/sanitizer.yml
@@ -1,6 +1,14 @@
 name: Sanitizer
 
-on: [push, pull_request]
+on:
+  push:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
+  pull_request:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
 
 jobs:
   sanitizer:
diff --git a/packages/PEGTL/.github/workflows/windows.yml b/packages/PEGTL/.github/workflows/windows.yml
index 760efb9c8..e47498485 100644
--- a/packages/PEGTL/.github/workflows/windows.yml
+++ b/packages/PEGTL/.github/workflows/windows.yml
@@ -1,6 +1,14 @@
 name: Windows
 
-on: [push, pull_request]
+on:
+  push:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
+  pull_request:
+    paths-ignore:
+      - 'README.md'
+      - 'doc/**'
 
 jobs:
   vs2019:
diff --git a/packages/PEGTL/.gitrepo b/packages/PEGTL/.gitrepo
index d60e16e83..873dce466 100644
--- a/packages/PEGTL/.gitrepo
+++ b/packages/PEGTL/.gitrepo
@@ -5,8 +5,8 @@
 ;
 [subrepo]
 	remote = git@github.com:taocpp/PEGTL.git
-	branch = master
-	commit = c131c2e2aad67037285ef39d11ec4f1d28d4fc73
-	parent = 2f2fa0e22bd114f44f78c5bee89bc13bd0959d1d
+	branch = main
+	commit = fbfebc50d0b84a1fcd40e083a6e630fe815e21a7
+	parent = 8bade9551beef13a194e250386ff539c38cef805
 	method = merge
 	cmdver = 0.4.3
diff --git a/packages/PEGTL/README.md b/packages/PEGTL/README.md
index e613c97f9..0ee9ddfe6 100644
--- a/packages/PEGTL/README.md
+++ b/packages/PEGTL/README.md
@@ -9,7 +9,7 @@
 [![clang-tidy](https://github.com/taocpp/PEGTL/workflows/clang-tidy/badge.svg)](https://github.com/taocpp/PEGTL/actions?query=workflow%3Aclang-tidy)
 [![Sanitizer](https://github.com/taocpp/PEGTL/workflows/Sanitizer/badge.svg)](https://github.com/taocpp/PEGTL/actions?query=workflow%3ASanitizer)
 [![CodeQL](https://github.com/taocpp/PEGTL/workflows/CodeQL/badge.svg)](https://github.com/taocpp/PEGTL/actions?query=workflow%3ACodeQL)
-[![Code Coverage](https://codecov.io/gh/taocpp/PEGTL/branch/master/graph/badge.svg?token=ykWa8RRdyk)](https://codecov.io/gh/taocpp/PEGTL)
+[![Code Coverage](https://codecov.io/gh/taocpp/PEGTL/branch/main/graph/badge.svg?token=ykWa8RRdyk)](https://codecov.io/gh/taocpp/PEGTL)
 
 The Parsing Expression Grammar Template Library (PEGTL) is a zero-dependency C++ header-only parser combinator library for creating parsers according to a [Parsing Expression Grammar](http://en.wikipedia.org/wiki/Parsing_expression_grammar) (PEG).
 
diff --git a/packages/PEGTL/doc/Changelog.md b/packages/PEGTL/doc/Changelog.md
index cc194318f..eed13ec42 100644
--- a/packages/PEGTL/doc/Changelog.md
+++ b/packages/PEGTL/doc/Changelog.md
@@ -2,9 +2,11 @@
 
 ## 3.2.1
 
-**Not yet released**
+Released 2021-07-31
 
 * Added an optional limiter to guard against infinite recursion.
+* Fixed CMake export error.
+* Improved compile time efficiency.
 
 ## 3.2.0
 
diff --git a/packages/PEGTL/doc/Contrib-and-Examples.md b/packages/PEGTL/doc/Contrib-and-Examples.md
index 92c4032a2..f5b658e75 100644
--- a/packages/PEGTL/doc/Contrib-and-Examples.md
+++ b/packages/PEGTL/doc/Contrib-and-Examples.md
@@ -40,6 +40,12 @@ For all questions and remarks contact us at **taocpp(at)icemx.net**.
 
 * Grammars and actions for PEGTL-input-to-integer conversions.
 
+###### `<tao/pegtl/contrib/limit_depth.hpp>`
+
+* Limits the nesting level of rules when parsing a grammar, prevents stack overflows.
+* Can be applied selectively at specific rules to improve efficiency.
+* See `src/test/pegtl/limit_depth.cpp`.
+
 ###### `<tao/pegtl/contrib/json.hpp>`
 
 * JSON grammar according to [RFC 7159](https://tools.ietf.org/html/rfc7159) (for UTF-8 encoded JSON only).
diff --git a/packages/PEGTL/doc/Installing-and-Using.md b/packages/PEGTL/doc/Installing-and-Using.md
index e235edfba..f2e56051d 100644
--- a/packages/PEGTL/doc/Installing-and-Using.md
+++ b/packages/PEGTL/doc/Installing-and-Using.md
@@ -115,8 +115,6 @@ For more options and ways to use Vcpkg, please refer to the [Vcpkg documentation
 
 ## Using Conan
 
-[![Download](https://api.bintray.com/packages/conan/conan-center/taocpp-pegtl%3A_/images/download.svg)](https://bintray.com/conan/conan-center/taocpp-pegtl%3A_/_latestVersion)
-
 You can download and install the PEGTL using the [Conan] package manager:
 
 ```bash
diff --git a/packages/PEGTL/doc/Parse-Tree.md b/packages/PEGTL/doc/Parse-Tree.md
index baa3b24a7..8e668f9f8 100644
--- a/packages/PEGTL/doc/Parse-Tree.md
+++ b/packages/PEGTL/doc/Parse-Tree.md
@@ -94,7 +94,7 @@ template<> struct my_selector< my_rule_2 > : std::true_type
 };
 ```
 
-`transform` can modify `n` in any way you like, the [`parse_tree.cpp`](https://github.com/taocpp/PEGTL/blob/master/src/example/pegtl/parse_tree.cpp)-example shows two techniques for marking nodes as "content-less", and for transforming the parse tree into an AST.
+`transform` can modify `n` in any way you like, the [`parse_tree.cpp`](https://github.com/taocpp/PEGTL/blob/main/src/example/pegtl/parse_tree.cpp)-example shows two techniques for marking nodes as "content-less", and for transforming the parse tree into an AST.
 
 It is also possible to call `n.reset()`, or otherwise set `n` to an empty pointer, which effectively removes `n` (and all of its child nodes) from the parse tree.
 
@@ -185,7 +185,7 @@ struct node : basic_node< node > {};
 
 The name is the demangled name of the rule. By default, all nodes (except the root node) can provide the content that matched, i.e. the part of the input that the rule the node was created for matched. It is only necessary to check `has_content()` when `remove_content()` was used by a transform function (either directly or indirectly via one of the convenience helpers), otherwise all nodes except for the root will always "have content".
 
-See [`parse_tree.cpp`](https://github.com/taocpp/PEGTL/blob/master/src/example/pegtl/parse_tree.cpp) for more information on how to output (or otherwise use) the nodes.
+See [`parse_tree.cpp`](https://github.com/taocpp/PEGTL/blob/main/src/example/pegtl/parse_tree.cpp) for more information on how to output (or otherwise use) the nodes.
 
 ## Custom Node Class
 
diff --git a/packages/PEGTL/include/tao/pegtl/argv_input.hpp b/packages/PEGTL/include/tao/pegtl/argv_input.hpp
index 06cbc74cd..89eb3d024 100644
--- a/packages/PEGTL/include/tao/pegtl/argv_input.hpp
+++ b/packages/PEGTL/include/tao/pegtl/argv_input.hpp
@@ -20,9 +20,9 @@ namespace TAO_PEGTL_NAMESPACE
    {
       [[nodiscard]] inline std::string make_argv_source( const std::size_t argn )
       {
-         std::ostringstream os;
-         os << "argv[" << argn << ']';
-         return os.str();
+         std::ostringstream oss;
+         oss << "argv[" << argn << ']';
+         return std::move( oss ).str();
       }
 
    }  // namespace internal
diff --git a/packages/PEGTL/include/tao/pegtl/buffer_input.hpp b/packages/PEGTL/include/tao/pegtl/buffer_input.hpp
index 60d39d349..0a0ea7494 100644
--- a/packages/PEGTL/include/tao/pegtl/buffer_input.hpp
+++ b/packages/PEGTL/include/tao/pegtl/buffer_input.hpp
@@ -160,7 +160,7 @@ namespace TAO_PEGTL_NAMESPACE
             std::terminate();
 #endif
          }
-         if( const auto r = m_reader( m_end, ( std::min )( buffer_free_after_end(), ( std::max )( amount - buffer_occupied(), Chunk ) ) ) ) {
+         if( const auto r = m_reader( m_end, (std::min)( buffer_free_after_end(), (std::max)( amount - buffer_occupied(), Chunk ) ) ) ) {
             m_end += r;
          }
       }
diff --git a/packages/PEGTL/include/tao/pegtl/change_action_and_state.hpp b/packages/PEGTL/include/tao/pegtl/change_action_and_state.hpp
index f226c71ee..fb67181e1 100644
--- a/packages/PEGTL/include/tao/pegtl/change_action_and_state.hpp
+++ b/packages/PEGTL/include/tao/pegtl/change_action_and_state.hpp
@@ -12,6 +12,8 @@
 #include "nothing.hpp"
 #include "rewind_mode.hpp"
 
+#include "internal/dependent_false.hpp"
+
 namespace TAO_PEGTL_NAMESPACE
 {
    template< template< typename... > class NewAction, typename NewState >
@@ -30,14 +32,30 @@ namespace TAO_PEGTL_NAMESPACE
       [[nodiscard]] static bool match( ParseInput& in, States&&... st )
       {
          static_assert( !std::is_same_v< Action< void >, NewAction< void > >, "old and new action class templates are identical" );
-         NewState s( static_cast< const ParseInput& >( in ), st... );
-         if( Control< Rule >::template match< A, M, NewAction, Control >( in, s ) ) {
-            if constexpr( A == apply_mode::action ) {
-               Action< Rule >::success( static_cast< const ParseInput& >( in ), s, st... );
+
+         if constexpr( std::is_constructible_v< NewState, const ParseInput&, States... > ) {
+            NewState s( static_cast< const ParseInput& >( in ), st... );
+            if( Control< Rule >::template match< A, M, NewAction, Control >( in, s ) ) {
+               if constexpr( A == apply_mode::action ) {
+                  Action< Rule >::success( static_cast< const ParseInput& >( in ), s, st... );
+               }
+               return true;
             }
-            return true;
+            return false;
+         }
+         else if constexpr( std::is_default_constructible_v< NewState > ) {
+            NewState s;
+            if( Control< Rule >::template match< A, M, NewAction, Control >( in, s ) ) {
+               if constexpr( A == apply_mode::action ) {
+                  Action< Rule >::success( static_cast< const ParseInput& >( in ), s, st... );
+               }
+               return true;
+            }
+            return false;
+         }
+         else {
+            static_assert( internal::dependent_false< NewState >, "unable to instantiate new state" );
          }
-         return false;
       }
 
       template< typename ParseInput,
diff --git a/packages/PEGTL/include/tao/pegtl/change_state.hpp b/packages/PEGTL/include/tao/pegtl/change_state.hpp
index bb1007979..9169c078f 100644
--- a/packages/PEGTL/include/tao/pegtl/change_state.hpp
+++ b/packages/PEGTL/include/tao/pegtl/change_state.hpp
@@ -4,12 +4,16 @@
 #ifndef TAO_PEGTL_CHANGE_STATE_HPP
 #define TAO_PEGTL_CHANGE_STATE_HPP
 
+#include <type_traits>
+
 #include "apply_mode.hpp"
 #include "config.hpp"
 #include "match.hpp"
 #include "nothing.hpp"
 #include "rewind_mode.hpp"
 
+#include "internal/dependent_false.hpp"
+
 namespace TAO_PEGTL_NAMESPACE
 {
    template< typename NewState >
@@ -27,14 +31,29 @@ namespace TAO_PEGTL_NAMESPACE
                 typename... States >
       [[nodiscard]] static bool match( ParseInput& in, States&&... st )
       {
-         NewState s( static_cast< const ParseInput& >( in ), st... );
-         if( TAO_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, s ) ) {
-            if constexpr( A == apply_mode::action ) {
-               Action< Rule >::success( static_cast< const ParseInput& >( in ), s, st... );
+         if constexpr( std::is_constructible_v< NewState, const ParseInput&, States... > ) {
+            NewState s( static_cast< const ParseInput& >( in ), st... );
+            if( TAO_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, s ) ) {
+               if constexpr( A == apply_mode::action ) {
+                  Action< Rule >::success( static_cast< const ParseInput& >( in ), s, st... );
+               }
+               return true;
             }
-            return true;
+            return false;
+         }
+         else if constexpr( std::is_default_constructible_v< NewState > ) {
+            NewState s;
+            if( TAO_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, s ) ) {
+               if constexpr( A == apply_mode::action ) {
+                  Action< Rule >::success( static_cast< const ParseInput& >( in ), s, st... );
+               }
+               return true;
+            }
+            return false;
+         }
+         else {
+            static_assert( internal::dependent_false< NewState >, "unable to instantiate new state" );
          }
-         return false;
       }
 
       template< typename ParseInput,
diff --git a/packages/PEGTL/include/tao/pegtl/contrib/add_state.hpp b/packages/PEGTL/include/tao/pegtl/contrib/add_state.hpp
new file mode 100644
index 000000000..fc3c46fbf
--- /dev/null
+++ b/packages/PEGTL/include/tao/pegtl/contrib/add_state.hpp
@@ -0,0 +1,69 @@
+// Copyright (c) 2021 Dr. Colin Hirsch and Daniel Frey
+// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
+
+#ifndef TAO_PEGTL_CONTRIB_ADD_STATE_HPP
+#define TAO_PEGTL_CONTRIB_ADD_STATE_HPP
+
+#include <type_traits>
+
+#include "../apply_mode.hpp"
+#include "../config.hpp"
+#include "../match.hpp"
+#include "../nothing.hpp"
+#include "../rewind_mode.hpp"
+
+#include "../internal/dependent_false.hpp"
+
+namespace TAO_PEGTL_NAMESPACE
+{
+   template< typename AddState >
+   struct add_state
+      : maybe_nothing
+   {
+      template< typename Rule,
+                apply_mode A,
+                rewind_mode M,
+                template< typename... >
+                class Action,
+                template< typename... >
+                class Control,
+                typename ParseInput,
+                typename... States >
+      [[nodiscard]] static bool match( ParseInput& in, States&&... st )
+      {
+         if constexpr( std::is_constructible_v< AddState, const ParseInput&, States... > ) {
+            AddState s( static_cast< const ParseInput& >( in ), st... );
+            if( TAO_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, s, st... ) ) {
+               if constexpr( A == apply_mode::action ) {
+                  Action< Rule >::success( static_cast< const ParseInput& >( in ), s, st... );
+               }
+               return true;
+            }
+            return false;
+         }
+         else if constexpr( std::is_default_constructible_v< AddState > ) {
+            AddState s;
+            if( TAO_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, s, st... ) ) {
+               if constexpr( A == apply_mode::action ) {
+                  Action< Rule >::success( static_cast< const ParseInput& >( in ), s, st... );
+               }
+               return true;
+            }
+            return false;
+         }
+         else {
+            static_assert( internal::dependent_false< AddState >, "unable to instantiate new state" );
+         }
+      }
+
+      template< typename ParseInput,
+                typename... States >
+      static void success( const ParseInput& in, AddState& s, States&&... st ) noexcept( noexcept( s.success( in, st... ) ) )
+      {
+         s.success( in, st... );
+      }
+   };
+
+}  // namespace TAO_PEGTL_NAMESPACE
+
+#endif
diff --git a/packages/PEGTL/include/tao/pegtl/contrib/analyze.hpp b/packages/PEGTL/include/tao/pegtl/contrib/analyze.hpp
index 0bfbd18c2..17c2a58df 100644
--- a/packages/PEGTL/include/tao/pegtl/contrib/analyze.hpp
+++ b/packages/PEGTL/include/tao/pegtl/contrib/analyze.hpp
@@ -132,7 +132,7 @@ namespace TAO_PEGTL_NAMESPACE
                      }
                   }
                }
-               // LCOV_EXCL_END
+               // LCOV_EXCL_STOP
             }
             return accum;
          }
diff --git a/packages/PEGTL/include/tao/pegtl/contrib/http.hpp b/packages/PEGTL/include/tao/pegtl/contrib/http.hpp
index a1375aa9e..1755f5469 100644
--- a/packages/PEGTL/include/tao/pegtl/contrib/http.hpp
+++ b/packages/PEGTL/include/tao/pegtl/contrib/http.hpp
@@ -126,8 +126,8 @@ namespace TAO_PEGTL_NAMESPACE::http
    struct https_URI : if_must< istring< 'h', 't', 't', 'p', 's', ':', '/', '/' >, uri::authority, uri::path_abempty, uri::opt_query, uri::opt_fragment > {};
 
    struct partial_URI : seq< uri::relative_part, uri::opt_query > {};
-
    // clang-format on
+
    struct chunk_size
    {
       using rule_t = plus< abnf::HEXDIG >::rule_t;
@@ -170,13 +170,13 @@ namespace TAO_PEGTL_NAMESPACE::http
          return i > 0;
       }
    };
-   // clang-format off
 
+   // clang-format off
    struct chunk_ext_name : token {};
    struct chunk_ext_val : sor< quoted_string, token > {};
    struct chunk_ext : star_must< one< ';' >, chunk_ext_name, if_must< one< '=' >, chunk_ext_val > > {};
-
    // clang-format on
+
    struct chunk_data
    {
       using rule_t = star< abnf::OCTET >::rule_t;
diff --git a/packages/PEGTL/include/tao/pegtl/contrib/integer.hpp b/packages/PEGTL/include/tao/pegtl/contrib/integer.hpp
index f859662bf..b8edf793c 100644
--- a/packages/PEGTL/include/tao/pegtl/contrib/integer.hpp
+++ b/packages/PEGTL/include/tao/pegtl/contrib/integer.hpp
@@ -66,7 +66,7 @@ namespace TAO_PEGTL_NAMESPACE
          return ( '0' <= c ) && ( c <= '9' );
       }
 
-      template< typename Integer, Integer Maximum = ( std::numeric_limits< Integer >::max )() >
+      template< typename Integer, Integer Maximum = (std::numeric_limits< Integer >::max)() >
       [[nodiscard]] constexpr bool accumulate_digit( Integer& result, const char digit ) noexcept
       {
          // Assumes that digit is a digit as per is_digit(); returns false on overflow.
@@ -86,7 +86,7 @@ namespace TAO_PEGTL_NAMESPACE
          return true;
       }
 
-      template< typename Integer, Integer Maximum = ( std::numeric_limits< Integer >::max )() >
+      template< typename Integer, Integer Maximum = (std::numeric_limits< Integer >::max)() >
       [[nodiscard]] constexpr bool accumulate_digits( Integer& result, const std::string_view input ) noexcept
       {
          // Assumes input is a non-empty sequence of digits; returns false on overflow.
@@ -99,7 +99,7 @@ namespace TAO_PEGTL_NAMESPACE
          return true;
       }
 
-      template< typename Integer, Integer Maximum = ( std::numeric_limits< Integer >::max )() >
+      template< typename Integer, Integer Maximum = (std::numeric_limits< Integer >::max)() >
       [[nodiscard]] constexpr bool convert_positive( Integer& result, const std::string_view input ) noexcept
       {
          // Assumes result == 0 and that input is a non-empty sequence of digits; returns false on overflow.
@@ -115,7 +115,7 @@ namespace TAO_PEGTL_NAMESPACE
 
          static_assert( std::is_signed_v< Signed > );
          using Unsigned = std::make_unsigned_t< Signed >;
-         constexpr Unsigned maximum = static_cast< Unsigned >( ( std::numeric_limits< Signed >::max )() ) + 1;
+         constexpr Unsigned maximum = static_cast< Unsigned >( (std::numeric_limits< Signed >::max)() ) + 1;
          Unsigned temporary = 0;
          if( accumulate_digits< Unsigned, maximum >( temporary, input ) ) {
             result = static_cast< Signed >( ~temporary ) + 1;
@@ -124,7 +124,7 @@ namespace TAO_PEGTL_NAMESPACE
          return false;
       }
 
-      template< typename Unsigned, Unsigned Maximum = ( std::numeric_limits< Unsigned >::max )() >
+      template< typename Unsigned, Unsigned Maximum = (std::numeric_limits< Unsigned >::max)() >
       [[nodiscard]] constexpr bool convert_unsigned( Unsigned& result, const std::string_view input ) noexcept
       {
          // Assumes result == 0 and that input is a non-empty sequence of digits; returns false on overflow.
@@ -167,8 +167,8 @@ namespace TAO_PEGTL_NAMESPACE
 
       template< typename ParseInput,
                 typename Unsigned,
-                Unsigned Maximum = ( std::numeric_limits< Unsigned >::max )() >
-      [[nodiscard]] bool match_and_convert_unsigned_with_maximum( ParseInput& in, Unsigned& st )
+                Unsigned Maximum = (std::numeric_limits< Unsigned >::max)() >
+      [[nodiscard]] bool match_and_convert_unsigned_with_maximum_throws( ParseInput& in, Unsigned& st )
       {
          // Assumes st == 0.
 
@@ -181,7 +181,7 @@ namespace TAO_PEGTL_NAMESPACE
                }
                do {
                   if( !accumulate_digit< Unsigned, Maximum >( st, c ) ) {
-                     throw TAO_PEGTL_NAMESPACE::parse_error( "integer overflow", in );  // Consistent with "as if" an action was doing the conversion.
+                     throw TAO_PEGTL_NAMESPACE::parse_error( "integer overflow", in );
                   }
                   in.bump_in_this_line();
                } while( ( !in.empty() ) && is_digit( c = in.peek_char() ) );
@@ -191,6 +191,38 @@ namespace TAO_PEGTL_NAMESPACE
          return false;
       }
 
+      template< typename ParseInput,
+                typename Unsigned,
+                Unsigned Maximum = (std::numeric_limits< Unsigned >::max)() >
+      [[nodiscard]] bool match_and_convert_unsigned_with_maximum_nothrow( ParseInput& in, Unsigned& st )
+      {
+         // Assumes st == 0.
+
+         if( !in.empty() ) {
+            char c = in.peek_char();
+            if( c == '0' ) {
+               if( ( in.size( 2 ) < 2 ) || ( !is_digit( in.peek_char( 1 ) ) ) ) {
+                  in.bump_in_this_line();
+                  return true;
+               }
+               return false;
+            }
+            if( is_digit( c ) ) {
+               unsigned b = 0;
+
+               do {
+                  if( !accumulate_digit< Unsigned, Maximum >( st, c ) ) {
+                     return false;
+                  }
+                  ++b;
+               } while( ( !in.empty() ) && is_digit( c = in.peek_char( b ) ) );
+               in.bump_in_this_line( b );
+               return true;
+            }
+         }
+         return false;
+      }
+
    }  // namespace internal
 
    struct unsigned_action
@@ -250,7 +282,7 @@ namespace TAO_PEGTL_NAMESPACE
       {
          // This function "only" offers basic exception safety.
          st = 0;
-         return internal::match_and_convert_unsigned_with_maximum( in, st );  // Throws on overflow.
+         return internal::match_and_convert_unsigned_with_maximum_throws( in, st );  // Throws on overflow.
       }
    };
 
@@ -272,7 +304,7 @@ namespace TAO_PEGTL_NAMESPACE
       }
    };
 
-   template< typename Unsigned, Unsigned Maximum = ( std::numeric_limits< Unsigned >::max )() >
+   template< typename Unsigned, Unsigned Maximum = (std::numeric_limits< Unsigned >::max)() >
    struct maximum_rule
    {
       using rule_t = maximum_rule;
@@ -284,11 +316,11 @@ namespace TAO_PEGTL_NAMESPACE
       [[nodiscard]] static bool match( ParseInput& in )
       {
          Unsigned st = 0;
-         return internal::match_and_convert_unsigned_with_maximum< ParseInput, Unsigned, Maximum >( in, st );  // Throws on overflow.
+         return internal::match_and_convert_unsigned_with_maximum_nothrow< ParseInput, Unsigned, Maximum >( in, st );
       }
    };
 
-   template< typename Unsigned, Unsigned Maximum = ( std::numeric_limits< Unsigned >::max )() >
+   template< typename Unsigned, Unsigned Maximum = (std::numeric_limits< Unsigned >::max)() >
    struct maximum_rule_with_action
    {
       using rule_t = maximum_rule_with_action;
@@ -307,7 +339,7 @@ namespace TAO_PEGTL_NAMESPACE
       [[nodiscard]] static auto match( ParseInput& in, States&&... /*unused*/ ) -> std::enable_if_t< A == apply_mode::nothing, bool >
       {
          Unsigned st = 0;
-         return internal::match_and_convert_unsigned_with_maximum< ParseInput, Unsigned, Maximum >( in, st );  // Throws on overflow.
+         return internal::match_and_convert_unsigned_with_maximum_throws< ParseInput, Unsigned, Maximum >( in, st );
       }
 
       template< apply_mode A,
@@ -322,7 +354,7 @@ namespace TAO_PEGTL_NAMESPACE
       {
          // This function "only" offers basic exception safety.
          st = 0;
-         return internal::match_and_convert_unsigned_with_maximum< ParseInput, Unsigned, Maximum >( in, st );  // Throws on overflow.
+         return internal::match_and_convert_unsigned_with_maximum_throws< ParseInput, Unsigned, Maximum >( in, st );
       }
    };
 
diff --git a/packages/PEGTL/include/tao/pegtl/contrib/peg.hpp b/packages/PEGTL/include/tao/pegtl/contrib/peg.hpp
index a921e372c..3c15c9b72 100644
--- a/packages/PEGTL/include/tao/pegtl/contrib/peg.hpp
+++ b/packages/PEGTL/include/tao/pegtl/contrib/peg.hpp
@@ -7,119 +7,115 @@
 
 #include <tao/pegtl.hpp>
 
-namespace TAO_PEGTL_NAMESPACE
+namespace TAO_PEGTL_NAMESPACE::peg
 {
-   namespace peg
+   // PEG grammar from https://pdos.csail.mit.edu/~baford/packrat/popl04/peg-popl04.pdf
+   namespace grammar
    {
-      // PEG grammar from https://pdos.csail.mit.edu/~baford/packrat/popl04/peg-popl04.pdf
-      namespace grammar
-      {
-         // clang-format off
-         struct AND;
-         struct Char;
-         struct Class;
-         struct CLOSE;
-         struct Comment;
-         struct Definition;
-         struct DOT;
-         struct EndOfFile;
-         struct EndOfLine;
-         struct Expression;
-         struct QUESTION;
-         struct IdentCont;
-         struct Identifier;
-         struct IdentStart;
-         struct LEFTARROW;
-         struct Literal;
-         struct NOT;
-         struct OPEN;
-         struct PLUS;
-         struct Prefix;
-         struct Primary;
-         struct Range;
-         struct Sequence;
-         struct SLASH;
-         struct Space;
-         struct Spacing;
-         struct STAR;
-         struct Suffix;
-
-         struct Grammar : seq< Spacing, plus< Definition >, EndOfFile > {};
-
-         struct Definition : seq< Identifier, LEFTARROW, Expression > {};
-         struct Expression : list< Sequence, SLASH > {};
-         struct Sequence : star< Prefix > {};
-
-         struct Prefix : seq< opt< sor< AND, NOT > >, Suffix > {};
-         struct Suffix : seq< Primary, opt< sor< QUESTION, STAR, PLUS > > > {};
-
-         struct Primary : sor<
-            seq< Identifier, not_at< LEFTARROW > >,
-            seq< OPEN, Expression, CLOSE >,
-            Literal,
-            Class,
-            DOT
-            > {};
-
-         struct Identifier : seq< IdentStart, star< IdentCont >, Spacing > {};
-
-         struct IdentStart : identifier_first {};
-
-         struct IdentCont : identifier_other {};
-
-         struct Literal : sor<
-            seq< one< '\'' >, until< one< '\'' >, Char >, Spacing >,
-            seq< one< '"' >, until< one< '"' >, Char >, Spacing >
-            > {};
-
-         struct Class : seq< one< '[' >, until< one< ']' >, Range >, Spacing > {};
-
-         struct Range : sor<
-            seq< Char, one< '-' >, Char >,
-            Char
-            > {};
-
-         struct Char : sor<
-            seq<
-               one< '\\' >,
-               one< 'n', 'r', 't', '\'', '"', '[', ']', '\\' > >,
-            seq<
-               one< '\\' >,
-               range< '0', '2' >,
-               range< '0', '7' >,
-               range< '0', '7' > >,
-            seq<
-               one< '\\' >,
-               range< '0','7' >,
-               opt< range< '0','7' > > >,
-            seq<
-               not_at< one< '\\' > >,
-               any >
-            > {};
-
-         struct LEFTARROW : seq< string< '<','-' >, Spacing > {};
-         struct SLASH : seq< one< '/' >, Spacing > {};
-         struct AND : seq< one< '&' >, Spacing > {};
-         struct NOT : seq< one< '!' >, Spacing > {};
-         struct QUESTION : seq< one< '?' >, Spacing > {};
-         struct STAR : seq< one< '*' >, Spacing > {};
-         struct PLUS : seq< one< '+' >, Spacing > {};
-         struct OPEN : seq< one< '(' >, Spacing > {};
-         struct CLOSE : seq< one< ')' >, Spacing > {};
-         struct DOT : seq< one< '.' >, Spacing > {};
-
-         struct Spacing : star< sor< Space, Comment > > {};
-         struct Comment : seq< one< '#' >, until< EndOfLine > > {};
-
-         struct Space : sor< one< ' ', '\t' >, EndOfLine > {};
-         struct EndOfLine : sor< string< '\r', '\n' >, one< '\n' >, one< '\r' > > {};
-         struct EndOfFile : eof {};
-         // clang-format on
-
-      }  // namespace grammar
-
-   }  // namespace peg
-
-}  // namespace TAO_PEGTL_NAMESPACE
+      // clang-format off
+      struct AND;
+      struct Char;
+      struct Class;
+      struct CLOSE;
+      struct Comment;
+      struct Definition;
+      struct DOT;
+      struct EndOfFile;
+      struct EndOfLine;
+      struct Expression;
+      struct QUESTION;
+      struct IdentCont;
+      struct Identifier;
+      struct IdentStart;
+      struct LEFTARROW;
+      struct Literal;
+      struct NOT;
+      struct OPEN;
+      struct PLUS;
+      struct Prefix;
+      struct Primary;
+      struct Range;
+      struct Sequence;
+      struct SLASH;
+      struct Space;
+      struct Spacing;
+      struct STAR;
+      struct Suffix;
+
+      struct Grammar : seq< Spacing, plus< Definition >, EndOfFile > {};
+
+      struct Definition : seq< Identifier, LEFTARROW, Expression > {};
+      struct Expression : list< Sequence, SLASH > {};
+      struct Sequence : star< Prefix > {};
+
+      struct Prefix : seq< opt< sor< AND, NOT > >, Suffix > {};
+      struct Suffix : seq< Primary, opt< sor< QUESTION, STAR, PLUS > > > {};
+
+      struct Primary : sor<
+         seq< Identifier, not_at< LEFTARROW > >,
+         seq< OPEN, Expression, CLOSE >,
+         Literal,
+         Class,
+         DOT
+         > {};
+
+      struct Identifier : seq< IdentStart, star< IdentCont >, Spacing > {};
+
+      struct IdentStart : identifier_first {};
+
+      struct IdentCont : identifier_other {};
+
+      struct Literal : sor<
+         seq< one< '\'' >, until< one< '\'' >, Char >, Spacing >,
+         seq< one< '"' >, until< one< '"' >, Char >, Spacing >
+         > {};
+
+      struct Class : seq< one< '[' >, until< one< ']' >, Range >, Spacing > {};
+
+      struct Range : sor<
+         seq< Char, one< '-' >, Char >,
+         Char
+         > {};
+
+      struct Char : sor<
+         seq<
+            one< '\\' >,
+            one< 'n', 'r', 't', '\'', '"', '[', ']', '\\' > >,
+         seq<
+            one< '\\' >,
+            range< '0', '2' >,
+            range< '0', '7' >,
+            range< '0', '7' > >,
+         seq<
+            one< '\\' >,
+            range< '0','7' >,
+            opt< range< '0','7' > > >,
+         seq<
+            not_at< one< '\\' > >,
+            any >
+         > {};
+
+      struct LEFTARROW : seq< string< '<','-' >, Spacing > {};
+      struct SLASH : seq< one< '/' >, Spacing > {};
+      struct AND : seq< one< '&' >, Spacing > {};
+      struct NOT : seq< one< '!' >, Spacing > {};
+      struct QUESTION : seq< one< '?' >, Spacing > {};
+      struct STAR : seq< one< '*' >, Spacing > {};
+      struct PLUS : seq< one< '+' >, Spacing > {};
+      struct OPEN : seq< one< '(' >, Spacing > {};
+      struct CLOSE : seq< one< ')' >, Spacing > {};
+      struct DOT : seq< one< '.' >, Spacing > {};
+
+      struct Spacing : star< sor< Space, Comment > > {};
+      struct Comment : seq< one< '#' >, until< EndOfLine > > {};
+
+      struct Space : sor< one< ' ', '\t' >, EndOfLine > {};
+      struct EndOfLine : sor< string< '\r', '\n' >, one< '\n' >, one< '\r' > > {};
+      struct EndOfFile : eof {};
+      // clang-format on
+
+   }  // namespace grammar
+
+}  // namespace TAO_PEGTL_NAMESPACE::peg
 
 #endif  // TAO_PEGTL_CONTRIB_PEG_HPP
diff --git a/packages/PEGTL/include/tao/pegtl/internal/file_mapper_posix.hpp b/packages/PEGTL/include/tao/pegtl/internal/file_mapper_posix.hpp
index 0c60e3a4a..68bb8f6d6 100644
--- a/packages/PEGTL/include/tao/pegtl/internal/file_mapper_posix.hpp
+++ b/packages/PEGTL/include/tao/pegtl/internal/file_mapper_posix.hpp
@@ -54,7 +54,7 @@ namespace TAO_PEGTL_NAMESPACE::internal
             std::perror( "fstat() failed" );
             std::terminate();
 #endif
-            // LCOV_EXCL_END
+            // LCOV_EXCL_STOP
          }
          return std::size_t( st.st_size );
       }
@@ -105,7 +105,7 @@ namespace TAO_PEGTL_NAMESPACE::internal
             std::perror( "mmap() failed" );
             std::terminate();
 #endif
-            // LCOV_EXCL_END
+            // LCOV_EXCL_STOP
          }
       }
 
diff --git a/packages/PEGTL/include/tao/pegtl/position.hpp b/packages/PEGTL/include/tao/pegtl/position.hpp
index 360816681..b4f1c3b26 100644
--- a/packages/PEGTL/include/tao/pegtl/position.hpp
+++ b/packages/PEGTL/include/tao/pegtl/position.hpp
@@ -88,9 +88,9 @@ namespace TAO_PEGTL_NAMESPACE
 
    [[nodiscard]] inline std::string to_string( const position& p )
    {
-      std::ostringstream o;
-      o << p;
-      return o.str();
+      std::ostringstream oss;
+      oss << p;
+      return std::move( oss ).str();
    }
 
 }  // namespace TAO_PEGTL_NAMESPACE
diff --git a/packages/PEGTL/src/example/pegtl/CMakeLists.txt b/packages/PEGTL/src/example/pegtl/CMakeLists.txt
index 64bb7380d..58e1f593b 100644
--- a/packages/PEGTL/src/example/pegtl/CMakeLists.txt
+++ b/packages/PEGTL/src/example/pegtl/CMakeLists.txt
@@ -22,8 +22,6 @@ set(example_sources
   json_trace.cpp
   lua53_analyze.cpp
   lua53_parse.cpp
-  lua53_print_debug.cpp
-  lua53_print_names.cpp
   modulus_match.cpp
   parse_tree.cpp
   parse_tree_user_state.cpp
diff --git a/packages/PEGTL/src/example/pegtl/abnf2pegtl.cpp b/packages/PEGTL/src/example/pegtl/abnf2pegtl.cpp
index 1a9b0d6b9..90ac59a51 100644
--- a/packages/PEGTL/src/example/pegtl/abnf2pegtl.cpp
+++ b/packages/PEGTL/src/example/pegtl/abnf2pegtl.cpp
@@ -313,10 +313,16 @@ namespace TAO_PEGTL_NAMESPACE
       template<> inline constexpr auto error_message< abnf::grammar::defined_as > = "expected '=' or '=/'";
       template<> inline constexpr auto error_message< abnf::grammar::req_c_nl > = "unterminated rule";
       template<> inline constexpr auto error_message< abnf::grammar::rule > = "expected rule";
-
-      struct error { template< typename Rule > static constexpr auto message = error_message< Rule >; };
-      template< typename Rule > using control = must_if< error >::control< Rule >;
       // clang-format on
+
+      struct error
+      {
+         template< typename Rule >
+         static constexpr auto message = error_message< Rule >;
+      };
+
+      template< typename Rule >
+      using control = must_if< error >::control< Rule >;
 #else
       template< typename Rule >
       using control = normal< Rule >;
@@ -629,9 +635,9 @@ namespace TAO_PEGTL_NAMESPACE
                v <<= 1;
                v |= ( *p++ & 1 );
             } while( p != n->m_end.data );
-            std::ostringstream o;
-            o << v;
-            return o.str();
+            std::ostringstream oss;
+            oss << v;
+            return std::move( oss ).str();
          } );
 
          nrv.add< grammar::hex_val::type >( []( const node_ptr& n ) { return gen_val< grammar::hex_val::range >( n ); } );
@@ -727,9 +733,9 @@ namespace TAO_PEGTL_NAMESPACE
             if( min_val == max_val ) {
                return min_element;
             }
-            std::ostringstream os;
-            os << ( max_val - min_val );
-            const auto max_element = prefix + ( ( max_val - min_val == 1 ) ? "opt< " : ( "rep_opt< " + os.str() + ", " ) ) + content + " >";
+            std::ostringstream oss;
+            oss << ( max_val - min_val );
+            const auto max_element = prefix + ( ( max_val - min_val == 1 ) ? "opt< " : ( "rep_opt< " + std::move( oss ).str() + ", " ) ) + content + " >";
             return prefix + "seq< " + min_element + ", " + max_element + " >";
          } );
 
diff --git a/packages/PEGTL/src/example/pegtl/expression.cpp b/packages/PEGTL/src/example/pegtl/expression.cpp
index 5d490f93f..030b0d6db 100644
--- a/packages/PEGTL/src/example/pegtl/expression.cpp
+++ b/packages/PEGTL/src/example/pegtl/expression.cpp
@@ -17,8 +17,6 @@ int main()
 #include <iomanip>
 #include <iostream>
 #include <stdexcept>
-#include <tuple>
-#include <variant>
 #include <vector>
 
 #include <tao/pegtl.hpp>
@@ -46,7 +44,7 @@ namespace TAO_PEGTL_NAMESPACE::expression
    {
       struct prefix_info
       {
-         prefix_info( const std::string_view n, const std::uint8_t pbp ) noexcept
+         prefix_info( const std::string_view n, const unsigned pbp ) noexcept
             : name( n ),
               prefix_binding_power( pbp )
          {
@@ -55,16 +53,16 @@ namespace TAO_PEGTL_NAMESPACE::expression
 
          std::string name;
 
-         std::uint8_t prefix_binding_power;
+         unsigned prefix_binding_power;
       };
 
       struct infix_postfix_info
       {
-         infix_postfix_info( const std::string_view n, const std::uint8_t lbp, const std::uint8_t rbp = 0 ) noexcept
+         infix_postfix_info( const std::string_view n, const unsigned lbp, const unsigned rbp = 0 ) noexcept
             : infix_postfix_info( n, std::string_view(), lbp, rbp )
          {}
 
-         infix_postfix_info( const std::string_view n, const std::string_view o, const std::uint8_t lbp, const std::uint8_t rbp = 0 ) noexcept
+         infix_postfix_info( const std::string_view n, const std::string_view o, const unsigned lbp, const unsigned rbp = 0 ) noexcept
             : name( n ),
               other( o ),
               left_binding_power( lbp ),
@@ -90,8 +88,8 @@ namespace TAO_PEGTL_NAMESPACE::expression
          std::string name;
          std::string other;  // Used for the ':' of the ternary operator etc.
 
-         std::uint8_t left_binding_power;
-         std::uint8_t right_binding_power;
+         unsigned left_binding_power;
+         unsigned right_binding_power;
       };
 
       template< typename ParseInput >
@@ -120,7 +118,7 @@ namespace TAO_PEGTL_NAMESPACE::expression
       }
 
       template< typename ParseInput, typename OperatorInfo >
-      [[nodiscard]] const OperatorInfo* match_infix_postfix( ParseInput& in, const std::size_t max_length, const std::vector< OperatorInfo >& ops, const std::uint8_t min_precedence )
+      [[nodiscard]] const OperatorInfo* match_infix_postfix( ParseInput& in, const std::size_t max_length, const std::vector< OperatorInfo >& ops, const unsigned min_precedence )
       {
          const std::size_t max = std::min( max_length, in.size( max_length ) );
          for( std::string op( in.current(), max ); !op.empty(); op.pop_back() ) {
@@ -143,68 +141,64 @@ namespace TAO_PEGTL_NAMESPACE::expression
 
       struct operator_maps
       {
-         // clang-format off
          operator_maps()
-            : prefix( sorted_operator_vector( {
-                  prefix_info( "!", 80 ),
-                  prefix_info( "+", 80 ),
-                  prefix_info( "-", 80 ),
-                  prefix_info( "~", 80 ),
-                  prefix_info( "*", 80 ),
-                  prefix_info( "&", 80 ),
-                  prefix_info( "++", 80 ),
-                  prefix_info( "--", 80 )
-               } ) ),
-              infix_postfix( sorted_operator_vector( {
-                  infix_postfix_info( "::", 99, 100 ),  // Special: Followed by identifier (or template-space-identifer, which we don't support yet).
-                  infix_postfix_info( ".*", 37, 38 ),
-                  infix_postfix_info( "->*", 37, 38 ),
-                  infix_postfix_info( "*", 35, 36 ),
-                  infix_postfix_info( "/", 35, 36 ),
-                  infix_postfix_info( "%", 35, 36 ),
-                  infix_postfix_info( "+", 33, 34 ),
-                  infix_postfix_info( "-", 33, 34 ),
-                  infix_postfix_info( "<<", 31, 32 ),
-                  infix_postfix_info( ">>", 31, 32 ),
-                  infix_postfix_info( "<=>", 29, 30 ),
-                  infix_postfix_info( "<", 27, 28 ),
-                  infix_postfix_info( "<=", 27, 28 ),
-                  infix_postfix_info( ">", 27, 28 ),
-                  infix_postfix_info( ">=", 27, 28 ),
-                  infix_postfix_info( "==", 25, 26 ),
-                  infix_postfix_info( "!=", 25, 26 ),
-                  infix_postfix_info( "&", 23, 24 ),
-                  infix_postfix_info( "^", 21, 22 ),
-                  infix_postfix_info( "|", 19, 20 ),
-                  infix_postfix_info( "&&", 17, 18 ),
-                  infix_postfix_info( "||", 15, 16 ),
-                  infix_postfix_info( "?", ":", 14, 13 ),  // Special: Ternary operator.
-                  infix_postfix_info( "=", 12, 11 ),
-                  infix_postfix_info( "+=", 12, 11 ),
-                  infix_postfix_info( "-=", 12, 11 ),
-                  infix_postfix_info( "*=", 12, 11 ),
-                  infix_postfix_info( "/=", 12, 11 ),
-                  infix_postfix_info( "%=", 12, 11 ),
-                  infix_postfix_info( "<<=", 12, 11 ),
-                  infix_postfix_info( ">>=", 12, 11 ),
-                  infix_postfix_info( "&=", 12, 11 ),
-                  infix_postfix_info( "^=", 12, 11 ),
-                  infix_postfix_info( "|=", 12, 11 ),
-                  // infix_postfix_info( ",", 9, 10 ),  // TODO: Enable, but forbid in function argument list.
-                  infix_postfix_info( "[", "]", 90 ),  // Special: Argument list.
-                  infix_postfix_info( "(", ")", 90 ),  // Special: Argument list.
-                  infix_postfix_info( ".", 90 ),  // Special: Followed by identifier.
-                  infix_postfix_info( "->", 90 ),  // Special: Followed by identifier.
-                  infix_postfix_info( "++", 90 ),
-                  infix_postfix_info( "--", 90 )
-               } ) ),
+            : prefix( sorted_operator_vector(
+               { prefix_info( "!", 80 ),
+                 prefix_info( "+", 80 ),
+                 prefix_info( "-", 80 ),
+                 prefix_info( "~", 80 ),
+                 prefix_info( "*", 80 ),
+                 prefix_info( "&", 80 ),
+                 prefix_info( "++", 80 ),
+                 prefix_info( "--", 80 ) } ) ),
+              infix_postfix( sorted_operator_vector(
+                 { infix_postfix_info( "::", 99, 100 ),  // Special: Followed by identifier (or template-space-identifer, which we don't support yet).
+                   infix_postfix_info( ".*", 37, 38 ),
+                   infix_postfix_info( "->*", 37, 38 ),
+                   infix_postfix_info( "*", 35, 36 ),
+                   infix_postfix_info( "/", 35, 36 ),
+                   infix_postfix_info( "%", 35, 36 ),
+                   infix_postfix_info( "+", 33, 34 ),
+                   infix_postfix_info( "-", 33, 34 ),
+                   infix_postfix_info( "<<", 31, 32 ),
+                   infix_postfix_info( ">>", 31, 32 ),
+                   infix_postfix_info( "<=>", 29, 30 ),
+                   infix_postfix_info( "<", 27, 28 ),
+                   infix_postfix_info( "<=", 27, 28 ),
+                   infix_postfix_info( ">", 27, 28 ),
+                   infix_postfix_info( ">=", 27, 28 ),
+                   infix_postfix_info( "==", 25, 26 ),
+                   infix_postfix_info( "!=", 25, 26 ),
+                   infix_postfix_info( "&", 23, 24 ),
+                   infix_postfix_info( "^", 21, 22 ),
+                   infix_postfix_info( "|", 19, 20 ),
+                   infix_postfix_info( "&&", 17, 18 ),
+                   infix_postfix_info( "||", 15, 16 ),
+                   infix_postfix_info( "?", ":", 14, 13 ),  // Special: Ternary operator.
+                   infix_postfix_info( "=", 12, 11 ),
+                   infix_postfix_info( "+=", 12, 11 ),
+                   infix_postfix_info( "-=", 12, 11 ),
+                   infix_postfix_info( "*=", 12, 11 ),
+                   infix_postfix_info( "/=", 12, 11 ),
+                   infix_postfix_info( "%=", 12, 11 ),
+                   infix_postfix_info( "<<=", 12, 11 ),
+                   infix_postfix_info( ">>=", 12, 11 ),
+                   infix_postfix_info( "&=", 12, 11 ),
+                   infix_postfix_info( "^=", 12, 11 ),
+                   infix_postfix_info( "|=", 12, 11 ),
+                   // infix_postfix_info( ",", 9, 10 ),  // TODO: Enable, but forbid in function argument list.
+                   infix_postfix_info( "[", "]", 90 ),  // Special: Argument list.
+                   infix_postfix_info( "(", ")", 90 ),  // Special: Argument list.
+                   infix_postfix_info( ".", 90 ),       // Special: Followed by identifier.
+                   infix_postfix_info( "->", 90 ),      // Special: Followed by identifier.
+                   infix_postfix_info( "++", 90 ),
+                   infix_postfix_info( "--", 90 ) } ) ),
               max_prefix_length( std::max_element( prefix.begin(), prefix.end(), []( const auto& l, const auto& r ) { return l.name.size() < r.name.size(); } )->name.size() ),
               max_infix_postfix_length( std::max_element( infix_postfix.begin(), infix_postfix.end(), []( const auto& l, const auto& r ) { return l.name.size() < r.name.size(); } )->name.size() )
          {
             // These are C++20 operators with the correct associativity and relative precedence, however some are still missing:
             // TODO: Compound literal (C99), _Alignof (C11), Functional cast, sizeof, co_await, co_yield, throw, new, new[], delete, delete[], C-style casts.
          }
-         // clang-format on
 
          const std::vector< prefix_info > prefix;
          const std::vector< infix_postfix_info > infix_postfix;
@@ -251,7 +245,7 @@ namespace TAO_PEGTL_NAMESPACE::expression
                    typename ParseInput,
                    typename Result,
                    typename Config >
-         [[nodiscard]] static bool match( ParseInput& in, Result& res, const Config& cfg, const std::uint8_t /*unused*/ )
+         [[nodiscard]] static bool match( ParseInput& in, Result& res, const Config& cfg, const unsigned /*unused*/ )
          {
             return Control< if_must< one< '(' >, star< ignored >, expression< Literal, Identifier >, star< ignored >, one< ')' > > >::template match< A, M, Action, Control >( in, res, cfg, 0 );
          }
@@ -269,7 +263,7 @@ namespace TAO_PEGTL_NAMESPACE::expression
                    typename ParseInput,
                    typename Result,
                    typename Config >
-         [[nodiscard]] static bool match( ParseInput& in, Result& res, const Config& cfg, const std::uint8_t /*unused*/ )
+         [[nodiscard]] static bool match( ParseInput& in, Result& res, const Config& cfg, const unsigned /*unused*/ )
          {
             if( const auto* info = match_prefix( in, cfg.max_prefix_length, cfg.prefix ) ) {
                (void)Control< must< star< ignored >, expression< Literal, Identifier > > >::template match< A, M, Action, Control >( in, res, cfg, info->prefix_binding_power );
@@ -294,7 +288,7 @@ namespace TAO_PEGTL_NAMESPACE::expression
                    typename ParseInput,
                    typename Result,
                    typename Config >
-         [[nodiscard]] static bool match( ParseInput& in, Result& res, const Config& cfg, const std::uint8_t min )
+         [[nodiscard]] static bool match( ParseInput& in, Result& res, const Config& cfg, const unsigned min )
          {
             if( const auto* info = match_infix_postfix( in, cfg.max_infix_postfix_length, cfg.infix_postfix, min ) ) {
                if( info->name == "?" ) {
@@ -314,11 +308,11 @@ namespace TAO_PEGTL_NAMESPACE::expression
                   return true;
                }
                if( ( info->name == "(" ) || ( info->name == "[" ) ) {
-                  const std::size_t size = res.term_stack.size();  // TODO: Determine number of arguments without relying on res!?
+                  const std::size_t size = res.string_stack.size();  // TODO: Determine number of arguments without relying on res!!!
                   (void)Control< must< star< ignored >, opt< list_must< expression< Literal, Identifier >, one< ',' >, ignored > > > >::template match< A, M, Action, Control >( in, res, cfg, 0 );
                   (void)Control< must< star< ignored >, string_view_rule > >::template match< A, M, Action, Control >( in, info->other );
                   if constexpr( A == apply_mode::action ) {
-                     res.call( info->name, info->other, res.term_stack.size() - size );
+                     res.call( info->name, info->other, res.string_stack.size() - size );
                   }
                   return true;
                }
@@ -393,28 +387,6 @@ namespace application
 {
    namespace pegtl = TAO_PEGTL_NAMESPACE;
 
-   struct term_t;
-
-   using tuple_t = std::tuple< std::string, std::vector< term_t > >;
-   using variant_t = std::variant< std::int64_t, std::string, tuple_t >;
-
-   struct term_t
-   {
-      explicit term_t( const std::int64_t l ) noexcept
-         : variant( l )
-      {}
-
-      explicit term_t( std::string&& s ) noexcept
-         : variant( std::move( s ) )
-      {}
-
-      explicit term_t( variant_t&& v ) noexcept
-         : variant( std::move( v ) )
-      {}
-
-      variant_t variant;
-   };
-
    [[nodiscard]] inline std::string operator+( const char* l, const std::string_view r )
    {
       return std::string( l ) + " '" + std::string( r ) + "'";
@@ -424,131 +396,68 @@ namespace application
    {
       void infix( const std::string_view op )
       {
-         assert( term_stack.size() >= 2 );
-         {
-            variant_t tmp = tuple_t( "infix" + op, { std::move( term_stack.at( term_stack.size() - 2 ) ), std::move( term_stack.at( term_stack.size() - 1 ) ) } );
-            term_stack.pop_back();
-            term_stack.back().variant = std::move( tmp );
-         }
          assert( string_stack.size() >= 2 );
-         {
-            std::string tmp = "( " + string_stack.at( string_stack.size() - 2 ) + " " + std::string( op ) + " " + string_stack.at( string_stack.size() - 1 ) + " )";
-            string_stack.pop_back();
-            string_stack.back() = std::move( tmp );
-         }
+
+         std::string tmp = "( " + string_stack.at( string_stack.size() - 2 ) + " " + std::string( op ) + " " + string_stack.at( string_stack.size() - 1 ) + " )";
+         string_stack.pop_back();
+         string_stack.back() = std::move( tmp );
       }
 
       void prefix( const std::string_view op )
       {
-         assert( term_stack.size() >= 1 );  // NOLINT(readability-container-size-empty)
-         {
-            variant_t tmp = tuple_t( "prefix" + op, { std::move( term_stack.at( term_stack.size() - 1 ) ) } );
-            term_stack.back().variant = std::move( tmp );
-         }
          assert( string_stack.size() >= 1 );  // NOLINT(readability-container-size-empty)
-         {
-            std::string tmp = std::string( op ) + "( " + string_stack.at( string_stack.size() - 1 ) + " )";
-            string_stack.back() = std::move( tmp );
-         }
+
+         std::string tmp = std::string( op ) + "( " + string_stack.at( string_stack.size() - 1 ) + " )";
+         string_stack.back() = std::move( tmp );
       }
 
       void postfix( const std::string_view op )
       {
-         assert( term_stack.size() >= 1 );  // NOLINT(readability-container-size-empty)
-         {
-            variant_t tmp = tuple_t( "postfix" + op, { std::move( term_stack.at( term_stack.size() - 1 ) ) } );
-            term_stack.back().variant = std::move( tmp );
-         }
          assert( string_stack.size() >= 1 );  // NOLINT(readability-container-size-empty)
-         {
-            std::string tmp = "( " + string_stack.at( string_stack.size() - 1 ) + " )" + std::string( op );
-            string_stack.back() = std::move( tmp );
-         }
+
+         std::string tmp = "( " + string_stack.at( string_stack.size() - 1 ) + " )" + std::string( op );
+         string_stack.back() = std::move( tmp );
       }
 
       void ternary( const std::string_view op, const std::string_view o2 )
       {
-         assert( term_stack.size() >= 2 );
-         {
-            variant_t tmp = tuple_t( "ternary", { std::move( term_stack.at( term_stack.size() - 3 ) ), std::move( term_stack.at( term_stack.size() - 2 ) ), std::move( term_stack.at( term_stack.size() - 1 ) ) } );
-            term_stack.pop_back();
-            term_stack.pop_back();
-            term_stack.back().variant = std::move( tmp );
-         }
          assert( string_stack.size() >= 2 );
-         {
-            std::string tmp = "( " + string_stack.at( string_stack.size() - 3 ) + " " + std::string( op ) + " " + string_stack.at( string_stack.size() - 2 ) + " " + std::string( o2 ) + " " + string_stack.at( string_stack.size() - 1 ) + " )";
-            string_stack.pop_back();
-            string_stack.pop_back();
-            string_stack.back() = std::move( tmp );
-         }
+
+         std::string tmp = "( " + string_stack.at( string_stack.size() - 3 ) + " " + std::string( op ) + " " + string_stack.at( string_stack.size() - 2 ) + " " + std::string( o2 ) + " " + string_stack.at( string_stack.size() - 1 ) + " )";
+         string_stack.pop_back();
+         string_stack.pop_back();
+         string_stack.back() = std::move( tmp );
       }
 
       void call( const std::string_view op, const std::string_view o2, const std::size_t args )
       {
-         assert( term_stack.size() > args );
-         {
-            variant_t tmp = tuple_t( "call '" + std::string( op ) + std::string( o2 ) + "'", std::vector< term_t >( term_stack.end() - args - 1, term_stack.end() ) );
-            for( std::size_t i = 0; i < args; ++i ) {
-               term_stack.pop_back();
-            }
-            term_stack.back().variant = ( std::move( tmp ) );
-         }
          assert( string_stack.size() > args );
-         {
-            std::string tmp = *( string_stack.end() - args - 1 ) + std::string( op ) + " ";
-            for( std::size_t i = 0; i < args; ++i ) {
-               if( i > 0 ) {
-                  tmp += ", ";
-               }
-               tmp += *( string_stack.end() - args + i );
+
+         std::string tmp = *( string_stack.end() - args - 1 ) + std::string( op ) + " ";
+         for( std::size_t i = 0; i < args; ++i ) {
+            if( i > 0 ) {
+               tmp += ", ";
             }
-            tmp += " " + std::string( o2 );
-            string_stack.resize( string_stack.size() - args );
-            string_stack.back() = std::move( tmp );
+            tmp += *( string_stack.end() - args + i );
          }
+         tmp += " " + std::string( o2 );
+         string_stack.resize( string_stack.size() - args );
+         string_stack.back() = std::move( tmp );
       }
 
       void number( const std::int64_t l )
       {
-         term_stack.emplace_back( l );
          string_stack.emplace_back( std::to_string( l ) );
       }
 
       void identifier( const std::string& id )
       {
-         term_stack.emplace_back( id );
          string_stack.emplace_back( id );
       }
 
-      std::vector< term_t > term_stack;
       std::vector< std::string > string_stack;
    };
 
-   inline std::ostream& operator<<( std::ostream& o, const term_t& t );
-
-   inline std::ostream& operator<<( std::ostream& o, const tuple_t& t )
-   {
-      o << "{ " << std::get< 0 >( t );
-      for( const auto& res : std::get< 1 >( t ) ) {
-         o << " " << res;
-      }
-      o << " }";
-      return o;
-   }
-
-   inline std::ostream& operator<<( std::ostream& o, const variant_t& v )
-   {
-      std::visit( [ & ]( const auto& t ) { o << t; }, v );
-      return o;
-   }
-
-   inline std::ostream& operator<<( std::ostream& o, const term_t& t )
-   {
-      o << t.variant;
-      return o;
-   }
-
    struct literal
       : pegtl::plus< pegtl::digit >
    {};
@@ -595,10 +504,8 @@ int main( int argc, char** argv )
          application::result res;
          TAO_PEGTL_NAMESPACE::parse< application::grammar, application::action >( in, res );
          std::cout << "Input: " << argv[ i ] << std::endl;
-         assert( res.term_stack.size() == 1 );
          assert( res.string_stack.size() == 1 );
          std::cout << "Result: " << res.string_stack.at( 0 ) << std::endl;
-         std::cout << "Result: " << res.term_stack.at( 0 ) << std::endl;
       }
       catch( const TAO_PEGTL_NAMESPACE::parse_error& e ) {
          const auto p = e.positions().front();
diff --git a/packages/PEGTL/src/example/pegtl/indent_aware.cpp b/packages/PEGTL/src/example/pegtl/indent_aware.cpp
index 0d6c65aac..42295a222 100644
--- a/packages/PEGTL/src/example/pegtl/indent_aware.cpp
+++ b/packages/PEGTL/src/example/pegtl/indent_aware.cpp
@@ -42,7 +42,6 @@ def b():
 namespace example
 {
    // clang-format off
-
    struct eq : pegtl::one< '=' > {};
    struct co : pegtl::one< ':' > {};
    struct hs : pegtl::one< '#' > {};
@@ -77,7 +76,6 @@ namespace example
    struct line : pegtl::sor< nothing, something > {};
 
    struct grammar : pegtl::until< pegtl::eof, pegtl::must< line > > {};
-
    // clang-format on
 
    enum class type
diff --git a/packages/PEGTL/src/example/pegtl/json_errors.hpp b/packages/PEGTL/src/example/pegtl/json_errors.hpp
index c03d21f75..e0517af74 100644
--- a/packages/PEGTL/src/example/pegtl/json_errors.hpp
+++ b/packages/PEGTL/src/example/pegtl/json_errors.hpp
@@ -37,15 +37,17 @@ namespace example
    template<> inline constexpr auto error_message< pegtl::json::key::content > = "unterminated key";
 
    template<> inline constexpr auto error_message< pegtl::eof > = "unexpected character after JSON value";
+   // clang-format on
 
    // As must_if<> can not take error_message as a template parameter directly, we need to wrap it.
    struct error
    {
-      template< typename Rule > static constexpr auto message = error_message< Rule >;
+      template< typename Rule >
+      static constexpr auto message = error_message< Rule >;
    };
 
-   template< typename Rule > using control = pegtl::must_if< error >::control< Rule >;
-   // clang-format on
+   template< typename Rule >
+   using control = pegtl::must_if< error >::control< Rule >;
 
 #else
 
diff --git a/packages/PEGTL/src/example/pegtl/lua53_print_debug.cpp b/packages/PEGTL/src/example/pegtl/lua53_print_debug.cpp
deleted file mode 100644
index 6703c5a1c..000000000
--- a/packages/PEGTL/src/example/pegtl/lua53_print_debug.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2015-2021 Dr. Colin Hirsch and Daniel Frey
-// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
-
-#if !defined( __cpp_exceptions )
-#include <iostream>
-int main()
-{
-   std::cerr << "Exception support required, example unavailable." << std::endl;
-   return 1;
-}
-#else
-
-#include <iostream>
-
-#include <tao/pegtl/contrib/print.hpp>
-
-#include "lua53.hpp"
-
-int main()  // NOLINT(bugprone-exception-escape)
-{
-   tao::pegtl::print_debug< lua53::grammar >( std::cout );
-   return 0;
-}
-
-#endif
diff --git a/packages/PEGTL/src/example/pegtl/lua53_print_names.cpp b/packages/PEGTL/src/example/pegtl/lua53_print_names.cpp
deleted file mode 100644
index 12260a20c..000000000
--- a/packages/PEGTL/src/example/pegtl/lua53_print_names.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2015-2021 Dr. Colin Hirsch and Daniel Frey
-// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
-
-#if !defined( __cpp_exceptions )
-#include <iostream>
-int main()
-{
-   std::cerr << "Exception support required, example unavailable." << std::endl;
-   return 1;
-}
-#else
-
-#include <iostream>
-
-#include <tao/pegtl/contrib/print.hpp>
-
-#include "lua53.hpp"
-
-int main()  // NOLINT(bugprone-exception-escape)
-{
-   tao::pegtl::print_names< lua53::grammar >( std::cout );
-   return 0;
-}
-
-#endif
diff --git a/packages/PEGTL/src/example/pegtl/peg2pegtl.cpp b/packages/PEGTL/src/example/pegtl/peg2pegtl.cpp
index c1ce89438..60b2628fb 100644
--- a/packages/PEGTL/src/example/pegtl/peg2pegtl.cpp
+++ b/packages/PEGTL/src/example/pegtl/peg2pegtl.cpp
@@ -227,10 +227,16 @@ namespace TAO_PEGTL_NAMESPACE
       template<> inline constexpr auto error_message< peg::grammar::Expression > = "unterminated expression";
       template<> inline constexpr auto error_message< peg::grammar::Grammar > = "unterminated grammar";
       template<> inline constexpr auto error_message< peg::grammar::Range > = "unterminated range";
-
-      struct error { template< typename Rule > static constexpr auto message = error_message< Rule >; };
-      template< typename Rule > using control = must_if< error >::control< Rule >;
       // clang-format on
+
+      struct error
+      {
+         template< typename Rule >
+         static constexpr auto message = error_message< Rule >;
+      };
+
+      template< typename Rule >
+      using control = must_if< error >::control< Rule >;
 #else
       template< typename Rule >
       using control = normal< Rule >;
diff --git a/packages/PEGTL/src/example/pegtl/proto3.cpp b/packages/PEGTL/src/example/pegtl/proto3.cpp
index 4283a8b27..39d126fa9 100644
--- a/packages/PEGTL/src/example/pegtl/proto3.cpp
+++ b/packages/PEGTL/src/example/pegtl/proto3.cpp
@@ -18,9 +18,9 @@ int main()
 namespace TAO_PEGTL_NAMESPACE::proto3
 {
    // clang-format off
-
-   struct comment : seq< two< '/' >, until< eolf > > {};
-   struct sp : sor< space, comment > {};
+   struct comment_sl : seq< two< '/' >, until< eolf > > {};
+   struct comment_ml : seq< one< '/' >, one< '*' >, until< seq< one< '*' >, one< '/' > > > > {};
+   struct sp : sor< space, comment_sl, comment_ml > {};
    struct sps : star< sp > {};
 
    struct comma : one< ',' > {};
@@ -30,6 +30,7 @@ namespace TAO_PEGTL_NAMESPACE::proto3
 
    struct option;
    struct message;
+   struct extend;
 
    struct odigit : range< '0', '7' > {};
 
@@ -38,9 +39,10 @@ namespace TAO_PEGTL_NAMESPACE::proto3
    struct ident : seq< ident_first, star< ident_other > > {};
    struct full_ident : list_must< ident, dot > {};
 
-   struct oct_lit : seq< one< '0' >, star< odigit > > {};
+   struct sign : one< '+', '-' > {};
+   struct oct_lit : seq< one< '0' >, plus< odigit > > {};
    struct hex_lit : seq< one< '0' >, one< 'x', 'X' >, plus< xdigit > > {};
-   struct dec_lit : seq< range< '1', '9' >, star< digit > > {};
+   struct dec_lit : sor< one< '0' >, seq< opt< sign >, range< '1', '9' >, star< digit > > >  {};
    struct int_lit : sor< dec_lit, hex_lit, oct_lit > {};
 
    struct hex_escape : if_must< one< 'x', 'X' >, xdigit, xdigit > {};
@@ -52,32 +54,37 @@ namespace TAO_PEGTL_NAMESPACE::proto3
    struct str_impl : if_must< one< Q >, until< one< Q >, char_value > > {};
    struct str_lit : sor< str_impl< '\'' >, str_impl< '"' > > {};
 
-   struct bool_lit : seq< sor< string< 't', 'r', 'u', 'e' >, string< 'f', 'a', 'l', 's', 'e' > >, not_at< ident_other > > {};
+   struct bool_lit : sor< keyword< 't', 'r', 'u', 'e' >, keyword< 'f', 'a', 'l', 's', 'e' > > {};
 
-   struct sign : one< '+', '-' > {};
-   struct constant : sor< bool_lit, full_ident, seq< opt< sign >, int_lit >, str_lit > {};  // TODO: Needs sps after sign?
+   struct exp : seq < one <'E', 'e'>, opt< sign >, plus< digit > > {};
+   struct float_lit_1 : seq< plus< digit >, dot, star< digit >, opt< exp > > {};
+   struct float_lit_2 : seq< dot, plus< digit >, opt< exp > > {};
+   struct float_lit_3 : seq< plus< digit >, exp > {};
+   struct float_lit : sor < seq< opt<sign>, sor< float_lit_1, float_lit_2, float_lit_3, keyword< 'i', 'n', 'f' > > >, keyword< 'n', 'a', 'n' > > {};
+
+   struct constant : sor< bool_lit, full_ident, float_lit, int_lit, str_lit > {};
 
    struct option_name : seq< sor< ident, if_must< one< '(' >, full_ident, one< ')' > > >, star_must< dot, ident > > {};
-   struct option : if_must< string< 'o', 'p', 't', 'i', 'o', 'n' >, sps, option_name, sps, equ, sps, constant, sps, semi, sps > {};
-
-   struct bool_type : string< 'b', 'o', 'o', 'l' > {};
-   struct bytes_type : string< 'b', 'y', 't', 'e', 's' > {};
-   struct double_type : string< 'd', 'o', 'u', 'b', 'l', 'e' > {};
-   struct float_type : string< 'f', 'l', 'o', 'a', 't' > {};
-   struct string_type : string< 's', 't', 'r', 'i', 'n', 'g' > {};
-
-   struct int32_type : string< 'i', 'n', 't', '3', '2' > {};
-   struct int64_type : string< 'i', 'n', 't', '6', '4' > {};
-   struct sint32_type : string< 's', 'i', 'n', 't', '3', '2' > {};
-   struct sint64_type : string< 's', 'i', 'n', 't', '6', '4' > {};
-   struct uint32_type : string< 'u', 'i', 'n', 't', '3', '2' > {};
-   struct uint64_type : string< 'u', 'i', 'n', 't', '6', '4' > {};
-   struct fixed32_type : string< 'f', 'i', 'x', 'e', 'd', '3', '2' > {};
-   struct fixed64_type : string< 'f', 'i', 'x', 'e', 'd', '6', '4' > {};
-   struct sfixed32_type : string< 's', 'f', 'i', 'x', 'e', 'd', '3', '2' > {};
-   struct sfixed64_type : string< 's', 'f', 'i', 'x', 'e', 'd', '6', '4' > {};
-
-   struct builtin_type : seq< sor< bool_type, bytes_type, double_type, float_type, string_type, int32_type, int64_type, sint32_type, sint64_type, uint32_type, uint64_type, fixed32_type, fixed64_type, sfixed32_type, sfixed64_type >, not_at< ident_other > > {};
+   struct option : if_must< keyword< 'o', 'p', 't', 'i', 'o', 'n' >, sps, option_name, sps, equ, sps, constant, sps, semi > {};
+
+   struct bool_type : keyword< 'b', 'o', 'o', 'l' > {};
+   struct bytes_type : keyword< 'b', 'y', 't', 'e', 's' > {};
+   struct double_type : keyword< 'd', 'o', 'u', 'b', 'l', 'e' > {};
+   struct float_type : keyword< 'f', 'l', 'o', 'a', 't' > {};
+   struct string_type : keyword< 's', 't', 'r', 'i', 'n', 'g' > {};
+
+   struct int32_type : keyword< 'i', 'n', 't', '3', '2' > {};
+   struct int64_type : keyword< 'i', 'n', 't', '6', '4' > {};
+   struct sint32_type : keyword< 's', 'i', 'n', 't', '3', '2' > {};
+   struct sint64_type : keyword< 's', 'i', 'n', 't', '6', '4' > {};
+   struct uint32_type : keyword< 'u', 'i', 'n', 't', '3', '2' > {};
+   struct uint64_type : keyword< 'u', 'i', 'n', 't', '6', '4' > {};
+   struct fixed32_type : keyword< 'f', 'i', 'x', 'e', 'd', '3', '2' > {};
+   struct fixed64_type : keyword< 'f', 'i', 'x', 'e', 'd', '6', '4' > {};
+   struct sfixed32_type : keyword< 's', 'f', 'i', 'x', 'e', 'd', '3', '2' > {};
+   struct sfixed64_type : keyword< 's', 'f', 'i', 'x', 'e', 'd', '6', '4' > {};
+
+   struct builtin_type : sor< bool_type, bytes_type, double_type, float_type, string_type, int32_type, int64_type, sint32_type, sint64_type, uint32_type, uint64_type, fixed32_type, fixed64_type, sfixed32_type, sfixed64_type > {};
 
    struct defined_type : seq< opt< dot >, full_ident > {};  // NOTE: This replaces both message_type and enum_type -- they have the same syntax.
 
@@ -87,48 +94,49 @@ namespace TAO_PEGTL_NAMESPACE::proto3
    struct field_options : if_must< one< '[' >, sps, list< field_option, comma, sp >, sps, one< ']' > > {};
    struct field_name : ident {};
    struct field_number : int_lit {};
-   struct field : seq< opt< string< 'r', 'e', 'p', 'e', 'a', 't', 'e', 'd' >, sps >, type, sps, field_name, sps, equ, sps, field_number, sps, opt< field_options, sps >, semi > {};
+   struct field : seq< opt< sor < keyword< 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l' >, keyword< 'r', 'e', 'p', 'e', 'a', 't', 'e', 'd' > >, sps >, type, sps, field_name, sps, equ, sps, field_number, sps, opt< field_options, sps >, semi > {};
 
    struct oneof_name : ident {};
    struct oneof_field : if_must< type, sps, field_name, sps, equ, sps, field_number, sps, opt< field_options, sps >, semi > {};
    struct oneof_body : sor< oneof_field, semi > {};
-   struct oneof : if_must< string< 'o', 'n', 'e', 'o', 'f' >, sps, oneof_name, sps, one< '{' >, sps, until< one< '}' >, oneof_body, sps >, sps > {};
+   struct oneof : if_must< keyword< 'o', 'n', 'e', 'o', 'f' >, sps, oneof_name, sps, one< '{' >, sps, until< one< '}' >, oneof_body, sps >, sps > {};
 
    struct key_type : seq< sor< bool_type, string_type, int32_type, int64_type, sint32_type, sint64_type, uint32_type, uint64_type, fixed32_type, fixed64_type, sfixed32_type, sfixed64_type >, not_at< ident_other > > {};
    struct map_name : ident {};
-   struct map_field : if_must< string< 'm', 'a', 'p' >, sps, one< '<' >, sps, key_type, sps, comma, sps, type, sps, one< '>' >, sps, map_name, sps, equ, sps, field_number, sps, opt< field_options, sps >, semi > {};
+   struct map_field : if_must< keyword< 'm', 'a', 'p' >, sps, one< '<' >, sps, key_type, sps, comma, sps, type, sps, one< '>' >, sps, map_name, sps, equ, sps, field_number, sps, opt< field_options, sps >, semi > {};
 
-   struct range : if_must< int_lit, sps, string< 't', 'o' >, sps, sor< int_lit, string< 'm', 'a', 'x' > > > {};
+   struct range : if_must< int_lit, sps, keyword< 't', 'o' >, sps, sor< int_lit, keyword< 'm', 'a', 'x' > > > {};
    struct ranges : list_must< range, comma, sp > {};
    struct field_names : list_must< field_name, comma, sp > {};
-   struct reserved : if_must< string< 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd' >, sps, sor< ranges, field_names >, sps, semi > {};
+   struct reserved : if_must< keyword< 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd' >, sps, sor< ranges, field_names >, sps, semi > {};
 
    struct enum_name : ident {};
    struct enum_value_option : seq< option_name, sps, equ, sps, constant > {};
    struct enum_field : seq< ident, sps, equ, sps, int_lit, sps, opt_must< one< '[' >, sps, list_must< enum_value_option, comma, sp >, sps, one< ']' >, sps >, semi > {};
    struct enum_body : if_must< one< '{' >, sps, star< sor< option, enum_field, semi >, sps >, one< '}' > > {};
-   struct enum_def : if_must< string< 'e', 'n', 'u', 'm' >, sps, enum_name, sps, enum_body > {};
+   struct enum_def : if_must< keyword< 'e', 'n', 'u', 'm' >, sps, enum_name, sps, enum_body > {};
 
-   struct message_thing : sor< field, enum_def, message, option, oneof, map_field, reserved, semi > {};
-   struct message : if_must< string< 'm', 'e', 's', 's', 'a', 'g', 'e' >, sps, ident, sps, one< '{' >, sps, star< message_thing, sps >, one< '}' >, sps > {};
+   struct message_thing : sor< field, enum_def, message, option, oneof, map_field, reserved, extend, semi > {};
+   struct message_body : seq< one<'{'>, sps, star< message_thing, sps >, one<'}'> > {};
+   struct message : if_must< keyword< 'm', 'e', 's', 's', 'a', 'g', 'e' >, sps, defined_type, sps, message_body > {};
+   struct extend : if_must< keyword< 'e', 'x', 't', 'e', 'n', 'd' >, sps, defined_type, sps, message_body > {};
 
-   struct package : if_must< string< 'p', 'a', 'c', 'k', 'a', 'g', 'e' >, sps, full_ident, sps, semi, sps > {};
+   struct package : if_must< keyword< 'p', 'a', 'c', 'k', 'a', 'g', 'e' >, sps, full_ident, sps, semi > {};
 
-   struct import_option : opt< sor< string< 'w', 'e', 'a', 'k' >, string< 'p', 'u', 'b', 'l', 'i', 'c' > > > {};
-   struct import : if_must< string< 'i', 'm', 'p', 'o', 'r', 't' >, sps, import_option, sps, str_lit, sps, semi, sps > {};
+   struct import_option : opt< sor< keyword< 'w', 'e', 'a', 'k' >, keyword< 'p', 'u', 'b', 'l', 'i', 'c' > > > {};
+   struct import : if_must< keyword< 'i', 'm', 'p', 'o', 'r', 't' >, sps, import_option, sps, str_lit, sps, semi > {};
 
    struct rpc_name : ident {};
-   struct rpc_type : if_must< one< '(' >, sps, opt< string< 's', 't', 'r', 'e', 'a', 'm' >, sps >, defined_type, sps, one< ')' > > {};
+   struct rpc_type : if_must< one< '(' >, sps, opt< keyword< 's', 't', 'r', 'e', 'a', 'm' >, sps >, defined_type, sps, one< ')' > > {};
    struct rpc_options : if_must< one< '{' >, sps, star< sor< option, semi >, sps >, one< '}' > > {};
-   struct rpc : if_must< string< 'r', 'p', 'c' >, sps, rpc_name, sps, rpc_type, sps, string< 'r', 'e', 't', 'u', 'r', 'n', 's' >, sps, rpc_type, sor< semi, rpc_options > > {};
+   struct rpc : if_must< keyword< 'r', 'p', 'c' >, sps, rpc_name, sps, rpc_type, sps, keyword< 'r', 'e', 't', 'u', 'r', 'n', 's' >, sps, rpc_type, sps, sor< semi, rpc_options > > {};
    struct service_name : ident {};
-   struct service : if_must< string< 's', 'e', 'r', 'v', 'i', 'c', 'e' >, sps, service_name, sps, one< '{' >, sps, list_must< sor< option, rpc, semi >, comma, sp >, sps, one< '}' > > {};
+   struct service : if_must< keyword< 's', 'e', 'r', 'v', 'i', 'c', 'e' >, sps, service_name, sps, one< '{' >, sps, star< sor< option, rpc, semi >, sps >, one< '}' > > {};
 
-   struct body : sor< import, package, option, message, enum_def, service, semi > {};
+   struct body : sor< import, package, option, message, enum_def, service, extend, semi > {};
 
-   struct head : if_must< string< 's', 'y', 'n', 't', 'a', 'x' >, sps, equ, sps, string< '"', 'p', 'r', 'o', 't', 'o', '3', '"' >, sps, semi > {};
+   struct head : if_must< keyword< 's', 'y', 'n', 't', 'a', 'x' >, sps, equ, sps, string< '"', 'p', 'r', 'o', 't', 'o', '3', '"' >, sps, semi > {};
    struct proto : must< sps, head, sps, star< body, sps >, eof > {};
-
    // clang-format on
 
 }  // namespace TAO_PEGTL_NAMESPACE::proto3
diff --git a/packages/PEGTL/src/test/pegtl/contrib_analyze.cpp b/packages/PEGTL/src/test/pegtl/contrib_analyze.cpp
index 438b3a191..fec49897a 100644
--- a/packages/PEGTL/src/test/pegtl/contrib_analyze.cpp
+++ b/packages/PEGTL/src/test/pegtl/contrib_analyze.cpp
@@ -35,6 +35,7 @@ namespace TAO_PEGTL_NAMESPACE
       verify_analyze< eolf >( __LINE__, __FILE__, false, false );
       verify_analyze< success >( __LINE__, __FILE__, false, false );
       verify_analyze< failure >( __LINE__, __FILE__, true, false );
+
       // clang-format off
       {
          struct tst : star< tst > {};
diff --git a/packages/PEGTL/src/test/pegtl/contrib_control_action.cpp b/packages/PEGTL/src/test/pegtl/contrib_control_action.cpp
index b60f796e9..8249dc600 100644
--- a/packages/PEGTL/src/test/pegtl/contrib_control_action.cpp
+++ b/packages/PEGTL/src/test/pegtl/contrib_control_action.cpp
@@ -48,7 +48,7 @@ namespace TAO_PEGTL_NAMESPACE
       {
          TAO_PEGTL_TEST_UNREACHABLE;
       }
-      // LCOV_EXCL_END
+      // LCOV_EXCL_STOP
    };
 
    template<>
@@ -67,7 +67,7 @@ namespace TAO_PEGTL_NAMESPACE
       {
          TAO_PEGTL_TEST_UNREACHABLE;
       }
-      // LCOV_EXCL_END
+      // LCOV_EXCL_STOP
 
       template< typename ParseInput >
       static void failure( const ParseInput& /*unused*/, int /*unused*/ )
@@ -98,7 +98,7 @@ namespace TAO_PEGTL_NAMESPACE
       {
          TAO_PEGTL_TEST_UNREACHABLE;
       }
-      // LCOV_EXCL_END
+      // LCOV_EXCL_STOP
    };
 
 #if defined( __cpp_exceptions )
@@ -124,7 +124,7 @@ namespace TAO_PEGTL_NAMESPACE
       {
          TAO_PEGTL_TEST_UNREACHABLE;
       }
-      // LCOV_EXCL_END
+      // LCOV_EXCL_STOP
 
       template< typename ParseInput >
       static void unwind( const ParseInput& /*unused*/, int /*unused*/ )
diff --git a/packages/PEGTL/src/test/pegtl/contrib_if_then.cpp b/packages/PEGTL/src/test/pegtl/contrib_if_then.cpp
index dac262144..ceb60d602 100644
--- a/packages/PEGTL/src/test/pegtl/contrib_if_then.cpp
+++ b/packages/PEGTL/src/test/pegtl/contrib_if_then.cpp
@@ -15,12 +15,12 @@ namespace TAO_PEGTL_NAMESPACE
          if_then< one< 'a' >, one< 'b' >, one< 'c' > >::
          else_if_then< one< 'a' >, one< 'b' > >::
          else_then< one< 'c' > >;
+      // clang-format on
 
       verify_rule< grammar >( __LINE__, __FILE__, "abc", result_type::success, 0 );
       verify_rule< grammar >( __LINE__, __FILE__, "abcd", result_type::success, 1 );
       verify_rule< grammar >( __LINE__, __FILE__, "ab", result_type::local_failure, 2 );
       verify_rule< grammar >( __LINE__, __FILE__, "c", result_type::success, 0 );
-      // clang-format on
    }
 
 }  // namespace TAO_PEGTL_NAMESPACE
diff --git a/packages/PEGTL/src/test/pegtl/contrib_integer.cpp b/packages/PEGTL/src/test/pegtl/contrib_integer.cpp
index 3f0f46195..d08182a9c 100644
--- a/packages/PEGTL/src/test/pegtl/contrib_integer.cpp
+++ b/packages/PEGTL/src/test/pegtl/contrib_integer.cpp
@@ -11,6 +11,7 @@ int main()
 
 #include <limits>
 #include <sstream>
+#include <utility>
 
 #include "test.hpp"
 
@@ -64,9 +65,9 @@ namespace TAO_PEGTL_NAMESPACE
    template< typename S >
    std::string lexical_cast( const S s )
    {
-      std::ostringstream o;
-      o << s;
-      return o.str();
+      std::ostringstream oss;
+      oss << s;
+      return std::move( oss ).str();
    }
 
    template< typename S >
@@ -172,63 +173,63 @@ namespace TAO_PEGTL_NAMESPACE
       test_unsigned< unsigned char >( "000256" );
 
       test_signed< signed long long >( "0", 0 );
-      test_signed< signed long long >( ( std::numeric_limits< signed long long >::max )() );
-      test_signed< signed long long >( ( std::numeric_limits< signed long long >::min )() );
+      test_signed< signed long long >( (std::numeric_limits< signed long long >::max)() );
+      test_signed< signed long long >( (std::numeric_limits< signed long long >::min)() );
 
       test_unsigned< unsigned long long >( "0", 0 );
-      test_unsigned< unsigned long long >( ( std::numeric_limits< unsigned long long >::max )() );
+      test_unsigned< unsigned long long >( (std::numeric_limits< unsigned long long >::max)() );
 
       verify_rule< max_seq_rule< 0 > >( __LINE__, __FILE__, "a0b", result_type::success );
       verify_rule< max_seq_rule< 0 > >( __LINE__, __FILE__, "ab", result_type::local_failure );
-      verify_rule< max_seq_rule< 0 > >( __LINE__, __FILE__, "a1b", result_type::global_failure );
-      verify_rule< max_seq_rule< 0 > >( __LINE__, __FILE__, "a9b", result_type::global_failure );
-      verify_rule< max_seq_rule< 0 > >( __LINE__, __FILE__, "a11b", result_type::global_failure );
+      verify_rule< max_seq_rule< 0 > >( __LINE__, __FILE__, "a1b", result_type::local_failure );
+      verify_rule< max_seq_rule< 0 > >( __LINE__, __FILE__, "a9b", result_type::local_failure );
+      verify_rule< max_seq_rule< 0 > >( __LINE__, __FILE__, "a11b", result_type::local_failure );
 
       verify_rule< max_seq_rule< 1 > >( __LINE__, __FILE__, "a0b", result_type::success );
       verify_rule< max_seq_rule< 1 > >( __LINE__, __FILE__, "a1b", result_type::success );
       verify_rule< max_seq_rule< 1 > >( __LINE__, __FILE__, "ab", result_type::local_failure );
-      verify_rule< max_seq_rule< 1 > >( __LINE__, __FILE__, "a2b", result_type::global_failure );
-      verify_rule< max_seq_rule< 1 > >( __LINE__, __FILE__, "a9b", result_type::global_failure );
-      verify_rule< max_seq_rule< 1 > >( __LINE__, __FILE__, "a11b", result_type::global_failure );
+      verify_rule< max_seq_rule< 1 > >( __LINE__, __FILE__, "a2b", result_type::local_failure );
+      verify_rule< max_seq_rule< 1 > >( __LINE__, __FILE__, "a9b", result_type::local_failure );
+      verify_rule< max_seq_rule< 1 > >( __LINE__, __FILE__, "a11b", result_type::local_failure );
 
       verify_rule< max_seq_rule< 2 > >( __LINE__, __FILE__, "a0b", result_type::success );
       verify_rule< max_seq_rule< 2 > >( __LINE__, __FILE__, "a1b", result_type::success );
       verify_rule< max_seq_rule< 2 > >( __LINE__, __FILE__, "a2b", result_type::success );
       verify_rule< max_seq_rule< 2 > >( __LINE__, __FILE__, "ab", result_type::local_failure );
-      verify_rule< max_seq_rule< 2 > >( __LINE__, __FILE__, "a3b", result_type::global_failure );
-      verify_rule< max_seq_rule< 2 > >( __LINE__, __FILE__, "a9b", result_type::global_failure );
-      verify_rule< max_seq_rule< 2 > >( __LINE__, __FILE__, "a11b", result_type::global_failure );
+      verify_rule< max_seq_rule< 2 > >( __LINE__, __FILE__, "a3b", result_type::local_failure );
+      verify_rule< max_seq_rule< 2 > >( __LINE__, __FILE__, "a9b", result_type::local_failure );
+      verify_rule< max_seq_rule< 2 > >( __LINE__, __FILE__, "a11b", result_type::local_failure );
 
       verify_rule< max_seq_rule< 3 > >( __LINE__, __FILE__, "a0b", result_type::success );
       verify_rule< max_seq_rule< 3 > >( __LINE__, __FILE__, "a3b", result_type::success );
       verify_rule< max_seq_rule< 3 > >( __LINE__, __FILE__, "ab", result_type::local_failure );
-      verify_rule< max_seq_rule< 3 > >( __LINE__, __FILE__, "a4b", result_type::global_failure );
-      verify_rule< max_seq_rule< 3 > >( __LINE__, __FILE__, "a11b", result_type::global_failure );
+      verify_rule< max_seq_rule< 3 > >( __LINE__, __FILE__, "a4b", result_type::local_failure );
+      verify_rule< max_seq_rule< 3 > >( __LINE__, __FILE__, "a11b", result_type::local_failure );
 
-      verify_rule< max_seq_rule< 4 > >( __LINE__, __FILE__, "a5b", result_type::global_failure );
-      verify_rule< max_seq_rule< 4 > >( __LINE__, __FILE__, "a11b", result_type::global_failure );
+      verify_rule< max_seq_rule< 4 > >( __LINE__, __FILE__, "a5b", result_type::local_failure );
+      verify_rule< max_seq_rule< 4 > >( __LINE__, __FILE__, "a11b", result_type::local_failure );
 
       verify_rule< max_seq_rule< 9 > >( __LINE__, __FILE__, "a0b", result_type::success );
       verify_rule< max_seq_rule< 9 > >( __LINE__, __FILE__, "a9b", result_type::success );
       verify_rule< max_seq_rule< 9 > >( __LINE__, __FILE__, "ab", result_type::local_failure );
-      verify_rule< max_seq_rule< 9 > >( __LINE__, __FILE__, "a10b", result_type::global_failure );
-      verify_rule< max_seq_rule< 9 > >( __LINE__, __FILE__, "a11b", result_type::global_failure );
+      verify_rule< max_seq_rule< 9 > >( __LINE__, __FILE__, "a10b", result_type::local_failure );
+      verify_rule< max_seq_rule< 9 > >( __LINE__, __FILE__, "a11b", result_type::local_failure );
 
       verify_rule< max_seq_rule< 10 > >( __LINE__, __FILE__, "a0b", result_type::success );
       verify_rule< max_seq_rule< 10 > >( __LINE__, __FILE__, "a9b", result_type::success );
       verify_rule< max_seq_rule< 10 > >( __LINE__, __FILE__, "a10b", result_type::success );
       verify_rule< max_seq_rule< 10 > >( __LINE__, __FILE__, "ab", result_type::local_failure );
-      verify_rule< max_seq_rule< 10 > >( __LINE__, __FILE__, "a11b", result_type::global_failure );
-      verify_rule< max_seq_rule< 10 > >( __LINE__, __FILE__, "a19b", result_type::global_failure );
+      verify_rule< max_seq_rule< 10 > >( __LINE__, __FILE__, "a11b", result_type::local_failure );
+      verify_rule< max_seq_rule< 10 > >( __LINE__, __FILE__, "a19b", result_type::local_failure );
 
       verify_rule< max_seq_rule< 11 > >( __LINE__, __FILE__, "a0b", result_type::success );
       verify_rule< max_seq_rule< 11 > >( __LINE__, __FILE__, "a9b", result_type::success );
       verify_rule< max_seq_rule< 11 > >( __LINE__, __FILE__, "a10b", result_type::success );
       verify_rule< max_seq_rule< 11 > >( __LINE__, __FILE__, "a11b", result_type::success );
       verify_rule< max_seq_rule< 11 > >( __LINE__, __FILE__, "ab", result_type::local_failure );
-      verify_rule< max_seq_rule< 11 > >( __LINE__, __FILE__, "a12b", result_type::global_failure );
-      verify_rule< max_seq_rule< 11 > >( __LINE__, __FILE__, "a13b", result_type::global_failure );
-      verify_rule< max_seq_rule< 11 > >( __LINE__, __FILE__, "a111b", result_type::global_failure );
+      verify_rule< max_seq_rule< 11 > >( __LINE__, __FILE__, "a12b", result_type::local_failure );
+      verify_rule< max_seq_rule< 11 > >( __LINE__, __FILE__, "a13b", result_type::local_failure );
+      verify_rule< max_seq_rule< 11 > >( __LINE__, __FILE__, "a111b", result_type::local_failure );
 
       verify_rule< max_seq_rule< 12 > >( __LINE__, __FILE__, "a0b", result_type::success );
       verify_rule< max_seq_rule< 12 > >( __LINE__, __FILE__, "a1b", result_type::success );
@@ -237,16 +238,16 @@ namespace TAO_PEGTL_NAMESPACE
       verify_rule< max_seq_rule< 12 > >( __LINE__, __FILE__, "a11b", result_type::success );
       verify_rule< max_seq_rule< 12 > >( __LINE__, __FILE__, "a12b", result_type::success );
       verify_rule< max_seq_rule< 12 > >( __LINE__, __FILE__, "ab", result_type::local_failure );
-      verify_rule< max_seq_rule< 12 > >( __LINE__, __FILE__, "a13b", result_type::global_failure );
-      verify_rule< max_seq_rule< 12 > >( __LINE__, __FILE__, "a19b", result_type::global_failure );
-      verify_rule< max_seq_rule< 12 > >( __LINE__, __FILE__, "a111b", result_type::global_failure );
+      verify_rule< max_seq_rule< 12 > >( __LINE__, __FILE__, "a13b", result_type::local_failure );
+      verify_rule< max_seq_rule< 12 > >( __LINE__, __FILE__, "a19b", result_type::local_failure );
+      verify_rule< max_seq_rule< 12 > >( __LINE__, __FILE__, "a111b", result_type::local_failure );
 
       verify_rule< max_seq_rule< 18446744073709551614ULL > >( __LINE__, __FILE__, "a18446744073709551614b", result_type::success );
-      verify_rule< max_seq_rule< 18446744073709551614ULL > >( __LINE__, __FILE__, "a18446744073709551615b", result_type::global_failure );
+      verify_rule< max_seq_rule< 18446744073709551614ULL > >( __LINE__, __FILE__, "a18446744073709551615b", result_type::local_failure );
 
       verify_rule< max_seq_rule< 18446744073709551615ULL > >( __LINE__, __FILE__, "a18446744073709551615b", result_type::success );
-      verify_rule< max_seq_rule< 18446744073709551615ULL > >( __LINE__, __FILE__, "a18446744073709551616b", result_type::global_failure );
-      verify_rule< max_seq_rule< 18446744073709551615ULL > >( __LINE__, __FILE__, "a98446744073709551614b", result_type::global_failure );
+      verify_rule< max_seq_rule< 18446744073709551615ULL > >( __LINE__, __FILE__, "a18446744073709551616b", result_type::local_failure );
+      verify_rule< max_seq_rule< 18446744073709551615ULL > >( __LINE__, __FILE__, "a98446744073709551614b", result_type::local_failure );
 
       verify_analyze< unsigned_rule >( __LINE__, __FILE__, true, false );
       verify_analyze< unsigned_rule_with_action >( __LINE__, __FILE__, true, false );
diff --git a/packages/PEGTL/src/test/pegtl/contrib_uri.cpp b/packages/PEGTL/src/test/pegtl/contrib_uri.cpp
index 7ae74cd90..0d855035f 100644
--- a/packages/PEGTL/src/test/pegtl/contrib_uri.cpp
+++ b/packages/PEGTL/src/test/pegtl/contrib_uri.cpp
@@ -23,23 +23,25 @@ namespace TAO_PEGTL_NAMESPACE
    {
       verify_analyze< GRAMMAR >( __LINE__, __FILE__, true, false );
 
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "http://de.wikipedia.org/wiki/Uniform_Resource_Identifier", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "ftp://ftp.is.co.za/rfc/rfc1808.txt", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "file:///C:/Users/Benutzer/Desktop/Uniform%20Resource%20Identifier.html", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "file:///etc/fstab", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "geo:48.33,14.122;u=22.5", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "ldap://[2001:db8::7]/c=GB?objectClass?one", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "gopher://gopher.floodgap.com", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "mailto:John.Doe@example.com", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "sip:911@pbx.mycompany.com", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "news:comp.infosystems.www.servers.unix", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "data:text/plain;charset=iso-8859-7,%be%fa%be", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "tel:+1-816-555-1212", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "telnet://192.0.2.16:80/", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "urn:oasis:names:specification:docbook:dtd:xml:4.1.2", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "git://github.com/rails/rails.git", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "crid://broadcaster.com/movies/BestActionMovieEver", result_type::success, 0 );
-      verify_rule< GRAMMAR >( __LINE__, __FILE__, "http://nobody:password@example.org:8080/cgi-bin/script.php?action=submit&pageid=86392001#section_2", result_type::success, 0 );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "http://de.wikipedia.org/wiki/Uniform_Resource_Identifier", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "ftp://ftp.is.co.za/rfc/rfc1808.txt", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "file:///C:/Users/Benutzer/Desktop/Uniform%20Resource%20Identifier.html", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "file:///etc/fstab", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "geo:48.33,14.122;u=22.5", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "ldap://[2001:db8::7]/c=GB?objectClass?one", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "gopher://gopher.floodgap.com", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "mailto:John.Doe@example.com", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "sip:911@pbx.mycompany.com", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "news:comp.infosystems.www.servers.unix", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "data:text/plain;charset=iso-8859-7,%be%fa%be", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "tel:+1-816-555-1212", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "telnet://192.0.2.16:80/", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "urn:oasis:names:specification:docbook:dtd:xml:4.1.2", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "git://github.com/rails/rails.git", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "crid://broadcaster.com/movies/BestActionMovieEver", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "http://nobody:password@example.org:8080/cgi-bin/script.php?action=submit&pageid=86392001#section_2", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "quake://480fps.com:26000/", result_type::success );
+      verify_rule< GRAMMAR >( __LINE__, __FILE__, "ftp://300.300.300.300/foo", result_type::success );  // 300.300.300.300 is a valid hostname!
 
       TAO_PEGTL_TEST_THROWS( parse< GRAMMAR >( memory_input( "", "" ) ) );
    }
diff --git a/packages/PEGTL/src/test/pegtl/error_message.cpp b/packages/PEGTL/src/test/pegtl/error_message.cpp
index 8e19e9ae8..d701fc24a 100644
--- a/packages/PEGTL/src/test/pegtl/error_message.cpp
+++ b/packages/PEGTL/src/test/pegtl/error_message.cpp
@@ -22,11 +22,17 @@ namespace test1
 
    template< typename > inline constexpr const char* error_message = nullptr;
    template<> inline constexpr auto error_message< test1::b > = "test123";
-
-   struct error { template< typename Rule > static constexpr auto message = error_message< Rule >; };
-   template< typename Rule > using control = must_if< error >::control< Rule >;
    // clang-format on
 
+   struct error
+   {
+      template< typename Rule >
+      static constexpr auto message = error_message< Rule >;
+   };
+
+   template< typename Rule >
+   using control = must_if< error >::control< Rule >;
+
 }  // namespace test1
 
 namespace TAO_PEGTL_NAMESPACE
diff --git a/packages/PEGTL/src/test/pegtl/internal_file_mapper.cpp b/packages/PEGTL/src/test/pegtl/internal_file_mapper.cpp
index 2cf26fa40..322aec8ba 100644
--- a/packages/PEGTL/src/test/pegtl/internal_file_mapper.cpp
+++ b/packages/PEGTL/src/test/pegtl/internal_file_mapper.cpp
@@ -22,7 +22,7 @@ namespace TAO_PEGTL_NAMESPACE
          // LCOV_EXCL_START
          std::cerr << "pegtl: unit test failed for [ internal::file_mapper ]" << std::endl;
          ++failed;
-         // LCOV_EXCL_END
+         // LCOV_EXCL_STOP
       }
       catch( const internal::filesystem::filesystem_error& ) {
       }
@@ -31,7 +31,7 @@ namespace TAO_PEGTL_NAMESPACE
          std::cerr << "pegtl: unit test failed for [ internal::file_mapper ] with unexpected exception" << std::endl;
          ++failed;
       }
-      // LCOV_EXCL_END
+      // LCOV_EXCL_STOP
 
       const std::string s = "dummy content\n";
       const std::string dummy_content = s + s + s + s + s + s + s + s + s + s + s;
diff --git a/packages/PEGTL/src/test/pegtl/internal_file_opener.cpp b/packages/PEGTL/src/test/pegtl/internal_file_opener.cpp
index 33f7aba20..cea22c227 100644
--- a/packages/PEGTL/src/test/pegtl/internal_file_opener.cpp
+++ b/packages/PEGTL/src/test/pegtl/internal_file_opener.cpp
@@ -25,7 +25,7 @@ namespace TAO_PEGTL_NAMESPACE
          // LCOV_EXCL_START
          std::cerr << "pegtl: unit test failed for [ internal::file_opener ] " << std::endl;
          ++failed;
-         // LCOV_EXCL_END
+         // LCOV_EXCL_STOP
       }
       catch( const std::exception& ) {
       }
diff --git a/packages/PEGTL/src/test/pegtl/rule_apply.cpp b/packages/PEGTL/src/test/pegtl/rule_apply.cpp
index 722fe096c..7c5082272 100644
--- a/packages/PEGTL/src/test/pegtl/rule_apply.cpp
+++ b/packages/PEGTL/src/test/pegtl/rule_apply.cpp
@@ -60,7 +60,7 @@ namespace TAO_PEGTL_NAMESPACE
          {
             TAO_PEGTL_TEST_ASSERT( false );
          }
-         // LCOV_EXCL_END
+         // LCOV_EXCL_STOP
       };
 
    }  // namespace test1
diff --git a/packages/PEGTL/src/test/pegtl/rule_apply0.cpp b/packages/PEGTL/src/test/pegtl/rule_apply0.cpp
index 010fca8d2..678c424dd 100644
--- a/packages/PEGTL/src/test/pegtl/rule_apply0.cpp
+++ b/packages/PEGTL/src/test/pegtl/rule_apply0.cpp
@@ -55,7 +55,7 @@ namespace TAO_PEGTL_NAMESPACE
          {
             TAO_PEGTL_TEST_ASSERT( false );
          }
-         // LCOV_EXCL_END
+         // LCOV_EXCL_STOP
       };
 
    }  // namespace test1
diff --git a/packages/PEGTL/src/test/pegtl/rule_if_apply.cpp b/packages/PEGTL/src/test/pegtl/rule_if_apply.cpp
index 4297e9a8c..803d08f49 100644
--- a/packages/PEGTL/src/test/pegtl/rule_if_apply.cpp
+++ b/packages/PEGTL/src/test/pegtl/rule_if_apply.cpp
@@ -61,7 +61,7 @@ namespace TAO_PEGTL_NAMESPACE
          {
             TAO_PEGTL_TEST_ASSERT( false );
          }
-         // LCOV_EXCL_END
+         // LCOV_EXCL_STOP
       };
 
       template< typename Rule >
diff --git a/packages/PEGTL/src/test/pegtl/verify_impl.hpp b/packages/PEGTL/src/test/pegtl/verify_impl.hpp
index 312f2785a..aecc70b18 100644
--- a/packages/PEGTL/src/test/pegtl/verify_impl.hpp
+++ b/packages/PEGTL/src/test/pegtl/verify_impl.hpp
@@ -36,7 +36,7 @@ namespace TAO_PEGTL_NAMESPACE
       catch( ... ) {
          TAO_PEGTL_TEST_UNREACHABLE;
       }
-      // LCOV_EXCL_END
+      // LCOV_EXCL_STOP
 
 #else
 
-- 
GitLab