packages feed

YamlReference 0.2 → 0.3

raw patch · 149 files changed

+540/−511 lines, 149 files

Files

Text/Yaml/Reference.hs view
@@ -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 *)
YamlReference.cabal view
@@ -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
tests/c-b+block-header.n=2.s=folded.i.output view
@@ -1,4 +1,4 @@ I>-b\x0a !Commit to 'node' was made outside it+b\x0a $(m,t)=(1,clip)
tests/c-b+block-header.n=2.s=folded.im.output view
@@ -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)
tests/c-b+block-header.n=2.s=folded.imt.output view
@@ -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)
tests/c-b+block-header.n=2.s=folded.it.output view
@@ -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)
tests/c-b+block-header.n=2.s=folded.itm.output view
@@ -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)
tests/c-double-quoted.n=4.c=flow-out.invalid.output view
@@ -1,5 +1,5 @@ S I"-Ta !Commit to 'node' was made outside it+Ta !$InputFile$: line 1: column 2: Unexpected '\x0a'
tests/c-double-quoted.n=4.c=flow-out.output view
@@ -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
tests/c-flow-json-content.n=4.c=flow-in.double.output view
@@ -1,6 +1,6 @@ S I"+!Commit to 'node' was made outside it Ta I" s-!Commit to 'node' was made outside it
tests/c-flow-json-content.n=4.c=flow-in.mapping.output view
@@ -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
tests/c-flow-json-content.n=4.c=flow-in.sequence.output view
@@ -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
tests/c-flow-json-node.n=4.c=flow-in.tagged.output view
@@ -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
tests/c-flow-json-node.n=4.c=flow-in.untagged.output view
@@ -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
tests/c-flow-mapping.n=4.c=flow-in.compact.output view
@@ -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
tests/c-flow-mapping.n=4.c=flow-in.invalid.output view
@@ -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
tests/c-flow-mapping.n=4.c=flow-in.spaced.output view
@@ -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
tests/c-flow-sequence.n=4.c=flow-in.compact.output view
@@ -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
tests/c-flow-sequence.n=4.c=flow-in.invalid.output view
@@ -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
tests/c-flow-sequence.n=4.c=flow-in.spaced.output view
@@ -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
tests/c-l+folded.n=2.indent.output view
@@ -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
tests/c-l+folded.n=2.invalid.output view
@@ -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
tests/c-l+folded.n=2.simple.output view
@@ -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
tests/c-l+literal.n=2.invalid.output view
@@ -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
tests/c-l+literal.n=2.simple.output view
@@ -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
tests/c-l+literal.n=2.strip-indent.output view
@@ -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
tests/c-l+literal.n=2.strip.output view
@@ -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
tests/c-l-block-map-explicit-entry.n=2.output view
@@ -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
tests/c-l-block-map-explicit-key.n=2.output view
@@ -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
tests/c-l-block-map-implicit-value.n=2.empty.output view
@@ -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
tests/c-l-block-map-implicit-value.n=2.invalid.output view
@@ -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
tests/c-l-block-map-implicit-value.n=2.plain.output view
@@ -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
tests/c-l-block-seq-entry.n=2.output view
@@ -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
tests/c-ns-alias.output view
@@ -1,5 +1,5 @@ R I*+!Commit to 'node' was made outside it t*&!name r-!Commit to 'node' was made outside it
tests/c-ns-flow-map-adjacent-value.n=4.c=flow-in.compact.output view
@@ -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
tests/c-ns-flow-map-adjacent-value.n=4.c=flow-in.empty.output view
@@ -1,6 +1,6 @@ I:+!Commit to 'pair' was made outside it N S s n-!Commit to 'pair' was made outside it
tests/c-ns-flow-map-adjacent-value.n=4.c=flow-in.spaced.output view
@@ -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
tests/c-ns-flow-map-implicit-json.n=4.c=flow-in.compact.output view
@@ -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
tests/c-ns-flow-map-implicit-json.n=4.c=flow-in.spaced.output view
@@ -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
tests/c-ns-flow-map-separate-value.n=4.c=flow-in.empty.output view
@@ -1,6 +1,6 @@ I:+!Commit to 'pair' was made outside it N S s n-!Commit to 'pair' was made outside it
tests/c-ns-flow-map-separate-value.n=4.c=flow-in.invalid.output view
@@ -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
tests/c-ns-flow-map-separate-value.n=4.c=flow-in.value.output view
@@ -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
tests/c-ns-flow-map-single-json.n=4.c=flow-in.output view
@@ -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
tests/c-quoted-quote.output view
@@ -1,5 +1,5 @@ E I'+!Commit to 'escape' was made outside it t' e-!Commit to 'escape' was made outside it
− tests/debug-leak.input
@@ -1,1 +0,0 @@-#
− tests/debug-leak.output
@@ -1,2 +0,0 @@-I#-?\x0a
tests/l+block-mapping.n=1.output view
@@ -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
tests/l+block-sequence.n=1.output view
@@ -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
tests/l-block-map-explicit-value.n=2.output view
@@ -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
tests/l-explicit-document.invalid.output view
@@ -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
tests/l-explicit-document.literal.output view
@@ -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
tests/l-explicit-document.plain.output view
@@ -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
tests/l-implicit-document.invalid.output view
@@ -1,4 +1,4 @@ O N S-!$InputFile$: line 1: column 0: Forbidden pattern detected+!$InputFile$: line 1: column 0: Unexpected forbidden pattern
tests/l-implicit-document.literal.output view
@@ -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
tests/l-implicit-document.plain.output view
@@ -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
tests/l-nb-folded-lines.n=4.invalid.output view
@@ -1,4 +1,4 @@ i    -?a !Commit to 'fold' was made outside it+?a !$InputFile$: line 1: column 5: Expected end of input
tests/l-nb-folded-lines.n=4.output view
@@ -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
tests/l-nb-spaced-lines.n=4.output view
@@ -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
tests/l-nb-start-with-folded.n=4.output view
@@ -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
tests/l-nb-start-with-spaced.n=4.output view
@@ -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
tests/ns-esc-16-bit.output view
@@ -1,3 +1,3 @@ Iu-tFEDC !Commit to 'escaped' was made outside it+tFEDC
tests/ns-esc-32-bit.output view
@@ -1,3 +1,3 @@ IU-t0010FEDC !Commit to 'escaped' was made outside it+t0010FEDC
tests/ns-esc-8-bit.output view
@@ -1,3 +1,3 @@ Ix-tFF !Commit to 'escaped' was made outside it+tFF
tests/ns-esc-char.16-bit.output view
@@ -1,6 +1,6 @@ E I\x5c+!Commit to 'escape' was made outside it Iu tFEDC e-!Commit to 'escape' was made outside it
tests/ns-esc-char.32-bit.output view
@@ -1,6 +1,6 @@ E I\x5c+!Commit to 'escape' was made outside it IU t0010FEDC e-!Commit to 'escape' was made outside it
tests/ns-esc-char.8-bit.output view
@@ -1,6 +1,6 @@ E I\x5c+!Commit to 'escape' was made outside it Ix tFF e-!Commit to 'escape' was made outside it
tests/ns-esc-char.backslash.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it t\x5c e-!Commit to 'escape' was made outside it
tests/ns-esc-char.bell.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it ta e-!Commit to 'escape' was made outside it
tests/ns-esc-char.bs.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it tb e-!Commit to 'escape' was made outside it
tests/ns-esc-char.cr.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it tr e-!Commit to 'escape' was made outside it
tests/ns-esc-char.double-quote.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it t" e-!Commit to 'escape' was made outside it
tests/ns-esc-char.esc.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it te e-!Commit to 'escape' was made outside it
tests/ns-esc-char.ff.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it tf e-!Commit to 'escape' was made outside it
tests/ns-esc-char.lf.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it tn e-!Commit to 'escape' was made outside it
tests/ns-esc-char.ls.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it tL e-!Commit to 'escape' was made outside it
tests/ns-esc-char.nbsp.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it t_ e-!Commit to 'escape' was made outside it
tests/ns-esc-char.nl.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it tN e-!Commit to 'escape' was made outside it
tests/ns-esc-char.null.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it t0 e-!Commit to 'escape' was made outside it
tests/ns-esc-char.ps.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it tP e-!Commit to 'escape' was made outside it
tests/ns-esc-char.sp.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it t  e-!Commit to 'escape' was made outside it
tests/ns-esc-char.tab.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it tt e-!Commit to 'escape' was made outside it
tests/ns-esc-char.vt.output view
@@ -1,5 +1,5 @@ E I\x5c+!Commit to 'escape' was made outside it tv e-!Commit to 'escape' was made outside it
tests/ns-flow-content.n=4.c=flow-in.json.output view
@@ -1,6 +1,6 @@ S I"+!Commit to 'node' was made outside it Ta I" s-!Commit to 'node' was made outside it
tests/ns-flow-content.n=4.c=flow-in.yaml.output view
@@ -1,4 +1,4 @@ S+!Commit to 'node' was made outside it Ta s-!Commit to 'node' was made outside it
tests/ns-flow-map-entry.n=4.c=flow-in.explicit.output view
@@ -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
tests/ns-flow-map-implicit-empty.n=4.c=flow-in.invalid.output view
@@ -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
tests/ns-flow-map-implicit-empty.n=4.c=flow-in.output view
@@ -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
tests/ns-flow-map-implicit-entry.n=4.c=flow-in.empty.output view
@@ -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
tests/ns-flow-map-implicit-entry.n=4.c=flow-in.json.output view
@@ -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
tests/ns-flow-map-implicit-entry.n=4.c=flow-in.yaml.output view
@@ -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
tests/ns-flow-map-implicit-yaml.n=4.c=flow-in.compact.output view
@@ -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
tests/ns-flow-map-implicit-yaml.n=4.c=flow-in.spaced.output view
@@ -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
tests/ns-flow-map-single-entry.n=4.c=flow-in.empty.output view
@@ -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
tests/ns-flow-map-single-entry.n=4.c=flow-in.json.output view
@@ -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
tests/ns-flow-map-single-entry.n=4.c=flow-in.yaml.output view
@@ -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
tests/ns-flow-map-single-pair.n=4.c=flow-in.explicit.output view
@@ -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
tests/ns-flow-map-single-pair.n=4.c=flow-in.implicit.output view
@@ -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
tests/ns-flow-map-single-yaml.n=4.c=flow-in.output view
@@ -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
tests/ns-flow-node.n=4.c=flow-in.alias.output view
@@ -1,7 +1,7 @@ N R I*+!Commit to 'node' was made outside it ta r n-!Commit to 'node' was made outside it
tests/ns-flow-node.n=4.c=flow-in.tagged.output view
@@ -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
tests/ns-flow-node.n=4.c=flow-in.untagged.output view
@@ -1,6 +1,6 @@ N S+!Commit to 'node' was made outside it Ta s n-!Commit to 'node' was made outside it
tests/ns-flow-seq-entry.n=4.c=flow-in.pair.output view
@@ -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
tests/ns-flow-yaml-content.n=4.c=flow-in.output view
@@ -1,4 +1,4 @@ S+!Commit to 'node' was made outside it Ta s-!Commit to 'node' was made outside it
tests/ns-flow-yaml-node.n=4.c=flow-in.alias.output view
@@ -1,7 +1,7 @@ N R I*+!Commit to 'node' was made outside it ta r n-!Commit to 'node' was made outside it
tests/ns-flow-yaml-node.n=4.c=flow-in.tagged.output view
@@ -9,7 +9,7 @@ p w  S+!Commit to 'node' was made outside it Ta s n-!Commit to 'node' was made outside it
tests/ns-flow-yaml-node.n=4.c=flow-in.untagged.output view
@@ -1,6 +1,6 @@ N S+!Commit to 'node' was made outside it Ta s n-!Commit to 'node' was made outside it
tests/ns-l-block-map-entry.n=2.explicit.output view
@@ -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
tests/ns-l-block-map-entry.n=2.implicit.output view
@@ -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
tests/ns-l-block-map-implicit-entry.n=2.empty.output view
@@ -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
tests/ns-l-block-map-implicit-entry.n=2.non-empty.output view
@@ -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
tests/ns-l-in-line-mapping.n=2.output view
@@ -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
tests/ns-l-in-line-sequence.n=3.invalid.output view
@@ -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
tests/ns-l-in-line-sequence.n=3.output view
@@ -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
tests/ns-plain-multi.n=4.c=flow-in.invalid.output view
@@ -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
tests/ns-plain-multi.n=4.c=flow-in.output view
@@ -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
tests/ns-plain-single.c=flow-key.invalid.output view
@@ -1,3 +1,3 @@-?12 !Commit to 'node' was made outside it+?12 !$InputFile$: line 1: column 2: Expected end of input
tests/ns-plain-single.c=flow-out.output view
@@ -1,2 +1,2 @@-?a \x09" :# {} b !Commit to 'node' was made outside it+?a \x09" :# {} b
tests/ns-plain.n=4.c=flow-in.output view
@@ -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
tests/ns-plain.n=4.c=flow-key.invalid.output view
@@ -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
tests/ns-plain.n=4.c=flow-key.output view
@@ -1,4 +1,4 @@ S+!Commit to 'node' was made outside it Ta \x09" :# () b s-!Commit to 'node' was made outside it
tests/ns-s-flow-map-entries.n=4.c=flow-in.multi.output view
@@ -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
tests/ns-s-flow-map-entries.n=4.c=flow-in.single.output view
@@ -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
tests/ns-s-flow-seq-entries.n=4.c=flow-in.multi.output view
@@ -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
tests/ns-tag-directive.invalid.output view
@@ -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'
tests/ns-tag-directive.output view
@@ -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
tests/ns-yaml-directive.invalid.output view
@@ -1,4 +1,4 @@ tYAML-w  !Commit to 'directive' was made outside it+w  !$InputFile$: line 1: column 5: Unexpected 'a'
tests/ns-yaml-directive.output view
@@ -1,4 +1,4 @@ tYAML+!Commit to 'directive' was made outside it w  t0.1-!Commit to 'directive' was made outside it
tests/s-b-double-escaped.output view
@@ -1,6 +1,6 @@ ?  E I\x5c+!Commit to 'escape' was made outside it b\x0a e-!Commit to 'escape' was made outside it
tests/s-l+block-content.n=2.c=block-in.sequence.output view
@@ -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
tests/s-l+block-content.n=2.c=block-out.folded.output view
@@ -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
tests/s-l+block-content.n=2.c=block-out.literal.output view
@@ -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
tests/s-l+block-content.n=2.c=block-out.mapping.output view
@@ -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
tests/s-l+block-in-block.n=2.c=block-out.tagged.output view
@@ -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
tests/s-l+block-in-block.n=2.c=block-out.untagged.output view
@@ -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
tests/s-l+block-indented.n=2.c=block-in.sequence.output view
@@ -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
tests/s-l+block-indented.n=2.c=block-out.literal.output view
@@ -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
tests/s-l+block-indented.n=2.c=block-out.sequence.output view
@@ -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
tests/s-l+block-node.n=2.c=block-out.block.output view
@@ -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
tests/s-l+block-node.n=2.c=block-out.flow.output view
@@ -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
tests/s-l+flow-in-block.n=2.output view
@@ -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
tests/s-nb-folded-text.n=4.output view
@@ -1,3 +1,3 @@ i    -?a !Commit to 'fold' was made outside it+?a
tests/s-nb-spaced-text.n=4.output view
@@ -1,3 +1,3 @@ i    -? a !Commit to 'fold' was made outside it+? a
tests/s-ns-flow-map-explicit-empty.n=4.c=flow-in.output view
@@ -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
tests/s-ns-flow-map-explicit-entry.n=4.c=flow-in.json.output view
@@ -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
tests/s-ns-flow-map-explicit-entry.n=4.c=flow-in.value.output view
@@ -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
tests/s-ns-flow-map-explicit-entry.n=4.c=flow-in.yaml.output view
@@ -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
tests/s-ns-flow-map-explicit-json.n=4.c=flow-in.output view
@@ -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
tests/s-ns-flow-map-explicit-yaml.n=4.c=flow-in.output view
@@ -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
yaml2yeast/Main.hs view
@@ -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: --