    {-# LANGUAGE LambdaCase #-}
    -- | @since 1.4.2

    module Test.Tasty.Patterns.Printer
      ( printAwkExpr
      )
      where

    import Prelude hiding (LT, GT, EQ)
    import Test.Tasty.Patterns.Types

    -- | @since 1.4.2
    printAwkExpr :: Expr -> String
    printAwkExpr :: Expr -> String
    printAwkExpr Expr
    e = Int -> Expr -> ShowS
    go Int
    0 Expr
    e String
    ""

    go :: Int -> Expr -> ShowS
    go :: Int -> Expr -> ShowS
    go Int
    p = \case
      Expr
    NF -> String -> ShowS
    showString String
    "NF"
      IntLit Int
    n -> Int -> Int -> ShowS
    forall a. Show a => Int -> a -> ShowS
    showsPrec Int
    p Int
    n
      StringLit String
    xs -> Char -> ShowS
    showChar Char
    '"' ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString (ShowS
    escapeString String
    xs) ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    '"'
      ERE String
    xs -> Char -> ShowS
    showChar Char
    '/' ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString (ShowS
    escapeERE String
    xs) ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    '/'

      Field Expr
    x -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    9) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Char -> ShowS
    showChar Char
    '$' ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    9 Expr
    x

      -- Cf. comment for Test.Tasty.Patterns.Parser.expr2 to understand
      -- why we put showParens when precedence is 6 not 8.
      Neg Expr
    x -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    6) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Char -> ShowS
    showChar Char
    '-' ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    8 Expr
    x
      Not Expr
    x -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    8) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Char -> ShowS
    showChar Char
    '!' ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    8 Expr
    x

      Add Expr
    x Expr
    y -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    7) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Int -> Expr -> ShowS
    go Int
    7 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    '+' ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    7 Expr
    y
      Sub Expr
    x Expr
    y -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    7) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Int -> Expr -> ShowS
    go Int
    7 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    '-' ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    7 Expr
    y

      Concat Expr
    x Expr
    y -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    6) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Int -> Expr -> ShowS
    go Int
    6 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    ' ' ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    6 Expr
    y

      LT Expr
    x Expr
    y -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    5) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Int -> Expr -> ShowS
    go Int
    5 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    '<'    ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    5 Expr
    y
      LE Expr
    x Expr
    y -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    5) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Int -> Expr -> ShowS
    go Int
    5 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString String
    "<=" ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    5 Expr
    y
      GT Expr
    x Expr
    y -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    5) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Int -> Expr -> ShowS
    go Int
    5 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    '>'    ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    5 Expr
    y
      GE Expr
    x Expr
    y -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    5) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Int -> Expr -> ShowS
    go Int
    5 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString String
    ">=" ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    5 Expr
    y
      EQ Expr
    x Expr
    y -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    5) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Int -> Expr -> ShowS
    go Int
    5 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString String
    "==" ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    5 Expr
    y
      NE Expr
    x Expr
    y -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    5) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Int -> Expr -> ShowS
    go Int
    5 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString String
    "!=" ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    5 Expr
    y

      Match Expr
    x String
    y   -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    4) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Int -> Expr -> ShowS
    go Int
    4 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    '~'    ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    4 (String -> Expr
    ERE String
    y)
      NoMatch Expr
    x String
    y -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    4) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Int -> Expr -> ShowS
    go Int
    4 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString String
    "!~" ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    4 (String -> Expr
    ERE String
    y)

      And Expr
    x Expr
    y -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    2) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Int -> Expr -> ShowS
    go Int
    2 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString String
    "&&" ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    2 Expr
    y

      Or Expr
    x Expr
    y -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    1) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Int -> Expr -> ShowS
    go Int
    1 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString String
    "||" ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    1 Expr
    y

      If Expr
    c Expr
    t Expr
    f -> Bool -> ShowS -> ShowS
    showParen (Int
    p Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    0) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Int -> Expr -> ShowS
    go Int
    0 Expr
    c ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    '?' ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    0 Expr
    t ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    ':' ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    0 Expr
    f

      ToUpperFn Expr
    x -> String -> ShowS
    showString String
    "toupper(" ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    0 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    ')'
      ToLowerFn Expr
    x -> String -> ShowS
    showString String
    "tolower(" ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    0 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    ')'

      LengthFn Maybe Expr
    Nothing  -> String -> ShowS
    showString String
    "length()"
      LengthFn (Just Expr
    x) -> String -> ShowS
    showString String
    "length(" ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    0 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    ')'

      SubstrFn Expr
    x Expr
    y Maybe Expr
    Nothing  -> String -> ShowS
    showString String
    "substr(" ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    0 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    ',' ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    0 Expr
    y ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    ')'
      SubstrFn Expr
    x Expr
    y (Just Expr
    z) -> String -> ShowS
    showString String
    "substr(" ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    0 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    ',' ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    0 Expr
    y ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    ',' ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    0 Expr
    z ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    ')'

      MatchFn Expr
    x String
    y -> String -> ShowS
    showString String
    "match(" ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    0 Expr
    x ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    ',' ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Expr -> ShowS
    go Int
    0 (String -> Expr
    ERE String
    y) ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar Char
    ')'

    escapeString :: String -> String
    escapeString :: ShowS
    escapeString = (Char -> String) -> ShowS
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap ((Char -> String) -> ShowS) -> (Char -> String) -> ShowS
    forall a b. (a -> b) -> a -> b
    $ \Char
    c -> (if Char
    c Char -> String -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` String
    "\\\"" then (Char
    '\\' Char -> ShowS
    forall a. a -> [a] -> [a]
    :) else ShowS
    forall a. a -> a
    id) [Char
    c]

    escapeERE :: String -> String
    escapeERE :: ShowS
    escapeERE = (Char -> String) -> ShowS
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap ((Char -> String) -> ShowS) -> (Char -> String) -> ShowS
    forall a b. (a -> b) -> a -> b
    $ \Char
    c -> (if Char
    c Char -> String -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` String
    "\\/" then (Char
    '\\' Char -> ShowS
    forall a. a -> [a] -> [a]
    :) else ShowS
    forall a. a -> a
    id) [Char
    c]