diff --git a/Text/Yaml/Reference.hs b/Text/Yaml/Reference.hs
--- a/Text/Yaml/Reference.hs
+++ b/Text/Yaml/Reference.hs
@@ -14,9 +14,8 @@
 -- the actual productions from @Reference.bnf@.
 --
 -- The parsing framework is fully streaming (generates output tokens
--- \"immediately\"), but has a memory leak (actually retention) which causes it
--- to blow up on \"large\" files. To debug this with minimal syntax productions
--- use the @debug_leak@ production (@yes "#" | yaml2yeast -p debug-leak@).
+-- \"immediately\"). The memory leak that existed in previous version has been
+-- plugged.
 -------------------------------------------------------------------------------
 
 module Text.Yaml.Reference
@@ -53,11 +52,6 @@
 import qualified Prelude
 import           Prelude hiding ((/), (*), (+), (-), (^))
 
--- * DeepSeq
---
--- Without this, memory consumption goes to infinity. This is a subset of Dean
--- Herington's code.
-
 -- * Generic operators
 --
 -- ** Numeric operators
@@ -420,8 +414,8 @@
 --    building a parse tree, and completing all of it before any of it is
 --    accessible to the caller. We return a stream of tokens, and would like
 --    its head to be accessible as soon as possible to allow for streaming. To
---    do this we use a difference list (not a 'DList' - we use a \"real\"
---    difference list building on Haskell's lazy evaluation nature).
+--    do this with bounded memory usage we use a combination of continuation
+--    passing style and difference lists for the collected tokens.
 --
 --  * Haskell makes it so easy to roll your own parsing framework. We need some
 --    specialized machinery (limited lookahead, forbidden patterns). It is
@@ -435,23 +429,34 @@
 -- | A 'Parser' is basically a function computing a 'Reply'.
 data Parser result = Parser (State -> Reply result)
 
--- | A 'Reply' from a 'Parser'.
+-- | The 'Result' of each invocation is either an error, the actual result, or
+-- a continuation for computing the actual result.
+data Result result = Failed String        -- ^ Parsing aborted with a failure.
+                   | Result result        -- ^ Parsing completed with a result.
+                   | More (Parser result) -- ^ Parsing is ongoing with a continuation.
+
+-- Showing a 'Result' is only used in debugging.
+instance (Show result) => Show (Result result) where
+  show result = case result of
+                     Failed message -> "Failed " ++ message
+                     Result result  -> "Result " ++ (show result)
+                     More _         -> "More"
+
+-- | Each invication of a 'Parser' yields a 'Reply'. The 'Result' is only one
+-- part of the 'Reply'.
 data Reply result = Reply {
-    rResult     :: Either String result, -- ^ Error or parsing result.
-    rState      :: State,                -- ^ The updated parser state.
-    rTokens     :: D.DList Token,        -- ^ Tokens generated by the parser.
-    rCommits    :: D.DList String,       -- ^ Commitments to decision points.
-    rDidConsume :: Bool                  -- ^ Whether any characters were consumed.
+    rResult :: !(Result result), -- ^ Parsing result.
+    rTokens :: !(D.DList Token), -- ^ Tokens generated by the parser.
+    rCommit :: !(Maybe String),  -- ^ Commitment to a decision point.
+    rState  :: !State            -- ^ The updated parser state.
   }
 
--- Showing a 'State' is only used in debugging. Note that forcing dump of
--- @rTokens@, @rCommits@ or even @rDidConsume@ will prevent streaming them.
-instance Show (Reply result) where
-  show reply = -- "Result: " ++ (show $ reply|>rResult)
-               "State: { " ++ (show $ reply|>rState) ++ "}"
-            ++ ", Tokens: " ++ (show $ D.toList $ reply|>rTokens)
-            ++ ", Commits: " ++ (show $ D.toList $ reply|>rCommits)
-            ++ ", DidConsume: " ++ (show $ reply|>rDidConsume)
+-- Showing a 'State' is only used in debugging.
+instance (Show result) => Show (Reply result) where
+  show reply = "Result: "    ++ (show $ reply|>rResult)
+            ++ ", Tokens: "  ++ (show $ D.toList $ reply|>rTokens)
+            ++ ", Commit: "  ++ (show $ reply|>rCommit)
+            ++ ", State: { " ++ (show $ reply|>rState) ++ "}"
 
 -- A 'Pattern' is a parser that doesn't have an (interesting) result.
 type Pattern = Parser ()
@@ -469,52 +474,52 @@
     sForbidden    :: !(Maybe Pattern), -- ^ Pattern we must not enter into.
     sIsPeek       :: !Bool,            -- ^ Disables token generation.
     sChars        :: ![Char],          -- ^ (Reversed) characters collected for a token.
+    sOffset       :: !Int,             -- ^ Offset in characters in the input.
     sLine         :: !Int,             -- ^ Builds on YAML's line break definition.
     sColumn       :: !Int,             -- ^ Actually character number - we hate tabs.
     sCode         :: !Code,            -- ^ Of token we are collecting chars for.
     sLast         :: !Char,            -- ^ Last matched character.
-    sInput        :: [Char]            -- ^ The input decoded characters.
+    sInput        :: ![Char]           -- ^ The decoded input characters.
   }
 
 -- Showing a 'State' is only used in debugging. Note that forcing dump of
--- @sInput@ will disable streamin it.
+-- @sInput@ will disable streaming it.
 instance Show State where
-  show state = "Name: " ++ (show $ state|>sName)
+  show state = "Name: "       ++ (show $ state|>sName)
             ++ ", Encoding: " ++ (show $ state|>sEncoding)
             ++ ", Decision: " ++ (show $ state|>sDecision)
-            ++ ", Limit: " ++ (show $ state|>sLimit)
-            ++ ", IsPeek: " ++ (show $ state|>sIsPeek)
+            ++ ", Limit: "    ++ (show $ state|>sLimit)
+            ++ ", IsPeek: "   ++ (show $ state|>sIsPeek)
             ++ ", Chars: >>>" ++ (reverse $ state|>sChars) ++ "<<<"
-            ++ ", Line: " ++ (show $ state|>sLine)
-            ++ ", Column: " ++ (show $ state|>sColumn)
-            ++ ", Code: " ++ (show $ state|>sCode)
-            ++ ", Last: >>>" ++ (show $ state|>sLast) ++ "<<<"
+            ++ ", Offset: "   ++ (show $ state|>sOffset)
+            ++ ", Line: "     ++ (show $ state|>sLine)
+            ++ ", Column: "   ++ (show $ state|>sColumn)
+            ++ ", Code: "     ++ (show $ state|>sCode)
+            ++ ", Last: "     ++ (show $ state|>sLast)
 --          ++ ", Input: >>>" ++ (show $ state|>sInput) ++ "<<<"
 
 -- | @initialState name input@ returns an initial 'State' for parsing the
 -- /input/ (with /name/ for error messages).
 initialState :: String -> C.ByteString -> State
 initialState name input = let (encoding, decoded) = decode input
-                          in State { sName         = name,
-                                     sEncoding     = encoding,
-                                     sDecision     = "n/a",
-                                     sLimit        = -1,
-                                     sForbidden    = Nothing,
-                                     sIsPeek       = False,
-                                     sChars        = [],
-                                     sLine         = 1,
-                                     sColumn       = 0,
-                                     sCode         = Test,
-                                     sLast         = ' ',
-                                     sInput        = decoded }
+                          in State { sName      = name,
+                                     sEncoding  = encoding,
+                                     sDecision  = "",
+                                     sLimit     = -1,
+                                     sForbidden = Nothing,
+                                     sIsPeek    = False,
+                                     sChars     = [],
+                                     sOffset    = 0,
+                                     sLine      = 1,
+                                     sColumn    = 0,
+                                     sCode      = Test,
+                                     sLast      = ' ',
+                                     sInput     = decoded }
 
 -- *** Setters
 --
--- We need setter functions instead of using @{ sXxx = value }@ because the
--- nice syntax causes the old state to be fully evaluated, killing the
--- streaming (lazy) functionality we need. Generating the setters by hand was
--- tedious, there's surely a way to do this using Template Haskell or DrIFT or
--- some such. Life is too short.
+-- We need four setter functions to pass them around as arguments. For some
+-- reason, Haskell only generates getter functions.
 
 -- | @setDecision name state@ sets the @sDecision@ field to /decision/.
 setDecision :: String -> State -> State
@@ -543,12 +548,6 @@
 class Match parameter result | parameter -> result where
     match :: parameter -> Parser result
 
--- | @parse parser state@ applies the actual /parser/ match function to a
--- /state/.
-parse :: (Match match result) => match -> State -> Reply result
-parse parser state = let Parser parser' = match parser
-                     in parser' state
-
 -- | We don't need to convert a 'Parser', it already is one.
 instance Match (Parser result) result where
     match = id
@@ -567,104 +566,94 @@
 instance Match String () where
     match = foldr (&) empty
 
+-- ** Reply constructors
+
+-- | @returnReply state result@ prepares a 'Reply' with the specified /state/
+-- and /result/.
+returnReply :: State -> result -> Reply result
+returnReply state result = Reply { rResult = Result result,
+                                   rTokens = D.empty,
+                                   rCommit = Nothing,
+                                   rState  = state }
+
+-- | @tokenReply state token@ returns a 'Reply' containing the /state/ and
+-- /token/. Any collected characters are cleared (either there are none, or we
+-- put them in this token, or we don't want them).
+tokenReply state token = Reply { rResult = Result (),
+                                 rTokens = D.singleton token,
+                                 rCommit = Nothing,
+                                 rState  = state { sChars = [] } }
+
+-- | @failReply state message@ prepares a 'Reply' with the specified /state/
+-- and error /message/.
+failReply :: State -> String -> Reply result
+failReply state message = Reply { rResult = Failed $ state|>sName
+                                                  ++ ": line " ++ (show $ state|>sLine)
+                                                  ++ ": column " ++ (show $ state|>sColumn)
+                                                  ++ ": " ++ message,
+                                  rTokens = D.empty,
+                                  rCommit = Nothing,
+                                  rState  = state }
+
+-- | @unexpectedReply state@ returns a @failReply@ for an unexpected character.
+unexpectedReply :: State -> Reply result
+unexpectedReply state = case state|>sInput of
+                             (char:_) -> failReply state $ "Unexpected '" ++ [char] ++ "'"
+                             []       -> failReply state "Unexpected end of input"
+
 -- ** Parsing Monad
 
 -- | Allow using the @do@ notation for our parsers, which makes for short and
 -- sweet @do@ syntax when we want to examine the results (we typically don't).
---
--- We don't use the 'Monad' @fail@ method because we need access to the 'State'
--- on failure.
 instance Monad Parser where
 
-  -- | @return result@ does just that - return a /result/.
+  -- @return result@ does just that - return a /result/.
   return result = Parser $ \ state -> returnReply state result
 
-  -- | @left >>= right@ applies the /left/ parser, and if it didn't fail
-  -- applies the /right/ one (well, the one /right/ returns). For streaming it
-  -- is vital that we return a value "regardless" of the result of the left
-  -- parser. The fields in the reply are populated at different rates (in
-  -- particular, tokens are made available before the final result is known).
-  left >>= right =
-    Parser $ \ originalState -> let leftReply = parse left originalState
-                                    rightReply = case leftReply|>rResult of
-                                                      Right value   -> parse (right value) $ leftReply|>rState
-                                                      Left  message -> failReply (leftReply|>rState) message
-                                in bindReply leftReply rightReply
+  -- @left >>= right@ applies the /left/ parser, and if it didn't fail
+  -- applies the /right/ one (well, the one /right/ returns).
+  left >>= right = bindParser left right
+                   where bindParser (Parser left) right = Parser $ \ state ->
+                           let reply = left state
+                           in case reply|>rResult of
+                                   Failed message -> reply { rResult = Failed message }
+                                   Result value   -> reply { rResult = More $ right value }
+                                   More parser    -> reply { rResult = More $ bindParser parser right }
 
-  -- | @fail message@ does just that - failes with a /message/.
+  -- @fail message@ does just that - fails with a /message/.
   fail message = Parser $ \ state -> failReply state message
 
--- | @returnReply state result@ prepares a 'Reply' with the specified /state/
--- and /result/.
-returnReply :: State -> result -> Reply result
-returnReply state result = Reply { rResult     = Right result,
-                                   rState      = state,
-                                   rTokens     = D.empty,
-                                   rCommits    = D.empty,
-                                   rDidConsume = False }
-
--- NOTE: The profiler is blaming @bindReply@ at retaining old state and
--- reply objects. How come?
-
--- | @bindReply left right@ combines the replies of the /left/ and /right/
--- parsers to a single reply, allowing for generated 'Token' to be consumed
--- before parsing is completed.
-bindReply :: Reply result1 -> Reply result2 -> Reply result2
-bindReply left right = Reply { rResult     = right|>rResult,
-                               rState      = right|>rState,
-                               rTokens     = D.append (left|>rTokens) (right|>rTokens),
-                               rCommits    = D.append (left|>rCommits) (right|>rCommits),
-                               rDidConsume = (left|>rDidConsume) || (right|>rDidConsume) }
-
--- | @failReply state message@ prepares a 'Reply' with the specified /state/
--- and error /message/.
-failReply :: State -> String -> Reply result
-failReply state message = Reply { rResult     = Left $ state|>sName
-                                                    ++ ": line " ++ (show $ state|>sLine)
-                                                    ++ ": column " ++ (show $ state|>sColumn)
-                                                    ++ ": " ++ message,
-                                  rState      = state,
-                                  rTokens     = D.empty,
-                                  rCommits    = D.empty,
-                                  rDidConsume = False }
-
 -- ** Parsing operators
 --
--- Here we reap the benefits of renaming the numerical operators. Note that in
--- our specific case, we use the 'MonadPlus' to combine the results of
--- different parsers. Typically, parsing frameworks simply use the last result,
--- or leave the task of combining them to the rules themselves (using @do@
--- notation).
---
--- Operator precedence, in decreasing strength:
+-- Here we reap the benefits of renaming the numerical operators. The Operator
+-- precedence, in decreasing strength:
 --
 -- @repeated % n@, @repeated <% n@, @match - rejected@, @match ! decision@,
--- @match ?! decision@ are the strongest binding, and don't mix.
+-- @match ?! decision@, @choice ^ (first \/ second)@.
 --
 -- @match - first - second@ is @(match - first) - second@.
 --
 -- @first & second & third@ is @first & (second & third)@. Note that @first -
--- rejected & second@ is @(first - rejected) & second@, etc. d@ is @a & (b - c)
--- & d@.
+-- rejected & second@ is @(first - rejected) & second@, etc.
 --
 -- @match \/ alternative \/ otherwise@ is @match \/ (alternative \/
 -- otherwise)@. Note that @first & second \/ third@ is @(first & second) \/
 -- third@.
 --
 -- @( match *)@, @(match +)@, @(match ?)@ are the weakest and require the
--- @()@.
+-- surrounding @()@.
 
+infix  3 ^
 infix  3 %
 infix  3 <%
-infix  3 ^
 infix  3 !
 infix  3 ?!
 infixl 3 -
 infixr 2 &
 infixr 1 /
-infix 0 ?
-infix 0 *
-infix 0 +
+infix  0 ?
+infix  0 *
+infix  0 +
 
 -- | @parser % n@ repeats /parser/ exactly /n/ times.
 (%) :: (Match match result) => match -> Int -> Pattern
@@ -672,10 +661,17 @@
   | n <= 0 = empty
   | n > 0  = parser & parser % n .- 1
 
+-- | @parser <% n@ matches fewer than /n/ occurrences of /parser/.
+(<%) :: (Match match result) => match -> Int -> Pattern
+parser <% n
+  | n < 1 = fail "Fewer than 0 repetitions"
+  | n == 1 = reject parser Nothing
+  | n > 1  = "<%" ^ ( parser ! "<%" & parser <% n .- 1 / empty )
+
 -- | @decision ^ (option \/ option \/ ...)@ provides a /decision/ name to the
 -- choice about to be made, to allow to @commit@ to it.
 (^) :: (Match match result) => String -> match -> Parser result
-decision ^ parser = decide decision parser
+decision ^ parser = choice decision (match parser)
 
 -- | @parser ! decision@ commits to /decision/ after successfully matching the
 -- /parser/.
@@ -687,103 +683,121 @@
 (?!) :: (Match match result) => match -> String -> Pattern
 parser ?! decision = peek parser & commit decision
 
--- | @parser <% n@ matches fewer than /n/ occurrences of /parser/.
-(<%) :: (Match match result) => match -> Int -> Pattern
-parser <% n
-  | n < 1 = fail "Fewer than 0 repetitions"
-  | n == 1 = reject parser Nothing
-  | n > 1  = "<%" ^ ( parser ! "<%" & parser <% n .- 1 / empty )
-
 -- | @parser - rejected@ matches /parser/, except if /rejected/ matches at this
 -- point.
 (-) :: (Match match1 result1, Match match2 result2) => match1 -> match2 -> Parser result1
 parser - rejected = reject rejected Nothing & parser
 
 -- | @before & after@ parses /before/ and, if it succeeds, parses /after/. This
--- basically invokes the monad's @>>=@ method.
+-- basically invokes the monad's @>>=@ (bind) method.
 (&) :: (Match match1 result1, Match match2 result2) => match1 -> match2 -> Parser result2
 before & after = (match before) >> (match after)
 
 -- | @first \/ second@ tries to parse /first/, and failing that parses
 -- /second/, unless /first/ has committed in which case is fails immediately.
--- To achieve streaming, we need to construct the final state manually, passing
--- the commitments through \"regardless\" of the results of either parsers.
--- This allows our caller to start consuming tokens from a committed option
--- before it is done parsing.
 (/) :: (Match match1 result, Match match2 result) => match1 -> match2 -> Parser result
-first / second =
-  Parser $ \ originalState -> let decision = originalState|>sDecision
-                                  nestState = originalState { sDecision = "n/a" }
-                                  firstReply = parse first nestState
-                                  (firstIsCommitted, firstCommits) = commitStatus "n/a" decision $ D.toList $ firstReply|>rCommits
-                              in if firstIsCommitted
-                                    then firstReply { rCommits = firstCommits }
-                                    else case firstReply|>rResult of
-                                              Right _ -> firstReply { rCommits = firstCommits }
-                                              Left  _ -> let secondReply = parse second nestState
-                                                             (_, secondCommits) = commitStatus "n/a" decision $ D.toList $ secondReply|>rCommits
-                                                         in secondReply { rCommits = secondCommits }
-  where commitStatus :: String -> String -> [String] -> (Bool, D.DList String)
-        commitStatus prev decision []                             = (False, D.empty)
-        commitStatus prev decision (name:rest) | name == decision = (True, snd $ commitStatus prev decision rest)
-                                               | name == prev     = (True, snd $ commitStatus prev decision rest)
-                                               | otherwise        = (True, D.cons name $ snd $ commitStatus name decision rest)
+first / second = Parser $ \ state ->
+  let Parser parser = decide (match first) (match second)
+  in  parser state
 
--- | @(parser ?)@ (optional) tries to match /parser/, otherwise does nothing.
+-- | @(optional ?)@ tries to match /parser/, otherwise does nothing.
 (?) :: (Match match result) => match -> Pattern
-(?) parser = Parser $ \ state -> let reply = parse parser state
-                                 in case reply|>rResult of
-                                         Right _ -> reply { rResult = Right () }
-                                         Left  _ -> returnReply state ()
+(?) optional = "?" ^ (optional & empty / empty)
 
--- | @(parser *)@ matches zero or more occurrences of /parser/. Tricky
--- optimization: we only return the commitments of the first match. In the YAML
--- syntax, the additional occurences will only repeat them.
+-- | @(parser *)@ matches zero or more occurrences of /repeat/, as long as each
+-- one actually consumes input characters.
 (*) :: (Match match result) => match -> Pattern
-(*) parser = Parser zero_or_more
-             where zero_or_more state = let reply = parse parser state
-                                        in case (reply|>rResult, reply|>rDidConsume) of
-                                                (Left  _,  _)     -> returnReply state ()
-                                                (Right _,  False) -> returnReply state ()
-                                                (Right _,  True)  -> let reply' = zero_or_more $ reply|>rState
-                                                                     in bindReply reply reply' { rCommits = D.empty }
+(*) parser = "*" ^ zomParser
+  where zomParser = (nonEmpty parser ! "*" & zomParser) / empty
 
--- | @(parser +)@ matches one or more occurrences of /parser/.
+-- | @(parser +)@ matches one or more occurrences of /parser/, as long as each
+-- one actually consumed input characters.
 (+) :: (Match match result) => match -> Pattern
-(+) parser = parser & (parser *)
+(+) parser = nonEmpty parser & (parser *)
 
 -- ** Basic parsers
 
--- | @traced name parser@ traces all invocations to the parser. Is only used when
--- debugging.
-traced :: (Match match result, Show result) => String -> match -> Parser result
-traced name parser = Parser $ \ state -> trace_reply name $ parse parser $ trace_call name state
+-- | @decide first second@ tries to parse /first/, and failing that parses
+-- /second/, unless /first/ has committed in which case is fails immediately.
+decide :: Parser result -> Parser result -> Parser result
+decide left right = Parser $ \ state ->
+  let Parser parser = decideParser state D.empty left right
+  in  parser state
+  where decideParser point tokens (Parser left) right = Parser $ \state ->
+          let reply = left state
+              tokens' reply = D.append tokens $ reply|>rTokens
+          in case (reply|>rResult, reply|>rCommit) of
+                  (Failed _,    _)      -> Reply { rState  = point,
+                                                   rTokens = D.empty,
+                                                   rResult = More right,
+                                                   rCommit = Nothing }
+                  (Result _,   _)       -> reply { rTokens = tokens' reply }
+                  (More left', Just _)  -> reply { rTokens = tokens' reply,
+                                                   rResult = More left' }
+                  (More left', Nothing) -> let Parser parser = decideParser point (tokens' reply) left' right
+                                     in  parser $ reply|>rState
 
--- | @trace_call name state@ traces the /state/ at the start of the call to /name/.
-trace_call :: String -> State -> State
-trace_call name state = trace ("Call " ++ name ++ " with " ++ (show state)) state
+-- | @choice decision parser@ provides a /decision/ name to the choice about to
+-- be made in /parser/, to allow to @commit@ to it.
+choice :: String -> Parser result -> Parser result
+choice decision parser = Parser $ \ state ->
+  let Parser parser' = choiceParser (state|>sDecision) decision parser
+  in parser' state { sDecision = decision }
+  where choiceParser parentDecision makingDecision (Parser parser) = Parser $ \ state ->
+          let reply   = parser state
+              commit' = case reply|>rCommit of
+                             Nothing                                    -> Nothing
+                             Just decision | decision == makingDecision -> Nothing
+                                           | otherwise                  -> reply|>rCommit
+              reply'  = case reply|>rResult of
+                             More parser' -> reply { rCommit = commit',
+                                                     rResult = More $ choiceParser parentDecision makingDecision parser' }
+                             _            -> reply { rCommit = commit',
+                                                     rState = (reply|>rState) { sDecision = parentDecision } }
+          in reply'
 
--- | @trace_call name reply@ traces the /reply/ from calling /name/.
-trace_reply :: Show result => String -> Reply result -> Reply result
-trace_reply name reply = trace ("Done " ++ name ++ " with " ++ (show reply)) reply
+-- | @peek parser@ succeeds if /parser/ matches at this point, but does not
+-- consume any input.
+peek :: (Match match result) => match -> Parser result
+peek parser = Parser $ \ state ->
+  peekParser state (match parser) state { sIsPeek = True }
+  where peekParser point (Parser parser) state =
+          let reply = parser state
+          in case reply|>rResult of
+                  Failed message -> failReply point message
+                  Result value   -> returnReply point value
+                  More parser'   -> peekParser point parser' $ reply|>rState
 
--- | @reject rejected name@ fails if /rejected/ matches at this point, and does
+-- | @reject parser name@ fails if /parser/ matches at this point, and does
 -- nothing otherwise. If /name/ is provided, it is used in the error message,
 -- otherwise the messages uses the current character.
 reject :: (Match match result) => match -> Maybe String -> Pattern
-reject rejected name = Parser $ \ state -> let reply = parse rejected state { sIsPeek = True }
-                                           in case (reply|>rResult, name) of
-                                                   (Left  _, _)         -> returnReply state ()
-                                                   (Right _, Nothing)   -> unexpectedReply state
-                                                   (Right _, Just text) -> failReply state $ "Unexpected " ++ text
+reject parser name = Parser $ \ state ->
+  rejectParser state name (match parser) state { sIsPeek = True }
+  where rejectParser point name (Parser parser) state =
+          let reply = parser state
+          in case reply|>rResult of
+                  Failed message -> returnReply point ()
+                  Result value   -> case name of
+                                         Nothing   -> unexpectedReply point
+                                         Just text -> failReply point $ "Unexpected " ++ text
+                  More parser'   -> rejectParser point name parser' $ reply|>rState
 
--- | @peek parser@ succeeds if /parser/ matches at this point, but does not
--- consume any input.
-peek :: (Match match result) => match -> Parser result
-peek parser = Parser $ \ state -> let reply = parse parser state { sIsPeek = True }
-                                  in case reply|>rResult of
-                                          Right value -> returnReply state value
-                                          Left  _     -> failReply state "Peek failed"
+-- | @nonEmpty parser@ succeeds if /parser/ matches some non-empty input
+-- characters at this point.
+nonEmpty :: (Match match result) => match -> Parser result
+nonEmpty parser = Parser $ \ state ->
+  let Parser parser' = nonEmptyParser (state|>sOffset) (match parser)
+  in parser' state
+  where nonEmptyParser offset (Parser parser) = Parser $ \ state ->
+          let reply = parser state
+              state' = reply|>rState
+          in case reply|>rResult of
+                  Failed message -> reply
+                  Result value   -> if state'|>sOffset > offset
+                                       then reply
+                                       else failReply state' "Matched empty pattern"
+                  More parser'   -> reply { rResult = More $ nonEmptyParser offset parser' }
 
 -- | @empty@ always matches without consuming any input.
 empty :: Pattern
@@ -791,48 +805,51 @@
 
 -- | @eof@ matches the end of the input.
 eof :: Pattern
-eof = Parser $ \ state -> if state|>sInput == []
-                             then returnReply state ()
-                             else failReply state "Expected end of input"
+eof = Parser $ \ state ->
+  if state|>sInput == []
+     then returnReply state ()
+     else failReply state "Expected end of input"
 
 -- | @sol@ matches the start of a line.
 sol :: Pattern
-sol = Parser $ \ state -> if state|>sColumn == 0
-                             then returnReply state ()
-                             else failReply state "Expected start of line"
+sol = Parser $ \ state ->
+  if state|>sColumn == 0
+     then returnReply state ()
+     else failReply state "Expected start of line"
 
 -- ** State manipulation pseudo-parsers
 
--- | @incrLine@ increments @sLine@ counter resets @sColumn@.
+-- | @commit decision@ commits the parser to all the decisions up to the most
+-- recent parent /decision/. This makes all tokens generated in this parsing
+-- path immediately available to the caller.
+commit :: String -> Pattern
+commit decision = Parser $ \ state ->
+  Reply { rState  = state,
+          rTokens = D.empty,
+          rResult = Result (),
+          rCommit = Just decision }
+
+-- | @nextLine@ increments @sLine@ counter and resets @sColumn@.
 nextLine :: Pattern
-nextLine = Parser $ \ state -> returnReply state { sLine = state|>sLine .+ 1,
-                                                   sColumn = 0 }
-                                           ()
+nextLine = Parser $ \ state ->
+  returnReply state { sLine = state|>sLine .+ 1,
+                      sColumn = 0 }
+              ()
 
 -- | @with setField getField value parser@ invokes the specified /parser/ with
 -- the value of the specified field set to /value/ for the duration of the
 -- invocation, using the /setField/ and /getField/ functions to manipulate it.
 with :: (value -> State -> State) -> (State -> value) -> value -> Parser result -> Parser result
-with setField getField value parser = Parser $ \ originalState -> let originalValue = getField originalState
-                                                                      withState = setField value originalState
-                                                                      reply = parse parser withState
-                                                                      finalState = setField originalValue $ reply|>rState
-                                                                  in reply { rState = finalState }
-
--- | @decide name (a / b / ...)@ names the contained decision point so it can be
--- addressed by later @commit@ calls.
-decide :: (Match match result) => String -> match -> Parser result
-decide decision parser = with setDecision sDecision decision $ match parser
-
--- | @commit name@ commits the parser to all the decisions up to the most recent
--- containing decision with the specified /name/. This makes all tokens
--- generated in this parsing path immediately available to the caller.
-commit :: String -> Pattern
-commit name = Parser $ \ state -> Reply { rResult = Right (),
-                                          rState = state,
-                                          rTokens = D.empty,
-                                          rCommits = D.singleton name,
-                                          rDidConsume = False }
+with setField getField value parser = Parser $ \ state ->
+  let value' = getField state
+      Parser parser' = value' `seq` withParser value' parser
+  in  parser' $ setField value state
+  where withParser parentValue (Parser parser) = Parser $ \ state ->
+          let reply = parser state
+          in case reply|>rResult of
+                  Failed _     -> reply { rState = setField parentValue $ reply|>rState }
+                  Result _     -> reply { rState = setField parentValue $ reply|>rState }
+                  More parser' -> reply { rResult = More $ withParser parentValue parser' }
 
 -- | @parser ``forbidding`` pattern@ parses the specified /parser/ ensuring
 -- that it does not contain anything matching the /forbidden/ parser.
@@ -850,59 +867,45 @@
 -- pattern or if the 'State' lookahead limit is reached. Otherwise it consumes
 -- (and buffers) the next input char if it satisfies /test/.
 nextIf :: (Char -> Bool) -> Pattern
-nextIf test = Parser $ \ state -> case state|>sForbidden of
-                                       Nothing     -> limitedNextIf state
-                                       Just parser -> let reply = parse parser state { sIsPeek = True,
-                                                                                       sForbidden = Nothing }
-                                                      in case reply|>rResult of
-                                                              Left  _ -> limitedNextIf state
-                                                              Right _ -> failReply state "Forbidden pattern detected"
-              where limitedNextIf state = case state|>sLimit of
-                                               -1    -> consumeNextIf state
-                                               0     -> failReply state "Lookahead limit reached"
-                                               limit -> consumeNextIf state { sLimit = state|>sLimit .- 1 }
-                    consumeNextIf state = case state|>sInput of
-                                               (char:rest) | test char -> let chars = if state|>sIsPeek
-                                                                                         then []
-                                                                                         else char:(state|>sChars)
-                                                                              state' = state { sInput = rest,
-                                                                                               sLast = char,
-                                                                                               sChars = chars,
-                                                                                               sColumn = state|>sColumn .+ 1 }
-                                                                          in Reply { rResult = Right (),
-                                                                                     rState = state',
-                                                                                     rTokens = D.empty,
-                                                                                     rCommits = D.empty,
-                                                                                     rDidConsume = True }
-                                                           | otherwise -> unexpectedReply state
-                                               []                      -> unexpectedReply state
-
--- | @unexpectedReply state@ returns a @failReply@ for an unexpected character.
-unexpectedReply :: State -> Reply ()
-unexpectedReply state = case state|>sInput of
-                             (char:_) -> failReply state $ "Unexpected '" ++ [char] ++ "'"
-                             []       -> failReply state "Unexpected end of input"
+nextIf test = Parser $ \ state ->
+  case state|>sForbidden of
+       Nothing     -> limitedNextIf state
+       Just parser -> let Parser parser' = reject parser $ Just "forbidden pattern"
+                          reply = parser' state { sForbidden = Nothing }
+                      in case reply|>rResult of
+                              Failed _ -> reply
+                              Result _ -> limitedNextIf state
+  where limitedNextIf state =
+          case state|>sLimit of
+               -1    -> consumeNextIf state
+               0     -> failReply state "Lookahead limit reached"
+               limit -> consumeNextIf state { sLimit = state|>sLimit .- 1 }
+        consumeNextIf state =
+          case state|>sInput of
+               (char:rest) | test char -> let chars = if state|>sIsPeek
+                                                         then []
+                                                         else char:(state|>sChars)
+                                              state' = state { sInput = rest,
+                                                               sLast = char,
+                                                               sChars = chars,
+                                                               sOffset = state|>sOffset .+ 1,
+                                                               sColumn = state|>sColumn .+ 1 }
+                                          in returnReply state' ()
+                           | otherwise -> unexpectedReply state
+               []                      -> unexpectedReply state
 
 -- ** Producing tokens
 
 -- | @finishToken@ places all collected text into a new token and begins a new
 -- one, or does nothing if there are no collected characters.
 finishToken :: Pattern
-finishToken = Parser $ \ state -> if state|>sIsPeek
-                                     then returnReply state ()
-                                     else case state|>sChars of
-                                               []          -> returnReply state ()
-                                               chars@(_:_) -> tokenReply state Token { tCode = state|>sCode,
-                                                                                       tText = reverse chars }
-
--- | @tokenReply state token@ returns a 'Reply' containing the /state/ and
--- /token/. Any collected characters are cleared (either there are none, or we
--- put them in this token, or we don't want them).
-tokenReply state token = Reply { rResult = Right (),
-                                 rState = state { sChars = [] },
-                                 rTokens = D.singleton token,
-                                 rCommits = D.empty,
-                                 rDidConsume = False }
+finishToken = Parser $ \ state ->
+  if state|>sIsPeek
+     then returnReply state ()
+     else case state|>sChars of
+               []          -> returnReply state ()
+               chars@(_:_) -> tokenReply state Token { tCode = state|>sCode,
+                                                       tText = reverse chars }
 
 -- | @wrap parser@ invokes the /parser/, ensures any unclaimed input characters
 -- are wrapped into a token (only happens when testing productions), ensures no
@@ -918,9 +921,9 @@
 consume :: (Match match result) => match -> Parser result
 consume parser = do result <- match parser
                     finishToken
-                    clear_input
+                    clearInput
                     return result
-                 where clear_input = Parser $ \ state -> returnReply state { sInput = [] } ()
+                 where clearInput = Parser $ \ state -> returnReply state { sInput = [] } ()
 
 -- | @token code parser@ places all text matched by /parser/ into a 'Token' with
 -- the specified /code/ (unless it is empty). Note it collects the text even if
@@ -931,10 +934,11 @@
 -- | @fake code text@ creates a token with the specified /code/ and \"fake\"
 -- /text/ characters, instead of whatever characters are collected so far.
 fake :: Code -> String -> Pattern
-fake code text = Parser $ \ state -> if state|>sIsPeek
-                                        then returnReply state ()
-                                        else tokenReply state Token { tCode = code,
-                                                                      tText = text }
+fake code text = Parser $ \ state ->
+  if state|>sIsPeek
+     then returnReply state ()
+     else tokenReply state Token { tCode = code,
+                                   tText = text }
 
 -- | @meta parser@ collects the text matched by the specified /parser/ into a
 -- | @Meta@ token.
@@ -954,12 +958,12 @@
 -- | @nest code@ returns an empty token with the specified begin\/end /code/ to
 -- signal nesting.
 nest :: Code -> Pattern
-nest code = Parser $ \ state -> if state|>sIsPeek
-                                   then returnReply state ()
-                                   else let left = parse finishToken state
-                                            right = tokenReply state Token { tCode = code,
-                                                                             tText = "" }
-                                        in bindReply left right
+nest code = finishToken & nestParser code
+  where nestParser code = Parser $ \ state ->
+          if state|>sIsPeek
+             then returnReply state ()
+             else tokenReply state Token { tCode = code,
+                                           tText = "" }
 
 -- * Production parameters
 
@@ -1046,66 +1050,54 @@
 -- implementation details from our callers.
 
 -- | 'Tokenizer' converts a (named) input text into a list of 'Token'. Errors
--- are reported as tokens.
+-- are reported as tokens with the @Error@ 'Code'.
 type Tokenizer = String -> C.ByteString -> [Token]
 
 -- | @patternTokenizer pattern@ converts the /pattern/ to a simple 'Tokenizer'.
--- Note how using difference lists we can tuck the error token at the end of
--- the result without preventing the streaming.
 patternTokenizer :: Pattern -> Tokenizer
 patternTokenizer pattern name input =
-  let reply = parse (wrap pattern) (initialState name input)
-      last = case reply|>rResult of
-                  Right _       -> D.empty
-                  Left  message -> D.singleton Token { tCode = Error,
-                                                       tText = message }
-      bugs = commitBugs "n/a" $ D.toList $ reply|>rCommits
-      errors = D.append bugs last
-  in D.toList $ D.append (reply|>rTokens) errors
-
-{- NOTE: the 'debug-leak' production will run in constant memory "forever" when
- - using the following instead - that is, discarding the result and
- - commitments.
-
-patternTokenizer pattern name input =
-  let reply = parse pattern (initialState name input)
-  in D.toList $ reply|>rTokens
-
--}
+  D.toList $ patternParser (wrap pattern) (initialState name input)
+  where patternParser (Parser parser) state =
+          let reply = parser state
+              tokens = commitBugs reply
+          in case reply|>rResult of
+                  Failed message -> D.append tokens $ D.singleton Token { tCode = Error,
+                                                                          tText = message }
+                  Result _       -> tokens
+                  More parser'   -> D.append tokens $ patternParser parser' $ reply|>rState
 
 -- | @parserTokenizer what parser@ converts the /parser/ returning /what/ to a
--- simple 'Tokenizer' (only used for tests). Note how using difference lists we
--- can tuck the result or error token at the end of the result without
--- preventing the streaming.
+-- simple 'Tokenizer' (only used for tests). The result is reported as a token
+-- with the @Detected@ 'Code' The result is reported as a token with the
+-- @Detected@ 'Code'.
 parserTokenizer :: (Show result, Match match result) => String -> match -> Tokenizer
 parserTokenizer what parser name input =
-  let reply = parse (wrap parser) (initialState name input)
-      last = case reply|>rResult of
-                  Right value   -> Token { tCode = Detected,
-                                           tText = what ++ "=" ++ (show value) }
-                  Left  message -> Token { tCode = Error,
-                                           tText = message }
-      bugs = commitBugs "n/a" $ D.toList $ reply|>rCommits
-      errors = D.snoc bugs last
-  in D.toList $ D.append (reply|>rTokens) errors
+  D.toList $ parserParser (wrap parser) (initialState name input)
+  where parserParser (Parser parser) state =
+          let reply = parser state
+              tokens = commitBugs reply
+          in case reply|>rResult of
+                  Failed message -> D.append tokens $ D.singleton Token { tCode = Error,
+                                                                          tText = message }
+                  Result value  -> D.append tokens $ D.singleton Token { tCode = Detected,
+                                                                         tText = what ++ "=" ++ (show value) }
+                  More parser'  -> D.append tokens $ parserParser parser' $ reply|>rState
 
--- | @commitBugs commits@ converts any @commit@ calls made outside the decision
--- they refer to into an error token. No such calls should exists outside
--- tests.
-commitBugs :: String -> [String] -> D.DList Token
-commitBugs prev [] = D.empty
-commitBugs prev (decision:rest)
-  | decision == prev = commitBugs prev rest
-  | otherwise        = D.cons Token { tCode = Error,
-                                      tText = "Commit to '" ++ decision ++ "' was made outside it" }
-                            $ commitBugs decision rest
+-- | @commitBugs reply@ inserts an error token if a commit was made outside a
+-- named choice. This should never happen outside tests.
+commitBugs :: Reply result -> D.DList Token
+commitBugs reply =
+  let tokens = reply|>rTokens
+  in case reply|>rCommit of
+          Nothing     -> tokens
+          Just commit -> D.append tokens $ D.singleton Token { tCode = Error,
+                                                               tText = "Commit to '" ++ commit ++ "' was made outside it" }
 
 -- | @yaml name input@ converts the Unicode /input/ (called /name/ in error
 -- messages) to a list of 'Token' according to the YAML spec. This is it!
 yaml :: Tokenizer
 yaml = patternTokenizer l_yaml_stream
 
--- CPP LINES CAUSE HADDOCK TO BARF --
 #ifdef REAL_CPP
 -- This is how non-ancient C pre-processor do it.
 #define STR(X) #X
@@ -1117,7 +1109,6 @@
 #define PAT(PATTERN) pat STR(PATTERN) PATTERN
 #define PAR(PARSER)  par STR(PARSER)  PARSER
 #define PAC(PARSER)  pac STR(PARSER)  PARSER
--- CPP LINES CAUSE HADDOCK TO BARF --
 
 -- | @pName name@ converts a parser name to the \"proper\" spec name.
 pName :: String -> String
@@ -1134,7 +1125,6 @@
 tokenizers :: Map.Map String Tokenizer
 tokenizers = PAR(c_chomping_indicator) "t"
            $ PAC(detect_inline_indentation) "m"
-           $ PAT(debug_leak)
            $ PAT(b_as_line_feed)
            $ PAT(b_carriage_return)
            $ PAT(b_char)
@@ -1496,7 +1486,8 @@
                                                           UTF8    -> "TF8"
                                                           UTF16LE -> "TF16LE"
                                                           UTF16BE -> "TF16BE"
-                                          in parse (fake Bom text) state { sColumn = state|>sColumn .- 1 }
+                                              Parser parser = fake Bom text
+                                          in  parser state { sColumn = state|>sColumn .- 1 }
 
 -- | @na@ is the \"non-applicable\" indentation value. We use Haskell's laziness
 -- to verify it really is never used.
@@ -1514,8 +1505,4 @@
 result :: result -> Parser result
 result = return
 
--- CPP LINES CAUSE HADDOCK TO BARF --
 #include "Reference.bnf"
--- CPP LINES CAUSE HADDOCK TO BARF --
-
-debug_leak = ( c_comment & b_line_feed *)
diff --git a/YamlReference.cabal b/YamlReference.cabal
--- a/YamlReference.cabal
+++ b/YamlReference.cabal
@@ -1,5 +1,5 @@
 Name:            YamlReference
-Version:         0.2
+Version:         0.3
 License:         LGPL
 License-File:    lgpl.txt
 Copyright:       Oren Ben-Kiki 2007
@@ -7,7 +7,7 @@
 Maintainer:      yaml-oren@ben-kiki.org
 Stability:       alpha
 Homepage:        www.ben-kiki.org/oren/YamlReference
-Package-Url:     www.ben-kiki.org/oren/YamlReference/YamlReference-0.2.tar.gz
+Package-Url:     www.ben-kiki.org/oren/YamlReference/YamlReference-0.3.tar.gz
 Category:        Text
 Synopsis:        YAML reference implementation
 Description:     This package contains \"the\" reference YAML syntax parser
@@ -20,15 +20,12 @@
                  interesting tools on top of it, such as the @yeast2html@ YAML
                  syntax visualizer (contained in this package), pretty
                  printers, etc. This is a streaming parser that will
-                 \"immediately\" begin to generate output, but it has a memory
-                 leak (actually, retention) problem that prevents it from being
-                 applied to \"large\" files. To debug this with minimal syntax
-                 productions use @yes "#" | yaml2yeast -p debug-leak@.
+                 \"immediately\" begin to generate output. The memory leak that
+                 existed in previous version has been plugged.
 Build-Depends:   base >= 2.0, HUnit >= 1.1, regex-compat >= 0.71, dlist >= 0.2
 Exposed-Modules: Text.Yaml.Reference
 Extensions:      CPP, MultiParamTypeClasses
 Data-Files:      Text/Yaml/Reference.bnf yeast2html yaml2yeast.css
-                 tests/debug-leak.input tests/debug-leak.output
                  tests/b-as-line-feed.input tests/b-as-line-feed.output
                  tests/b-carriage-return.input tests/b-carriage-return.output
                  tests/b-char.cr.input tests/b-char.cr.output
diff --git a/tests/c-b+block-header.n=2.s=folded.i.output b/tests/c-b+block-header.n=2.s=folded.i.output
--- a/tests/c-b+block-header.n=2.s=folded.i.output
+++ b/tests/c-b+block-header.n=2.s=folded.i.output
@@ -1,4 +1,4 @@
 I>
-b\x0a
 !Commit to 'node' was made outside it
+b\x0a
 $(m,t)=(1,clip)
diff --git a/tests/c-b+block-header.n=2.s=folded.im.output b/tests/c-b+block-header.n=2.s=folded.im.output
--- a/tests/c-b+block-header.n=2.s=folded.im.output
+++ b/tests/c-b+block-header.n=2.s=folded.im.output
@@ -1,5 +1,5 @@
 I>
+!Commit to 'node' was made outside it
 I7
 b\x0a
-!Commit to 'node' was made outside it
 $(m,t)=(7,clip)
diff --git a/tests/c-b+block-header.n=2.s=folded.imt.output b/tests/c-b+block-header.n=2.s=folded.imt.output
--- a/tests/c-b+block-header.n=2.s=folded.imt.output
+++ b/tests/c-b+block-header.n=2.s=folded.imt.output
@@ -1,6 +1,6 @@
 I>
+!Commit to 'node' was made outside it
 I7
 I-
 b\x0a
-!Commit to 'node' was made outside it
 $(m,t)=(7,strip)
diff --git a/tests/c-b+block-header.n=2.s=folded.it.output b/tests/c-b+block-header.n=2.s=folded.it.output
--- a/tests/c-b+block-header.n=2.s=folded.it.output
+++ b/tests/c-b+block-header.n=2.s=folded.it.output
@@ -1,5 +1,5 @@
 I>
+!Commit to 'node' was made outside it
 I-
 b\x0a
-!Commit to 'node' was made outside it
 $(m,t)=(1,strip)
diff --git a/tests/c-b+block-header.n=2.s=folded.itm.output b/tests/c-b+block-header.n=2.s=folded.itm.output
--- a/tests/c-b+block-header.n=2.s=folded.itm.output
+++ b/tests/c-b+block-header.n=2.s=folded.itm.output
@@ -1,6 +1,6 @@
 I>
+!Commit to 'node' was made outside it
 I-
 I7
 b\x0a
-!Commit to 'node' was made outside it
 $(m,t)=(7,strip)
diff --git a/tests/c-double-quoted.n=4.c=flow-out.invalid.output b/tests/c-double-quoted.n=4.c=flow-out.invalid.output
--- a/tests/c-double-quoted.n=4.c=flow-out.invalid.output
+++ b/tests/c-double-quoted.n=4.c=flow-out.invalid.output
@@ -1,5 +1,5 @@
 S
 I"
-Ta
 !Commit to 'node' was made outside it
+Ta
 !$InputFile$: line 1: column 2: Unexpected '\x0a'
diff --git a/tests/c-double-quoted.n=4.c=flow-out.output b/tests/c-double-quoted.n=4.c=flow-out.output
--- a/tests/c-double-quoted.n=4.c=flow-out.output
+++ b/tests/c-double-quoted.n=4.c=flow-out.output
@@ -1,5 +1,6 @@
 S
 I"
+!Commit to 'node' was made outside it
 T a
 w 
 l\x0a
@@ -8,4 +9,3 @@
 Ta b\x09c 
 I"
 s
-!Commit to 'node' was made outside it
diff --git a/tests/c-flow-json-content.n=4.c=flow-in.double.output b/tests/c-flow-json-content.n=4.c=flow-in.double.output
--- a/tests/c-flow-json-content.n=4.c=flow-in.double.output
+++ b/tests/c-flow-json-content.n=4.c=flow-in.double.output
@@ -1,6 +1,6 @@
 S
 I"
+!Commit to 'node' was made outside it
 Ta
 I"
 s
-!Commit to 'node' was made outside it
diff --git a/tests/c-flow-json-content.n=4.c=flow-in.mapping.output b/tests/c-flow-json-content.n=4.c=flow-in.mapping.output
--- a/tests/c-flow-json-content.n=4.c=flow-in.mapping.output
+++ b/tests/c-flow-json-content.n=4.c=flow-in.mapping.output
@@ -1,5 +1,6 @@
 M
 I{
+!Commit to 'node' was made outside it
 X
 N
 S
@@ -10,10 +11,10 @@
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
 x
 I}
 m
-!Commit to 'node' was made outside it
diff --git a/tests/c-flow-json-content.n=4.c=flow-in.sequence.output b/tests/c-flow-json-content.n=4.c=flow-in.sequence.output
--- a/tests/c-flow-json-content.n=4.c=flow-in.sequence.output
+++ b/tests/c-flow-json-content.n=4.c=flow-in.sequence.output
@@ -1,5 +1,6 @@
 Q
 I[
+!Commit to 'node' was made outside it
 N
 S
 Ta
@@ -7,4 +8,3 @@
 n
 I]
 q
-!Commit to 'node' was made outside it
diff --git a/tests/c-flow-json-node.n=4.c=flow-in.tagged.output b/tests/c-flow-json-node.n=4.c=flow-in.tagged.output
--- a/tests/c-flow-json-node.n=4.c=flow-in.tagged.output
+++ b/tests/c-flow-json-node.n=4.c=flow-in.tagged.output
@@ -10,8 +10,8 @@
 w 
 S
 I"
+!Commit to 'node' was made outside it
 Ta
 I"
 s
 n
-!Commit to 'node' was made outside it
diff --git a/tests/c-flow-json-node.n=4.c=flow-in.untagged.output b/tests/c-flow-json-node.n=4.c=flow-in.untagged.output
--- a/tests/c-flow-json-node.n=4.c=flow-in.untagged.output
+++ b/tests/c-flow-json-node.n=4.c=flow-in.untagged.output
@@ -1,8 +1,8 @@
 N
 S
 I"
+!Commit to 'node' was made outside it
 Ta
 I"
 s
 n
-!Commit to 'node' was made outside it
diff --git a/tests/c-flow-mapping.n=4.c=flow-in.compact.output b/tests/c-flow-mapping.n=4.c=flow-in.compact.output
--- a/tests/c-flow-mapping.n=4.c=flow-in.compact.output
+++ b/tests/c-flow-mapping.n=4.c=flow-in.compact.output
@@ -1,5 +1,6 @@
 M
 I{
+!Commit to 'node' was made outside it
 X
 N
 S
@@ -11,6 +12,7 @@
 I:
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
@@ -39,6 +41,7 @@
 w 
 N
 S
+!Commit to 'node' was made outside it
 Td
 s
 n
@@ -57,4 +60,3 @@
 x
 I}
 m
-!Commit to 'node' was made outside it
diff --git a/tests/c-flow-mapping.n=4.c=flow-in.invalid.output b/tests/c-flow-mapping.n=4.c=flow-in.invalid.output
--- a/tests/c-flow-mapping.n=4.c=flow-in.invalid.output
+++ b/tests/c-flow-mapping.n=4.c=flow-in.invalid.output
@@ -1,5 +1,6 @@
 M
 I{
+!Commit to 'node' was made outside it
 X
 N
 S
@@ -11,5 +12,4 @@
 s
 n
 x
-!Commit to 'node' was made outside it
 !$InputFile$: line 1: column 2: Unexpected end of input
diff --git a/tests/c-flow-mapping.n=4.c=flow-in.spaced.output b/tests/c-flow-mapping.n=4.c=flow-in.spaced.output
--- a/tests/c-flow-mapping.n=4.c=flow-in.spaced.output
+++ b/tests/c-flow-mapping.n=4.c=flow-in.spaced.output
@@ -1,5 +1,6 @@
 M
 I{
+!Commit to 'node' was made outside it
 w 
 X
 N
@@ -14,6 +15,7 @@
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
@@ -44,6 +46,7 @@
 w 
 N
 S
+!Commit to 'node' was made outside it
 Td
 s
 n
@@ -67,4 +70,3 @@
 w 
 I}
 m
-!Commit to 'node' was made outside it
diff --git a/tests/c-flow-sequence.n=4.c=flow-in.compact.output b/tests/c-flow-sequence.n=4.c=flow-in.compact.output
--- a/tests/c-flow-sequence.n=4.c=flow-in.compact.output
+++ b/tests/c-flow-sequence.n=4.c=flow-in.compact.output
@@ -1,5 +1,6 @@
 Q
 I[
+!Commit to 'node' was made outside it
 N
 S
 Ta
@@ -17,6 +18,7 @@
 w 
 N
 S
+!Commit to 'node' was made outside it
 Td
 s
 n
@@ -24,4 +26,3 @@
 m
 I]
 q
-!Commit to 'node' was made outside it
diff --git a/tests/c-flow-sequence.n=4.c=flow-in.invalid.output b/tests/c-flow-sequence.n=4.c=flow-in.invalid.output
--- a/tests/c-flow-sequence.n=4.c=flow-in.invalid.output
+++ b/tests/c-flow-sequence.n=4.c=flow-in.invalid.output
@@ -1,10 +1,10 @@
 Q
 I[
+!Commit to 'node' was made outside it
 N
 S
 Ta
 s
 n
 I,
-!Commit to 'node' was made outside it
 !$InputFile$: line 1: column 3: Unexpected end of input
diff --git a/tests/c-flow-sequence.n=4.c=flow-in.spaced.output b/tests/c-flow-sequence.n=4.c=flow-in.spaced.output
--- a/tests/c-flow-sequence.n=4.c=flow-in.spaced.output
+++ b/tests/c-flow-sequence.n=4.c=flow-in.spaced.output
@@ -1,5 +1,6 @@
 Q
 I[
+!Commit to 'node' was made outside it
 w 
 N
 S
@@ -20,6 +21,7 @@
 w 
 N
 S
+!Commit to 'node' was made outside it
 Td
 s
 n
@@ -30,4 +32,3 @@
 w 
 I]
 q
-!Commit to 'node' was made outside it
diff --git a/tests/c-l+folded.n=2.indent.output b/tests/c-l+folded.n=2.indent.output
--- a/tests/c-l+folded.n=2.indent.output
+++ b/tests/c-l+folded.n=2.indent.output
@@ -1,5 +1,6 @@
 S
 I>
+!Commit to 'node' was made outside it
 I2
 w 
 C
@@ -23,4 +24,3 @@
 I#
 c
 b\x0a
-!Commit to 'node' was made outside it
diff --git a/tests/c-l+folded.n=2.invalid.output b/tests/c-l+folded.n=2.invalid.output
--- a/tests/c-l+folded.n=2.invalid.output
+++ b/tests/c-l+folded.n=2.invalid.output
@@ -1,5 +1,5 @@
 S
 I>
-b\x0a
 !Commit to 'node' was made outside it
+b\x0a
 !$InputFile$: line 2: column 0: Expected end of input
diff --git a/tests/c-l+folded.n=2.simple.output b/tests/c-l+folded.n=2.simple.output
--- a/tests/c-l+folded.n=2.simple.output
+++ b/tests/c-l+folded.n=2.simple.output
@@ -1,8 +1,8 @@
 S
 I>
+!Commit to 'node' was made outside it
 b\x0a
 i    
 Ta
 L\x0a
 s
-!Commit to 'node' was made outside it
diff --git a/tests/c-l+literal.n=2.invalid.output b/tests/c-l+literal.n=2.invalid.output
--- a/tests/c-l+literal.n=2.invalid.output
+++ b/tests/c-l+literal.n=2.invalid.output
@@ -1,7 +1,7 @@
 S
 I|
+!Commit to 'node' was made outside it
 I2
 I-
 b\x0a
-!Commit to 'node' was made outside it
 !$InputFile$: line 2: column 0: Expected end of input
diff --git a/tests/c-l+literal.n=2.simple.output b/tests/c-l+literal.n=2.simple.output
--- a/tests/c-l+literal.n=2.simple.output
+++ b/tests/c-l+literal.n=2.simple.output
@@ -1,8 +1,8 @@
 S
 I|
+!Commit to 'node' was made outside it
 b\x0a
 i    
 Ta
 L\x0a
 s
-!Commit to 'node' was made outside it
diff --git a/tests/c-l+literal.n=2.strip-indent.output b/tests/c-l+literal.n=2.strip-indent.output
--- a/tests/c-l+literal.n=2.strip-indent.output
+++ b/tests/c-l+literal.n=2.strip-indent.output
@@ -1,5 +1,6 @@
 S
 I|
+!Commit to 'node' was made outside it
 I-
 I2
 b\x0a
@@ -21,4 +22,3 @@
 I#
 c
 b\x0a
-!Commit to 'node' was made outside it
diff --git a/tests/c-l+literal.n=2.strip.output b/tests/c-l+literal.n=2.strip.output
--- a/tests/c-l+literal.n=2.strip.output
+++ b/tests/c-l+literal.n=2.strip.output
@@ -1,5 +1,6 @@
 S
 I|
+!Commit to 'node' was made outside it
 I-
 b\x0a
 i    
@@ -20,4 +21,3 @@
 I#
 c
 b\x0a
-!Commit to 'node' was made outside it
diff --git a/tests/c-l-block-map-explicit-entry.n=2.output b/tests/c-l-block-map-explicit-entry.n=2.output
--- a/tests/c-l-block-map-explicit-entry.n=2.output
+++ b/tests/c-l-block-map-explicit-entry.n=2.output
@@ -1,7 +1,9 @@
 I?
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
@@ -11,8 +13,8 @@
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
 b\x0a
-!Commit to 'node' was made outside it
diff --git a/tests/c-l-block-map-explicit-key.n=2.output b/tests/c-l-block-map-explicit-key.n=2.output
--- a/tests/c-l-block-map-explicit-key.n=2.output
+++ b/tests/c-l-block-map-explicit-key.n=2.output
@@ -1,9 +1,10 @@
 I?
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
 b\x0a
-!Commit to 'node' was made outside it
diff --git a/tests/c-l-block-map-implicit-value.n=2.empty.output b/tests/c-l-block-map-implicit-value.n=2.empty.output
--- a/tests/c-l-block-map-implicit-value.n=2.empty.output
+++ b/tests/c-l-block-map-implicit-value.n=2.empty.output
@@ -1,7 +1,7 @@
 I:
+!Commit to 'node' was made outside it
 N
 S
 s
 n
 b\x0a
-!Commit to 'node' was made outside it
diff --git a/tests/c-l-block-map-implicit-value.n=2.invalid.output b/tests/c-l-block-map-implicit-value.n=2.invalid.output
--- a/tests/c-l-block-map-implicit-value.n=2.invalid.output
+++ b/tests/c-l-block-map-implicit-value.n=2.invalid.output
@@ -1,7 +1,7 @@
 I:
+!Commit to 'node' was made outside it
 N
 S
 s
 n
-!Commit to 'node' was made outside it
 !$InputFile$: line 1: column 1: Expected start of line
diff --git a/tests/c-l-block-map-implicit-value.n=2.plain.output b/tests/c-l-block-map-implicit-value.n=2.plain.output
--- a/tests/c-l-block-map-implicit-value.n=2.plain.output
+++ b/tests/c-l-block-map-implicit-value.n=2.plain.output
@@ -1,9 +1,10 @@
 I:
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
 b\x0a
-!Commit to 'node' was made outside it
diff --git a/tests/c-l-block-seq-entry.n=2.output b/tests/c-l-block-seq-entry.n=2.output
--- a/tests/c-l-block-seq-entry.n=2.output
+++ b/tests/c-l-block-seq-entry.n=2.output
@@ -1,9 +1,10 @@
 I-
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
 b\x0a
-!Commit to 'node' was made outside it
diff --git a/tests/c-ns-alias.output b/tests/c-ns-alias.output
--- a/tests/c-ns-alias.output
+++ b/tests/c-ns-alias.output
@@ -1,5 +1,5 @@
 R
 I*
+!Commit to 'node' was made outside it
 t*&!name
 r
-!Commit to 'node' was made outside it
diff --git a/tests/c-ns-flow-map-adjacent-value.n=4.c=flow-in.compact.output b/tests/c-ns-flow-map-adjacent-value.n=4.c=flow-in.compact.output
--- a/tests/c-ns-flow-map-adjacent-value.n=4.c=flow-in.compact.output
+++ b/tests/c-ns-flow-map-adjacent-value.n=4.c=flow-in.compact.output
@@ -1,8 +1,8 @@
 I:
+!Commit to 'pair' was made outside it
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/c-ns-flow-map-adjacent-value.n=4.c=flow-in.empty.output b/tests/c-ns-flow-map-adjacent-value.n=4.c=flow-in.empty.output
--- a/tests/c-ns-flow-map-adjacent-value.n=4.c=flow-in.empty.output
+++ b/tests/c-ns-flow-map-adjacent-value.n=4.c=flow-in.empty.output
@@ -1,6 +1,6 @@
 I:
+!Commit to 'pair' was made outside it
 N
 S
 s
 n
-!Commit to 'pair' was made outside it
diff --git a/tests/c-ns-flow-map-adjacent-value.n=4.c=flow-in.spaced.output b/tests/c-ns-flow-map-adjacent-value.n=4.c=flow-in.spaced.output
--- a/tests/c-ns-flow-map-adjacent-value.n=4.c=flow-in.spaced.output
+++ b/tests/c-ns-flow-map-adjacent-value.n=4.c=flow-in.spaced.output
@@ -1,9 +1,9 @@
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/c-ns-flow-map-implicit-json.n=4.c=flow-in.compact.output b/tests/c-ns-flow-map-implicit-json.n=4.c=flow-in.compact.output
--- a/tests/c-ns-flow-map-implicit-json.n=4.c=flow-in.compact.output
+++ b/tests/c-ns-flow-map-implicit-json.n=4.c=flow-in.compact.output
@@ -6,10 +6,10 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/c-ns-flow-map-implicit-json.n=4.c=flow-in.spaced.output b/tests/c-ns-flow-map-implicit-json.n=4.c=flow-in.spaced.output
--- a/tests/c-ns-flow-map-implicit-json.n=4.c=flow-in.spaced.output
+++ b/tests/c-ns-flow-map-implicit-json.n=4.c=flow-in.spaced.output
@@ -7,11 +7,11 @@
 n
 w 
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/c-ns-flow-map-separate-value.n=4.c=flow-in.empty.output b/tests/c-ns-flow-map-separate-value.n=4.c=flow-in.empty.output
--- a/tests/c-ns-flow-map-separate-value.n=4.c=flow-in.empty.output
+++ b/tests/c-ns-flow-map-separate-value.n=4.c=flow-in.empty.output
@@ -1,6 +1,6 @@
 I:
+!Commit to 'pair' was made outside it
 N
 S
 s
 n
-!Commit to 'pair' was made outside it
diff --git a/tests/c-ns-flow-map-separate-value.n=4.c=flow-in.invalid.output b/tests/c-ns-flow-map-separate-value.n=4.c=flow-in.invalid.output
--- a/tests/c-ns-flow-map-separate-value.n=4.c=flow-in.invalid.output
+++ b/tests/c-ns-flow-map-separate-value.n=4.c=flow-in.invalid.output
@@ -1,7 +1,7 @@
 I:
+!Commit to 'pair' was made outside it
 N
 S
 s
 n
-!Commit to 'pair' was made outside it
 !$InputFile$: line 1: column 1: Expected end of input
diff --git a/tests/c-ns-flow-map-separate-value.n=4.c=flow-in.value.output b/tests/c-ns-flow-map-separate-value.n=4.c=flow-in.value.output
--- a/tests/c-ns-flow-map-separate-value.n=4.c=flow-in.value.output
+++ b/tests/c-ns-flow-map-separate-value.n=4.c=flow-in.value.output
@@ -1,9 +1,9 @@
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/c-ns-flow-map-single-json.n=4.c=flow-in.output b/tests/c-ns-flow-map-single-json.n=4.c=flow-in.output
--- a/tests/c-ns-flow-map-single-json.n=4.c=flow-in.output
+++ b/tests/c-ns-flow-map-single-json.n=4.c=flow-in.output
@@ -6,10 +6,10 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/c-quoted-quote.output b/tests/c-quoted-quote.output
--- a/tests/c-quoted-quote.output
+++ b/tests/c-quoted-quote.output
@@ -1,5 +1,5 @@
 E
 I'
+!Commit to 'escape' was made outside it
 t'
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/debug-leak.input b/tests/debug-leak.input
deleted file mode 100644
--- a/tests/debug-leak.input
+++ /dev/null
@@ -1,1 +0,0 @@
-#
diff --git a/tests/debug-leak.output b/tests/debug-leak.output
deleted file mode 100644
--- a/tests/debug-leak.output
+++ /dev/null
@@ -1,2 +0,0 @@
-I#
-?\x0a
diff --git a/tests/l+block-mapping.n=1.output b/tests/l+block-mapping.n=1.output
--- a/tests/l+block-mapping.n=1.output
+++ b/tests/l+block-mapping.n=1.output
@@ -7,9 +7,11 @@
 s
 n
 I:
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
@@ -18,9 +20,11 @@
 i  
 X
 I?
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tc
 s
 n
@@ -30,10 +34,10 @@
 w 
 N
 S
+!Commit to 'node' was made outside it
 Td
 s
 n
 b\x0a
 x
 m
-!Commit to 'node' was made outside it
diff --git a/tests/l+block-sequence.n=1.output b/tests/l+block-sequence.n=1.output
--- a/tests/l+block-sequence.n=1.output
+++ b/tests/l+block-sequence.n=1.output
@@ -1,23 +1,28 @@
 Q
 i  
 I-
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
 b\x0a
 i  
 I-
+!Commit to 'node' was made outside it
 N
 b\x0a
 Q
 i   
 I-
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
@@ -26,6 +31,7 @@
 n
 i  
 I-
+!Commit to 'node' was made outside it
 i 
 N
 Q
@@ -49,4 +55,3 @@
 q
 n
 q
-!Commit to 'node' was made outside it
diff --git a/tests/l-block-map-explicit-value.n=2.output b/tests/l-block-map-explicit-value.n=2.output
--- a/tests/l-block-map-explicit-value.n=2.output
+++ b/tests/l-block-map-explicit-value.n=2.output
@@ -3,8 +3,8 @@
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
 b\x0a
-!Commit to 'node' was made outside it
diff --git a/tests/l-explicit-document.invalid.output b/tests/l-explicit-document.invalid.output
--- a/tests/l-explicit-document.invalid.output
+++ b/tests/l-explicit-document.invalid.output
@@ -1,10 +1,10 @@
 O
 K---
+!Commit to 'doc' was made outside it
 N
 S
 s
 n
 b\x0a
 o
-!Commit to 'doc' was made outside it
 !$InputFile$: line 2: column 0: Expected end of input
diff --git a/tests/l-explicit-document.literal.output b/tests/l-explicit-document.literal.output
--- a/tests/l-explicit-document.literal.output
+++ b/tests/l-explicit-document.literal.output
@@ -1,5 +1,6 @@
 O
 K---
+!Commit to 'doc' was made outside it
 O
 N
 w 
@@ -12,4 +13,3 @@
 n
 o
 o
-!Commit to 'doc' was made outside it
diff --git a/tests/l-explicit-document.plain.output b/tests/l-explicit-document.plain.output
--- a/tests/l-explicit-document.plain.output
+++ b/tests/l-explicit-document.plain.output
@@ -6,7 +6,9 @@
 t1.1
 d
 b\x0a
+!Commit to 'doc' was made outside it
 K---
+!Commit to 'doc' was made outside it
 O
 w 
 N
@@ -17,4 +19,3 @@
 b\x0a
 o
 o
-!Commit to 'doc' was made outside it
diff --git a/tests/l-implicit-document.invalid.output b/tests/l-implicit-document.invalid.output
--- a/tests/l-implicit-document.invalid.output
+++ b/tests/l-implicit-document.invalid.output
@@ -1,4 +1,4 @@
 O
 N
 S
-!$InputFile$: line 1: column 0: Forbidden pattern detected
+!$InputFile$: line 1: column 0: Unexpected forbidden pattern
diff --git a/tests/l-implicit-document.literal.output b/tests/l-implicit-document.literal.output
--- a/tests/l-implicit-document.literal.output
+++ b/tests/l-implicit-document.literal.output
@@ -2,10 +2,10 @@
 N
 S
 I|
+!Commit to 'node' was made outside it
 b\x0a
 Ta
 L\x0a
 s
 n
 o
-!Commit to 'node' was made outside it
diff --git a/tests/l-implicit-document.plain.output b/tests/l-implicit-document.plain.output
--- a/tests/l-implicit-document.plain.output
+++ b/tests/l-implicit-document.plain.output
@@ -1,9 +1,9 @@
 O
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
 b\x0a
 o
-!Commit to 'node' was made outside it
diff --git a/tests/l-nb-folded-lines.n=4.invalid.output b/tests/l-nb-folded-lines.n=4.invalid.output
--- a/tests/l-nb-folded-lines.n=4.invalid.output
+++ b/tests/l-nb-folded-lines.n=4.invalid.output
@@ -1,4 +1,4 @@
 i    
-?a
 !Commit to 'fold' was made outside it
+?a
 !$InputFile$: line 1: column 5: Expected end of input
diff --git a/tests/l-nb-folded-lines.n=4.output b/tests/l-nb-folded-lines.n=4.output
--- a/tests/l-nb-folded-lines.n=4.output
+++ b/tests/l-nb-folded-lines.n=4.output
@@ -1,10 +1,12 @@
 i    
+!Commit to 'fold' was made outside it
 ?a
 l\x0a
 i    
+!Commit to 'fold' was made outside it
 ?b
 b\x0a
 L\x0a
 i    
-?c
 !Commit to 'fold' was made outside it
+?c
diff --git a/tests/l-nb-spaced-lines.n=4.output b/tests/l-nb-spaced-lines.n=4.output
--- a/tests/l-nb-spaced-lines.n=4.output
+++ b/tests/l-nb-spaced-lines.n=4.output
@@ -1,10 +1,12 @@
 i    
+!Commit to 'fold' was made outside it
 ? a
 L\x0a
 i    
+!Commit to 'fold' was made outside it
 ? b
 L\x0a
 L\x0a
 i    
-? c
 !Commit to 'fold' was made outside it
+? c
diff --git a/tests/l-nb-start-with-folded.n=4.output b/tests/l-nb-start-with-folded.n=4.output
--- a/tests/l-nb-start-with-folded.n=4.output
+++ b/tests/l-nb-start-with-folded.n=4.output
@@ -1,12 +1,14 @@
 i  
 L\x0a
 i    
+!Commit to 'fold' was made outside it
 ?a
 L\x0a
 i    
+!Commit to 'fold' was made outside it
 ? b
 L\x0a
 L\x0a
 i    
-?c
 !Commit to 'fold' was made outside it
+?c
diff --git a/tests/l-nb-start-with-spaced.n=4.output b/tests/l-nb-start-with-spaced.n=4.output
--- a/tests/l-nb-start-with-spaced.n=4.output
+++ b/tests/l-nb-start-with-spaced.n=4.output
@@ -1,10 +1,12 @@
 i    
+!Commit to 'fold' was made outside it
 ? a
 L\x0a
 i    
+!Commit to 'fold' was made outside it
 ?b
 L\x0a
 L\x0a
 i    
-? c
 !Commit to 'fold' was made outside it
+? c
diff --git a/tests/ns-esc-16-bit.output b/tests/ns-esc-16-bit.output
--- a/tests/ns-esc-16-bit.output
+++ b/tests/ns-esc-16-bit.output
@@ -1,3 +1,3 @@
 Iu
-tFEDC
 !Commit to 'escaped' was made outside it
+tFEDC
diff --git a/tests/ns-esc-32-bit.output b/tests/ns-esc-32-bit.output
--- a/tests/ns-esc-32-bit.output
+++ b/tests/ns-esc-32-bit.output
@@ -1,3 +1,3 @@
 IU
-t0010FEDC
 !Commit to 'escaped' was made outside it
+t0010FEDC
diff --git a/tests/ns-esc-8-bit.output b/tests/ns-esc-8-bit.output
--- a/tests/ns-esc-8-bit.output
+++ b/tests/ns-esc-8-bit.output
@@ -1,3 +1,3 @@
 Ix
-tFF
 !Commit to 'escaped' was made outside it
+tFF
diff --git a/tests/ns-esc-char.16-bit.output b/tests/ns-esc-char.16-bit.output
--- a/tests/ns-esc-char.16-bit.output
+++ b/tests/ns-esc-char.16-bit.output
@@ -1,6 +1,6 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 Iu
 tFEDC
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.32-bit.output b/tests/ns-esc-char.32-bit.output
--- a/tests/ns-esc-char.32-bit.output
+++ b/tests/ns-esc-char.32-bit.output
@@ -1,6 +1,6 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 IU
 t0010FEDC
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.8-bit.output b/tests/ns-esc-char.8-bit.output
--- a/tests/ns-esc-char.8-bit.output
+++ b/tests/ns-esc-char.8-bit.output
@@ -1,6 +1,6 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 Ix
 tFF
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.backslash.output b/tests/ns-esc-char.backslash.output
--- a/tests/ns-esc-char.backslash.output
+++ b/tests/ns-esc-char.backslash.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 t\x5c
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.bell.output b/tests/ns-esc-char.bell.output
--- a/tests/ns-esc-char.bell.output
+++ b/tests/ns-esc-char.bell.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 ta
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.bs.output b/tests/ns-esc-char.bs.output
--- a/tests/ns-esc-char.bs.output
+++ b/tests/ns-esc-char.bs.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 tb
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.cr.output b/tests/ns-esc-char.cr.output
--- a/tests/ns-esc-char.cr.output
+++ b/tests/ns-esc-char.cr.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 tr
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.double-quote.output b/tests/ns-esc-char.double-quote.output
--- a/tests/ns-esc-char.double-quote.output
+++ b/tests/ns-esc-char.double-quote.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 t"
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.esc.output b/tests/ns-esc-char.esc.output
--- a/tests/ns-esc-char.esc.output
+++ b/tests/ns-esc-char.esc.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 te
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.ff.output b/tests/ns-esc-char.ff.output
--- a/tests/ns-esc-char.ff.output
+++ b/tests/ns-esc-char.ff.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 tf
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.lf.output b/tests/ns-esc-char.lf.output
--- a/tests/ns-esc-char.lf.output
+++ b/tests/ns-esc-char.lf.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 tn
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.ls.output b/tests/ns-esc-char.ls.output
--- a/tests/ns-esc-char.ls.output
+++ b/tests/ns-esc-char.ls.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 tL
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.nbsp.output b/tests/ns-esc-char.nbsp.output
--- a/tests/ns-esc-char.nbsp.output
+++ b/tests/ns-esc-char.nbsp.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 t_
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.nl.output b/tests/ns-esc-char.nl.output
--- a/tests/ns-esc-char.nl.output
+++ b/tests/ns-esc-char.nl.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 tN
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.null.output b/tests/ns-esc-char.null.output
--- a/tests/ns-esc-char.null.output
+++ b/tests/ns-esc-char.null.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 t0
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.ps.output b/tests/ns-esc-char.ps.output
--- a/tests/ns-esc-char.ps.output
+++ b/tests/ns-esc-char.ps.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 tP
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.sp.output b/tests/ns-esc-char.sp.output
--- a/tests/ns-esc-char.sp.output
+++ b/tests/ns-esc-char.sp.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 t 
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.tab.output b/tests/ns-esc-char.tab.output
--- a/tests/ns-esc-char.tab.output
+++ b/tests/ns-esc-char.tab.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 tt
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-esc-char.vt.output b/tests/ns-esc-char.vt.output
--- a/tests/ns-esc-char.vt.output
+++ b/tests/ns-esc-char.vt.output
@@ -1,5 +1,5 @@
 E
 I\x5c
+!Commit to 'escape' was made outside it
 tv
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/ns-flow-content.n=4.c=flow-in.json.output b/tests/ns-flow-content.n=4.c=flow-in.json.output
--- a/tests/ns-flow-content.n=4.c=flow-in.json.output
+++ b/tests/ns-flow-content.n=4.c=flow-in.json.output
@@ -1,6 +1,6 @@
 S
 I"
+!Commit to 'node' was made outside it
 Ta
 I"
 s
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-content.n=4.c=flow-in.yaml.output b/tests/ns-flow-content.n=4.c=flow-in.yaml.output
--- a/tests/ns-flow-content.n=4.c=flow-in.yaml.output
+++ b/tests/ns-flow-content.n=4.c=flow-in.yaml.output
@@ -1,4 +1,4 @@
 S
+!Commit to 'node' was made outside it
 Ta
 s
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-map-entry.n=4.c=flow-in.explicit.output b/tests/ns-flow-map-entry.n=4.c=flow-in.explicit.output
--- a/tests/ns-flow-map-entry.n=4.c=flow-in.explicit.output
+++ b/tests/ns-flow-map-entry.n=4.c=flow-in.explicit.output
@@ -10,8 +10,8 @@
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
 x
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-map-implicit-empty.n=4.c=flow-in.invalid.output b/tests/ns-flow-map-implicit-empty.n=4.c=flow-in.invalid.output
--- a/tests/ns-flow-map-implicit-empty.n=4.c=flow-in.invalid.output
+++ b/tests/ns-flow-map-implicit-empty.n=4.c=flow-in.invalid.output
@@ -3,9 +3,9 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 N
 S
 s
 n
-!Commit to 'pair' was made outside it
 !$InputFile$: line 1: column 1: Expected end of input
diff --git a/tests/ns-flow-map-implicit-empty.n=4.c=flow-in.output b/tests/ns-flow-map-implicit-empty.n=4.c=flow-in.output
--- a/tests/ns-flow-map-implicit-empty.n=4.c=flow-in.output
+++ b/tests/ns-flow-map-implicit-empty.n=4.c=flow-in.output
@@ -3,11 +3,11 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-map-implicit-entry.n=4.c=flow-in.empty.output b/tests/ns-flow-map-implicit-entry.n=4.c=flow-in.empty.output
--- a/tests/ns-flow-map-implicit-entry.n=4.c=flow-in.empty.output
+++ b/tests/ns-flow-map-implicit-entry.n=4.c=flow-in.empty.output
@@ -3,11 +3,11 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-map-implicit-entry.n=4.c=flow-in.json.output b/tests/ns-flow-map-implicit-entry.n=4.c=flow-in.json.output
--- a/tests/ns-flow-map-implicit-entry.n=4.c=flow-in.json.output
+++ b/tests/ns-flow-map-implicit-entry.n=4.c=flow-in.json.output
@@ -6,10 +6,10 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-map-implicit-entry.n=4.c=flow-in.yaml.output b/tests/ns-flow-map-implicit-entry.n=4.c=flow-in.yaml.output
--- a/tests/ns-flow-map-implicit-entry.n=4.c=flow-in.yaml.output
+++ b/tests/ns-flow-map-implicit-entry.n=4.c=flow-in.yaml.output
@@ -4,11 +4,11 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-map-implicit-yaml.n=4.c=flow-in.compact.output b/tests/ns-flow-map-implicit-yaml.n=4.c=flow-in.compact.output
--- a/tests/ns-flow-map-implicit-yaml.n=4.c=flow-in.compact.output
+++ b/tests/ns-flow-map-implicit-yaml.n=4.c=flow-in.compact.output
@@ -4,11 +4,11 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-map-implicit-yaml.n=4.c=flow-in.spaced.output b/tests/ns-flow-map-implicit-yaml.n=4.c=flow-in.spaced.output
--- a/tests/ns-flow-map-implicit-yaml.n=4.c=flow-in.spaced.output
+++ b/tests/ns-flow-map-implicit-yaml.n=4.c=flow-in.spaced.output
@@ -5,11 +5,11 @@
 n
 w 
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-map-single-entry.n=4.c=flow-in.empty.output b/tests/ns-flow-map-single-entry.n=4.c=flow-in.empty.output
--- a/tests/ns-flow-map-single-entry.n=4.c=flow-in.empty.output
+++ b/tests/ns-flow-map-single-entry.n=4.c=flow-in.empty.output
@@ -3,11 +3,11 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-map-single-entry.n=4.c=flow-in.json.output b/tests/ns-flow-map-single-entry.n=4.c=flow-in.json.output
--- a/tests/ns-flow-map-single-entry.n=4.c=flow-in.json.output
+++ b/tests/ns-flow-map-single-entry.n=4.c=flow-in.json.output
@@ -6,10 +6,10 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-map-single-entry.n=4.c=flow-in.yaml.output b/tests/ns-flow-map-single-entry.n=4.c=flow-in.yaml.output
--- a/tests/ns-flow-map-single-entry.n=4.c=flow-in.yaml.output
+++ b/tests/ns-flow-map-single-entry.n=4.c=flow-in.yaml.output
@@ -4,11 +4,11 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-map-single-pair.n=4.c=flow-in.explicit.output b/tests/ns-flow-map-single-pair.n=4.c=flow-in.explicit.output
--- a/tests/ns-flow-map-single-pair.n=4.c=flow-in.explicit.output
+++ b/tests/ns-flow-map-single-pair.n=4.c=flow-in.explicit.output
@@ -1,6 +1,7 @@
 M
 X
 I?
+!Commit to 'pair' was made outside it
 w 
 N
 S
@@ -8,13 +9,13 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
 x
 m
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-map-single-pair.n=4.c=flow-in.implicit.output b/tests/ns-flow-map-single-pair.n=4.c=flow-in.implicit.output
--- a/tests/ns-flow-map-single-pair.n=4.c=flow-in.implicit.output
+++ b/tests/ns-flow-map-single-pair.n=4.c=flow-in.implicit.output
@@ -6,13 +6,13 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
 x
 m
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-map-single-yaml.n=4.c=flow-in.output b/tests/ns-flow-map-single-yaml.n=4.c=flow-in.output
--- a/tests/ns-flow-map-single-yaml.n=4.c=flow-in.output
+++ b/tests/ns-flow-map-single-yaml.n=4.c=flow-in.output
@@ -4,11 +4,11 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-node.n=4.c=flow-in.alias.output b/tests/ns-flow-node.n=4.c=flow-in.alias.output
--- a/tests/ns-flow-node.n=4.c=flow-in.alias.output
+++ b/tests/ns-flow-node.n=4.c=flow-in.alias.output
@@ -1,7 +1,7 @@
 N
 R
 I*
+!Commit to 'node' was made outside it
 ta
 r
 n
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-node.n=4.c=flow-in.tagged.output b/tests/ns-flow-node.n=4.c=flow-in.tagged.output
--- a/tests/ns-flow-node.n=4.c=flow-in.tagged.output
+++ b/tests/ns-flow-node.n=4.c=flow-in.tagged.output
@@ -10,8 +10,8 @@
 w 
 S
 I"
+!Commit to 'node' was made outside it
 Ta
 I"
 s
 n
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-node.n=4.c=flow-in.untagged.output b/tests/ns-flow-node.n=4.c=flow-in.untagged.output
--- a/tests/ns-flow-node.n=4.c=flow-in.untagged.output
+++ b/tests/ns-flow-node.n=4.c=flow-in.untagged.output
@@ -1,6 +1,6 @@
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-seq-entry.n=4.c=flow-in.pair.output b/tests/ns-flow-seq-entry.n=4.c=flow-in.pair.output
--- a/tests/ns-flow-seq-entry.n=4.c=flow-in.pair.output
+++ b/tests/ns-flow-seq-entry.n=4.c=flow-in.pair.output
@@ -9,9 +9,9 @@
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
 x
 m
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-yaml-content.n=4.c=flow-in.output b/tests/ns-flow-yaml-content.n=4.c=flow-in.output
--- a/tests/ns-flow-yaml-content.n=4.c=flow-in.output
+++ b/tests/ns-flow-yaml-content.n=4.c=flow-in.output
@@ -1,4 +1,4 @@
 S
+!Commit to 'node' was made outside it
 Ta
 s
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-yaml-node.n=4.c=flow-in.alias.output b/tests/ns-flow-yaml-node.n=4.c=flow-in.alias.output
--- a/tests/ns-flow-yaml-node.n=4.c=flow-in.alias.output
+++ b/tests/ns-flow-yaml-node.n=4.c=flow-in.alias.output
@@ -1,7 +1,7 @@
 N
 R
 I*
+!Commit to 'node' was made outside it
 ta
 r
 n
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-yaml-node.n=4.c=flow-in.tagged.output b/tests/ns-flow-yaml-node.n=4.c=flow-in.tagged.output
--- a/tests/ns-flow-yaml-node.n=4.c=flow-in.tagged.output
+++ b/tests/ns-flow-yaml-node.n=4.c=flow-in.tagged.output
@@ -9,7 +9,7 @@
 p
 w 
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
-!Commit to 'node' was made outside it
diff --git a/tests/ns-flow-yaml-node.n=4.c=flow-in.untagged.output b/tests/ns-flow-yaml-node.n=4.c=flow-in.untagged.output
--- a/tests/ns-flow-yaml-node.n=4.c=flow-in.untagged.output
+++ b/tests/ns-flow-yaml-node.n=4.c=flow-in.untagged.output
@@ -1,6 +1,6 @@
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
-!Commit to 'node' was made outside it
diff --git a/tests/ns-l-block-map-entry.n=2.explicit.output b/tests/ns-l-block-map-entry.n=2.explicit.output
--- a/tests/ns-l-block-map-entry.n=2.explicit.output
+++ b/tests/ns-l-block-map-entry.n=2.explicit.output
@@ -1,8 +1,10 @@
 X
 I?
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
@@ -12,10 +14,10 @@
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
 b\x0a
 b\x0a
 x
-!Commit to 'node' was made outside it
diff --git a/tests/ns-l-block-map-entry.n=2.implicit.output b/tests/ns-l-block-map-entry.n=2.implicit.output
--- a/tests/ns-l-block-map-entry.n=2.implicit.output
+++ b/tests/ns-l-block-map-entry.n=2.implicit.output
@@ -5,12 +5,13 @@
 s
 n
 I:
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
 b\x0a
 x
-!Commit to 'node' was made outside it
diff --git a/tests/ns-l-block-map-implicit-entry.n=2.empty.output b/tests/ns-l-block-map-implicit-entry.n=2.empty.output
--- a/tests/ns-l-block-map-implicit-entry.n=2.empty.output
+++ b/tests/ns-l-block-map-implicit-entry.n=2.empty.output
@@ -3,9 +3,9 @@
 s
 n
 I:
+!Commit to 'node' was made outside it
 N
 S
 s
 n
 b\x0a
-!Commit to 'node' was made outside it
diff --git a/tests/ns-l-block-map-implicit-entry.n=2.non-empty.output b/tests/ns-l-block-map-implicit-entry.n=2.non-empty.output
--- a/tests/ns-l-block-map-implicit-entry.n=2.non-empty.output
+++ b/tests/ns-l-block-map-implicit-entry.n=2.non-empty.output
@@ -4,11 +4,12 @@
 s
 n
 I:
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
 b\x0a
-!Commit to 'node' was made outside it
diff --git a/tests/ns-l-in-line-mapping.n=2.output b/tests/ns-l-in-line-mapping.n=2.output
--- a/tests/ns-l-in-line-mapping.n=2.output
+++ b/tests/ns-l-in-line-mapping.n=2.output
@@ -7,9 +7,11 @@
 s
 n
 I:
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
@@ -23,9 +25,11 @@
 s
 n
 I:
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Td
 s
 n
@@ -33,4 +37,3 @@
 x
 m
 n
-!Commit to 'node' was made outside it
diff --git a/tests/ns-l-in-line-sequence.n=3.invalid.output b/tests/ns-l-in-line-sequence.n=3.invalid.output
--- a/tests/ns-l-in-line-sequence.n=3.invalid.output
+++ b/tests/ns-l-in-line-sequence.n=3.invalid.output
@@ -1,14 +1,15 @@
 N
 Q
 I-
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
 b\x0a
 q
 n
-!Commit to 'node' was made outside it
 !$InputFile$: line 2: column 0: Expected end of input
diff --git a/tests/ns-l-in-line-sequence.n=3.output b/tests/ns-l-in-line-sequence.n=3.output
--- a/tests/ns-l-in-line-sequence.n=3.output
+++ b/tests/ns-l-in-line-sequence.n=3.output
@@ -1,22 +1,25 @@
 N
 Q
 I-
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
 b\x0a
 i   
 I-
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
 b\x0a
 q
 n
-!Commit to 'node' was made outside it
diff --git a/tests/ns-plain-multi.n=4.c=flow-in.invalid.output b/tests/ns-plain-multi.n=4.c=flow-in.invalid.output
--- a/tests/ns-plain-multi.n=4.c=flow-in.invalid.output
+++ b/tests/ns-plain-multi.n=4.c=flow-in.invalid.output
@@ -1,6 +1,6 @@
+!Commit to 'node' was made outside it
 ?a
 l\x0a
 i    
 ?12
-!Commit to 'node' was made outside it
 !$InputFile$: line 2: column 6: Expected end of input
diff --git a/tests/ns-plain-multi.n=4.c=flow-in.output b/tests/ns-plain-multi.n=4.c=flow-in.output
--- a/tests/ns-plain-multi.n=4.c=flow-in.output
+++ b/tests/ns-plain-multi.n=4.c=flow-in.output
@@ -1,3 +1,4 @@
+!Commit to 'node' was made outside it
 ?a
 w\x09
 b\x0a
@@ -10,4 +11,3 @@
 i    
 w  
 ?c
-!Commit to 'node' was made outside it
diff --git a/tests/ns-plain-single.c=flow-key.invalid.output b/tests/ns-plain-single.c=flow-key.invalid.output
--- a/tests/ns-plain-single.c=flow-key.invalid.output
+++ b/tests/ns-plain-single.c=flow-key.invalid.output
@@ -1,3 +1,3 @@
-?12
 !Commit to 'node' was made outside it
+?12
 !$InputFile$: line 1: column 2: Expected end of input
diff --git a/tests/ns-plain-single.c=flow-out.output b/tests/ns-plain-single.c=flow-out.output
--- a/tests/ns-plain-single.c=flow-out.output
+++ b/tests/ns-plain-single.c=flow-out.output
@@ -1,2 +1,2 @@
-?a \x09" :# {} b
 !Commit to 'node' was made outside it
+?a \x09" :# {} b
diff --git a/tests/ns-plain.n=4.c=flow-in.output b/tests/ns-plain.n=4.c=flow-in.output
--- a/tests/ns-plain.n=4.c=flow-in.output
+++ b/tests/ns-plain.n=4.c=flow-in.output
@@ -1,4 +1,5 @@
 S
+!Commit to 'node' was made outside it
 Ta
 w\x09
 b\x0a
@@ -12,4 +13,3 @@
 w  
 Tc
 s
-!Commit to 'node' was made outside it
diff --git a/tests/ns-plain.n=4.c=flow-key.invalid.output b/tests/ns-plain.n=4.c=flow-key.invalid.output
--- a/tests/ns-plain.n=4.c=flow-key.invalid.output
+++ b/tests/ns-plain.n=4.c=flow-key.invalid.output
@@ -1,5 +1,5 @@
 S
+!Commit to 'node' was made outside it
 T12
 s
-!Commit to 'node' was made outside it
 !$InputFile$: line 1: column 2: Expected end of input
diff --git a/tests/ns-plain.n=4.c=flow-key.output b/tests/ns-plain.n=4.c=flow-key.output
--- a/tests/ns-plain.n=4.c=flow-key.output
+++ b/tests/ns-plain.n=4.c=flow-key.output
@@ -1,4 +1,4 @@
 S
+!Commit to 'node' was made outside it
 Ta \x09" :# () b
 s
-!Commit to 'node' was made outside it
diff --git a/tests/ns-s-flow-map-entries.n=4.c=flow-in.multi.output b/tests/ns-s-flow-map-entries.n=4.c=flow-in.multi.output
--- a/tests/ns-s-flow-map-entries.n=4.c=flow-in.multi.output
+++ b/tests/ns-s-flow-map-entries.n=4.c=flow-in.multi.output
@@ -8,6 +8,7 @@
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
@@ -42,4 +43,3 @@
 x
 I,
 w 
-!Commit to 'node' was made outside it
diff --git a/tests/ns-s-flow-map-entries.n=4.c=flow-in.single.output b/tests/ns-s-flow-map-entries.n=4.c=flow-in.single.output
--- a/tests/ns-s-flow-map-entries.n=4.c=flow-in.single.output
+++ b/tests/ns-s-flow-map-entries.n=4.c=flow-in.single.output
@@ -8,8 +8,8 @@
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
 x
-!Commit to 'node' was made outside it
diff --git a/tests/ns-s-flow-seq-entries.n=4.c=flow-in.multi.output b/tests/ns-s-flow-seq-entries.n=4.c=flow-in.multi.output
--- a/tests/ns-s-flow-seq-entries.n=4.c=flow-in.multi.output
+++ b/tests/ns-s-flow-seq-entries.n=4.c=flow-in.multi.output
@@ -17,10 +17,10 @@
 w 
 N
 S
+!Commit to 'node' was made outside it
 Td
 s
 n
 x
 m
 w 
-!Commit to 'node' was made outside it
diff --git a/tests/ns-tag-directive.invalid.output b/tests/ns-tag-directive.invalid.output
--- a/tests/ns-tag-directive.invalid.output
+++ b/tests/ns-tag-directive.invalid.output
@@ -1,5 +1,5 @@
 tTAG
+!Commit to 'directive' was made outside it
 w 
 H
-!Commit to 'directive' was made outside it
 !$InputFile$: line 1: column 4: Unexpected 'a'
diff --git a/tests/ns-tag-directive.output b/tests/ns-tag-directive.output
--- a/tests/ns-tag-directive.output
+++ b/tests/ns-tag-directive.output
@@ -1,4 +1,5 @@
 tTAG
+!Commit to 'directive' was made outside it
 w 
 H
 I!
@@ -10,4 +11,3 @@
 I!
 tprefix
 g
-!Commit to 'directive' was made outside it
diff --git a/tests/ns-yaml-directive.invalid.output b/tests/ns-yaml-directive.invalid.output
--- a/tests/ns-yaml-directive.invalid.output
+++ b/tests/ns-yaml-directive.invalid.output
@@ -1,4 +1,4 @@
 tYAML
-w 
 !Commit to 'directive' was made outside it
+w 
 !$InputFile$: line 1: column 5: Unexpected 'a'
diff --git a/tests/ns-yaml-directive.output b/tests/ns-yaml-directive.output
--- a/tests/ns-yaml-directive.output
+++ b/tests/ns-yaml-directive.output
@@ -1,4 +1,4 @@
 tYAML
+!Commit to 'directive' was made outside it
 w 
 t0.1
-!Commit to 'directive' was made outside it
diff --git a/tests/s-b-double-escaped.output b/tests/s-b-double-escaped.output
--- a/tests/s-b-double-escaped.output
+++ b/tests/s-b-double-escaped.output
@@ -1,6 +1,6 @@
 ? 
 E
 I\x5c
+!Commit to 'escape' was made outside it
 b\x0a
 e
-!Commit to 'escape' was made outside it
diff --git a/tests/s-l+block-content.n=2.c=block-in.sequence.output b/tests/s-l+block-content.n=2.c=block-in.sequence.output
--- a/tests/s-l+block-content.n=2.c=block-in.sequence.output
+++ b/tests/s-l+block-content.n=2.c=block-in.sequence.output
@@ -2,12 +2,13 @@
 Q
 i  
 I-
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
 b\x0a
 q
-!Commit to 'node' was made outside it
diff --git a/tests/s-l+block-content.n=2.c=block-out.folded.output b/tests/s-l+block-content.n=2.c=block-out.folded.output
--- a/tests/s-l+block-content.n=2.c=block-out.folded.output
+++ b/tests/s-l+block-content.n=2.c=block-out.folded.output
@@ -1,8 +1,8 @@
 S
 I>
+!Commit to 'node' was made outside it
 b\x0a
 i   
 Ta
 L\x0a
 s
-!Commit to 'node' was made outside it
diff --git a/tests/s-l+block-content.n=2.c=block-out.literal.output b/tests/s-l+block-content.n=2.c=block-out.literal.output
--- a/tests/s-l+block-content.n=2.c=block-out.literal.output
+++ b/tests/s-l+block-content.n=2.c=block-out.literal.output
@@ -1,9 +1,9 @@
 w 
 S
 I|
+!Commit to 'node' was made outside it
 b\x0a
 i   
 Ta
 L\x0a
 s
-!Commit to 'node' was made outside it
diff --git a/tests/s-l+block-content.n=2.c=block-out.mapping.output b/tests/s-l+block-content.n=2.c=block-out.mapping.output
--- a/tests/s-l+block-content.n=2.c=block-out.mapping.output
+++ b/tests/s-l+block-content.n=2.c=block-out.mapping.output
@@ -8,13 +8,14 @@
 s
 n
 I:
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
 b\x0a
 x
 m
-!Commit to 'node' was made outside it
diff --git a/tests/s-l+block-in-block.n=2.c=block-out.tagged.output b/tests/s-l+block-in-block.n=2.c=block-out.tagged.output
--- a/tests/s-l+block-in-block.n=2.c=block-out.tagged.output
+++ b/tests/s-l+block-in-block.n=2.c=block-out.tagged.output
@@ -11,10 +11,10 @@
 w 
 S
 I|
+!Commit to 'node' was made outside it
 b\x0a
 i   
 Ta
 L\x0a
 s
 n
-!Commit to 'node' was made outside it
diff --git a/tests/s-l+block-in-block.n=2.c=block-out.untagged.output b/tests/s-l+block-in-block.n=2.c=block-out.untagged.output
--- a/tests/s-l+block-in-block.n=2.c=block-out.untagged.output
+++ b/tests/s-l+block-in-block.n=2.c=block-out.untagged.output
@@ -1,10 +1,10 @@
 N
 S
 I|
+!Commit to 'node' was made outside it
 b\x0a
 i   
 Ta
 L\x0a
 s
 n
-!Commit to 'node' was made outside it
diff --git a/tests/s-l+block-indented.n=2.c=block-in.sequence.output b/tests/s-l+block-indented.n=2.c=block-in.sequence.output
--- a/tests/s-l+block-indented.n=2.c=block-in.sequence.output
+++ b/tests/s-l+block-indented.n=2.c=block-in.sequence.output
@@ -3,13 +3,14 @@
 Q
 i  
 I-
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
 b\x0a
 q
 n
-!Commit to 'node' was made outside it
diff --git a/tests/s-l+block-indented.n=2.c=block-out.literal.output b/tests/s-l+block-indented.n=2.c=block-out.literal.output
--- a/tests/s-l+block-indented.n=2.c=block-out.literal.output
+++ b/tests/s-l+block-indented.n=2.c=block-out.literal.output
@@ -2,10 +2,10 @@
 w 
 S
 I|
+!Commit to 'node' was made outside it
 b\x0a
 i   
 Ta
 L\x0a
 s
 n
-!Commit to 'node' was made outside it
diff --git a/tests/s-l+block-indented.n=2.c=block-out.sequence.output b/tests/s-l+block-indented.n=2.c=block-out.sequence.output
--- a/tests/s-l+block-indented.n=2.c=block-out.sequence.output
+++ b/tests/s-l+block-indented.n=2.c=block-out.sequence.output
@@ -3,13 +3,14 @@
 Q
 i   
 I-
+!Commit to 'node' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
 b\x0a
 q
 n
-!Commit to 'node' was made outside it
diff --git a/tests/s-l+block-node.n=2.c=block-out.block.output b/tests/s-l+block-node.n=2.c=block-out.block.output
--- a/tests/s-l+block-node.n=2.c=block-out.block.output
+++ b/tests/s-l+block-node.n=2.c=block-out.block.output
@@ -1,10 +1,10 @@
 N
 S
 I|
+!Commit to 'node' was made outside it
 b\x0a
 i   
 Ta
 L\x0a
 s
 n
-!Commit to 'node' was made outside it
diff --git a/tests/s-l+block-node.n=2.c=block-out.flow.output b/tests/s-l+block-node.n=2.c=block-out.flow.output
--- a/tests/s-l+block-node.n=2.c=block-out.flow.output
+++ b/tests/s-l+block-node.n=2.c=block-out.flow.output
@@ -1,7 +1,7 @@
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
 b\x0a
-!Commit to 'node' was made outside it
diff --git a/tests/s-l+flow-in-block.n=2.output b/tests/s-l+flow-in-block.n=2.output
--- a/tests/s-l+flow-in-block.n=2.output
+++ b/tests/s-l+flow-in-block.n=2.output
@@ -1,7 +1,7 @@
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
 b\x0a
-!Commit to 'node' was made outside it
diff --git a/tests/s-nb-folded-text.n=4.output b/tests/s-nb-folded-text.n=4.output
--- a/tests/s-nb-folded-text.n=4.output
+++ b/tests/s-nb-folded-text.n=4.output
@@ -1,3 +1,3 @@
 i    
-?a
 !Commit to 'fold' was made outside it
+?a
diff --git a/tests/s-nb-spaced-text.n=4.output b/tests/s-nb-spaced-text.n=4.output
--- a/tests/s-nb-spaced-text.n=4.output
+++ b/tests/s-nb-spaced-text.n=4.output
@@ -1,3 +1,3 @@
 i    
-? a
 !Commit to 'fold' was made outside it
+? a
diff --git a/tests/s-ns-flow-map-explicit-empty.n=4.c=flow-in.output b/tests/s-ns-flow-map-explicit-empty.n=4.c=flow-in.output
--- a/tests/s-ns-flow-map-explicit-empty.n=4.c=flow-in.output
+++ b/tests/s-ns-flow-map-explicit-empty.n=4.c=flow-in.output
@@ -4,11 +4,11 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/s-ns-flow-map-explicit-entry.n=4.c=flow-in.json.output b/tests/s-ns-flow-map-explicit-entry.n=4.c=flow-in.json.output
--- a/tests/s-ns-flow-map-explicit-entry.n=4.c=flow-in.json.output
+++ b/tests/s-ns-flow-map-explicit-entry.n=4.c=flow-in.json.output
@@ -7,10 +7,10 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/s-ns-flow-map-explicit-entry.n=4.c=flow-in.value.output b/tests/s-ns-flow-map-explicit-entry.n=4.c=flow-in.value.output
--- a/tests/s-ns-flow-map-explicit-entry.n=4.c=flow-in.value.output
+++ b/tests/s-ns-flow-map-explicit-entry.n=4.c=flow-in.value.output
@@ -4,11 +4,11 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Ta
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/s-ns-flow-map-explicit-entry.n=4.c=flow-in.yaml.output b/tests/s-ns-flow-map-explicit-entry.n=4.c=flow-in.yaml.output
--- a/tests/s-ns-flow-map-explicit-entry.n=4.c=flow-in.yaml.output
+++ b/tests/s-ns-flow-map-explicit-entry.n=4.c=flow-in.yaml.output
@@ -5,11 +5,11 @@
 s
 n
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/s-ns-flow-map-explicit-json.n=4.c=flow-in.output b/tests/s-ns-flow-map-explicit-json.n=4.c=flow-in.output
--- a/tests/s-ns-flow-map-explicit-json.n=4.c=flow-in.output
+++ b/tests/s-ns-flow-map-explicit-json.n=4.c=flow-in.output
@@ -6,12 +6,12 @@
 I"
 s
 n
+!Commit to 'entry' was made outside it
 I:
+!Commit to 'pair' was made outside it
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
-!Commit to 'entry' was made outside it
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/tests/s-ns-flow-map-explicit-yaml.n=4.c=flow-in.output b/tests/s-ns-flow-map-explicit-yaml.n=4.c=flow-in.output
--- a/tests/s-ns-flow-map-explicit-yaml.n=4.c=flow-in.output
+++ b/tests/s-ns-flow-map-explicit-yaml.n=4.c=flow-in.output
@@ -4,13 +4,13 @@
 Ta
 s
 n
+!Commit to 'entry' was made outside it
 I:
+!Commit to 'pair' was made outside it
 w 
 N
 S
+!Commit to 'node' was made outside it
 Tb
 s
 n
-!Commit to 'entry' was made outside it
-!Commit to 'pair' was made outside it
-!Commit to 'node' was made outside it
diff --git a/yaml2yeast/Main.hs b/yaml2yeast/Main.hs
--- a/yaml2yeast/Main.hs
+++ b/yaml2yeast/Main.hs
@@ -132,6 +132,8 @@
 --
 --  [@y@] Ends YAML stream
 --
+--  [@!@] Parsing error at this point.
+--
 -- In addition, the following codes are used for testing partial productions
 -- and do not appear when parsing a complete YAML stream:
 --
