{-# LANGUAGE LambdaCase #-}

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 -> forall a. Show a => Int -> a -> ShowS
showsPrec Int
p Int
n
  StringLit String
xs -> Char -> ShowS
showChar Char
'"' forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString (ShowS
escapeString String
xs) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
'"'
  ERE String
xs -> Char -> ShowS
showChar Char
'/' forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString (ShowS
escapeERE String
xs) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
'/'

  Field Expr
x -> Bool -> ShowS -> ShowS
showParen (Int
p forall a. Ord a => a -> a -> Bool
>= Int
9) forall a b. (a -> b) -> a -> b
$ Char -> ShowS
showChar Char
'$' 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 forall a. Ord a => a -> a -> Bool
>= Int
6) forall a b. (a -> b) -> a -> b
$ Char -> ShowS
showChar Char
'-' 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 forall a. Ord a => a -> a -> Bool
>= Int
8) forall a b. (a -> b) -> a -> b
$ Char -> ShowS
showChar Char
'!' 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 forall a. Ord a => a -> a -> Bool
>= Int
7) forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
go Int
7 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
'+' 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 forall a. Ord a => a -> a -> Bool
>= Int
7) forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
go Int
7 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
'-' 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 forall a. Ord a => a -> a -> Bool
>= Int
6) forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
go Int
6 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
' ' 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 forall a. Ord a => a -> a -> Bool
>= Int
5) forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
go Int
5 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
'<'    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 forall a. Ord a => a -> a -> Bool
>= Int
5) forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
go Int
5 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"<=" 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 forall a. Ord a => a -> a -> Bool
>= Int
5) forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
go Int
5 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
'>'    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 forall a. Ord a => a -> a -> Bool
>= Int
5) forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
go Int
5 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
">=" 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 forall a. Ord a => a -> a -> Bool
>= Int
5) forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
go Int
5 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"==" 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 forall a. Ord a => a -> a -> Bool
>= Int
5) forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
go Int
5 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"!=" 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 forall a. Ord a => a -> a -> Bool
>= Int
4) forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
go Int
4 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
'~'    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 forall a. Ord a => a -> a -> Bool
>= Int
4) forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
go Int
4 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"!~" 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 forall a. Ord a => a -> a -> Bool
>= Int
2) forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
go Int
2 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"&&" 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 forall a. Ord a => a -> a -> Bool
>= Int
1) forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
go Int
1 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"||" 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 forall a. Ord a => a -> a -> Bool
>= Int
0) forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
go Int
0 Expr
c forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
'?' forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
go Int
0 Expr
t forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
':' 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(" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
go Int
0 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
')'
  ToLowerFn Expr
x -> String -> ShowS
showString String
"tolower(" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
go Int
0 Expr
x 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(" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
go Int
0 Expr
x 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(" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
go Int
0 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
',' forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
go Int
0 Expr
y 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(" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
go Int
0 Expr
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
',' forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
go Int
0 Expr
y forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
',' forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
go Int
0 Expr
z forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
')'

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

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

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