From 218bf376ed9aad154453d809138203479591a3fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gohla?= Date: Mon, 28 Mar 2022 23:17:32 +0100 Subject: [PATCH] Extend Statement with IfThenElif construct --- hs/Language/Bash/PrettyPrinter.hs | 11 ++++++++++- hs/Language/Bash/Syntax.hs | 6 ++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/hs/Language/Bash/PrettyPrinter.hs b/hs/Language/Bash/PrettyPrinter.hs index 8091eca..b55eb52 100644 --- a/hs/Language/Bash/PrettyPrinter.hs +++ b/hs/Language/Bash/PrettyPrinter.hs @@ -18,6 +18,7 @@ import Data.Monoid import Prelude hiding ( words, unwords, concat, null , replicate, lines, drop, length ) import Control.Monad.State.Strict +import qualified Data.List.NonEmpty as NE (head, tail) import qualified Text.ShellEscape as Esc @@ -120,6 +121,15 @@ instance (Annotation t) => PP (Statement t) where inword "then" >> pp t' >> outdent >> nl inword "else" >> pp t'' outword "fi" + IfThenElif t t' -> do hangWord "if" >> pp (fst $ NE.head t) >> outdent >> nl + inword "then" >> pp (snd $ NE.head t) >> outdent >> nl + mapM_ elif_clause $ NE.tail t + inword "else" >> pp t' + outword "fi" + where + elif_clause (s, s') = do + hangWord "elif" >> pp s >> outdent >> nl + inword "then" >> pp s' >> outdent >> nl For var vals t -> do hangWord (concat ["for ", bytes var, " in"]) mapM_ breakline vals outdent >> nl @@ -257,4 +267,3 @@ inlineEvalPrinter open close ann = do outdent >> outdent escapeWords s = unwords ((Esc.bytes . Esc.bash) <$> words s) - diff --git a/hs/Language/Bash/Syntax.hs b/hs/Language/Bash/Syntax.hs index bc19d7b..1ea2509 100644 --- a/hs/Language/Bash/Syntax.hs +++ b/hs/Language/Bash/Syntax.hs @@ -22,6 +22,7 @@ import Data.Word (Word8) import Data.ByteString.Char8 import Data.Foldable hiding (all, any, elem) import Data.Monoid +import qualified Data.List.NonEmpty as NE (NonEmpty(..), toList) import qualified Text.ShellEscape as Esc @@ -39,6 +40,8 @@ instance Functor Annotated where instance Foldable Annotated where foldMap f (Annotated t stmt) = f t `mappend` foldMap f stmt +type IfThenElifBranch t = (Annotated t, Annotated t) + {-| The 'Statement' type captures the different kind of statements that may exist in a Bash statement tree. It is mutually recursive with 'Annotated'. It is a 'Foldable' and a 'Functor'. @@ -58,6 +61,7 @@ data Statement t | Function FuncName (Annotated t) | IfThen (Annotated t) (Annotated t) | IfThenElse (Annotated t) (Annotated t) (Annotated t) + | IfThenElif (NE.NonEmpty (IfThenElifBranch t)) (Annotated t) | For Identifier [Expression t] (Annotated t) | Case (Expression t) [(Expression t, Annotated t)] | While (Annotated t) (Annotated t) @@ -91,6 +95,7 @@ instance Functor Statement where Function fname ann -> Function fname (f' ann) IfThen ann ann' -> IfThen (f' ann) (f' ann') IfThenElse a a' a'' -> IfThenElse (f' a) (f' a') (f' a'') + IfThenElif a a' -> IfThenElif (fmap (f' *** f') a) (f' a') For ident args ann -> For ident (fmap f' args) (f' ann) Case expr cases -> Case (f' expr) (fmap (f' *** f') cases) While ann ann' -> While (f' ann) (f' ann') @@ -124,6 +129,7 @@ instance Foldable Statement where Function _ ann -> f' ann IfThen ann ann' -> f' ann `mappend` f' ann' IfThenElse a a' a'' -> foldMap f' [a, a', a''] + IfThenElif a a' -> foldMap foldMapPair (NE.toList a) `mappend` f' a' For _ args ann -> foldMap f' args `mappend` f' ann Case expr cases -> f' expr `mappend` foldMap foldMapPair cases While ann ann' -> f' ann `mappend` f' ann'