packages feed

simple-parser-0.9: src/SimpleParser/Errata.hs

{-# LANGUAGE OverloadedStrings #-}

module SimpleParser.Errata
  ( LinePosExplainable
  , errataParseError
  , errataParseResult
  ) where

import Control.Monad (join)
import Data.Foldable (toList)
import Data.Sequence (Seq (..))
import qualified Data.Text as T
import Errata (Block, Style, blockMerged')
import SimpleParser.Explain (ErrorExplanation (..), Explainable, ParseErrorExplanation (..), explainParseError)
import SimpleParser.Result (ParseError, ParseErrorBundle (ParseErrorBundle), ParseResult (..))
import SimpleParser.Stream (Col (..), HasLinePos (..), Line (..), Pos, Span (..))

type LinePosExplainable l s e = (Explainable l s e, HasLinePos (Pos s))

errataExplanation :: HasLinePos p => Style -> FilePath -> ParseErrorExplanation p -> Block
errataExplanation style fp (ParseErrorExplanation sp context mayDetails  (ErrorExplanation reason mayExpected mayActual)) =
  let Span startPos endPos = sp
      startLine = unLine (viewLine startPos)
      startCol = unCol (viewCol startPos)
      endLine = unLine (viewLine endPos)
      endCol = unCol (viewCol endPos)
      mayLabel = Just reason
      mayHeader =
       case context of
         Empty -> Nothing
         _ -> Just (T.intercalate " > " (toList context))
      start = (startLine + 1, startCol + 1, mayLabel)
      end = (endLine + 1, endCol + 1, Nothing)
      mayBody =
        case (mayDetails, mayExpected, mayActual) of
          (Nothing, Nothing, Nothing) -> Nothing
          _ -> Just $ T.unlines $ join
            [ maybe [] (\de -> ["[Details ] " <> de]) mayDetails
            , maybe [] (\ex -> ["[Expected] " <> ex]) mayExpected
            , maybe [] (\ac -> ["[Actual  ] " <> ac]) mayActual
            ]
  in blockMerged' style fp mayHeader start end mayLabel mayBody

errataParseError :: LinePosExplainable l s e => Style -> FilePath -> ParseError l s e -> Block
errataParseError style fp pe =
  let pee = explainParseError pe
  in errataExplanation style fp pee

errataParseResult :: LinePosExplainable l s e => Style -> FilePath -> ParseResult l s e a -> [Block]
errataParseResult style fp pr =
  case pr of
    ParseResultError (ParseErrorBundle errs) -> fmap (errataParseError style fp) (toList errs)
    ParseResultSuccess _ -> []