content: -- | This is just a simple token printer. It's not a full fledged formatter, but
  -- it is used by the layout golden tests. Printing each token in the tree with
  -- this printer will result in the exact input that was given to the lexer.
  
  module Language.PureScript.CST.Print
    ( printToken
    , printTokens
    , printModule
    , printLeadingComment
    , printTrailingComment
    ) where
  
  import Prelude
  
  import Data.DList qualified as DList
  import Data.Text (Text)
  import Data.Text qualified as Text
  import Language.PureScript.CST.Types (Comment(..), LineFeed(..), Module, SourceStyle(..), SourceToken(..), Token(..), TokenAnn(..))
  import Language.PureScript.CST.Flatten (flattenModule)
  
  printToken :: Token -> Text
  printToken = printToken' True
  
  -- | Prints a given Token. The bool controls whether or not layout
  -- tokens should be printed.
  printToken' :: Bool -> Token -> Text
  printToken' showLayout = \case
    TokLeftParen             -> "("
    TokRightParen            -> ")"
    TokLeftBrace             -> "{"
    TokRightBrace            -> "}"
    TokLeftSquare            -> "["
    TokRightSquare           -> "]"
    TokLeftArrow ASCII       -> "<-"
    TokLeftArrow Unicode     -> "←"
    TokRightArrow ASCII      -> "->"
    TokRightArrow Unicode    -> "→"
    TokRightFatArrow ASCII   -> "=>"
    TokRightFatArrow Unicode -> "⇒"
    TokDoubleColon ASCII     -> "::"
    TokDoubleColon Unicode   -> "∷"
    TokForall ASCII          -> "forall"
    TokForall Unicode        -> "∀"
    TokEquals                -> "="
    TokPipe                  -> "|"
    TokTick                  -> "`"
    TokDot                   -> "."
    TokComma                 -> ","
    TokUnderscore            -> "_"
    TokBackslash             -> "\\"
    TokLowerName qual name   -> printQual qual <> name
    TokUpperName qual name   -> printQual qual <> name
    TokOperator qual sym     -> printQual qual <> sym
    TokSymbolName qual sym   -> printQual qual <> "(" <> sym <> ")"
    TokSymbolArr Unicode     -> "(→)"
    TokSymbolArr ASCII       -> "(->)"
    TokHole hole             -> "?" <> hole
    TokChar raw _            -> "'" <> raw <> "'"
    TokString raw _          -> "\"" <> raw <> "\""
    TokRawString raw         -> "\"\"\"" <> raw <> "\"\"\""
    TokInt raw _             -> raw
    TokNumber raw _          -> raw
    TokLayoutStart           -> if showLayout then "{" else ""
    TokLayoutSep             -> if showLayout then ";" else ""
    TokLayoutEnd             -> if showLayout then "}" else ""
    TokEof                   -> if showLayout then "<eof>" else ""
  
  printQual :: [Text] -> Text
  printQual = Text.concat . map (<> ".")
  
  printTokens :: [SourceToken] -> Text
  printTokens = printTokens' True
  
  printTokens' :: Bool -> [SourceToken] -> Text
  printTokens' showLayout toks = Text.concat (map pp toks)
    where
    pp (SourceToken (TokenAnn _ leading trailing) tok) =
      Text.concat (map printLeadingComment leading)
        <> printToken' showLayout tok
        <> Text.concat (map printTrailingComment trailing)
  
  printModule :: Module a -> Text
  printModule = printTokens' False . DList.toList . flattenModule
  
  printLeadingComment :: Comment LineFeed -> Text
  printLeadingComment = \case
    Comment raw -> raw
    Space n -> Text.replicate n " "
    Line LF -> "\n"
    Line CRLF -> "\r\n"
  
  printTrailingComment :: Comment void -> Text
  printTrailingComment = \case
    Comment raw -> raw
    Space n -> Text.replicate n " "
    Line _ -> ""
  