From c865e527d4dc17a18b726980c5804313f2681213 Mon Sep 17 00:00:00 2001 From: Pascal Hof Date: Mon, 7 Mar 2016 14:23:46 +0100 Subject: [PATCH 01/12] create cabal files --- source/BNFC.cabal | 6 +- source/src/BNFC/Backend/Haskell.hs | 9 ++- source/src/BNFC/Backend/Haskell/CFtoCabal.hs | 76 ++++++++++++++++++++ source/src/BNFC/Backend/Haskell/HsOpts.hs | 2 +- source/src/BNFC/Backend/HaskellGADT.hs | 2 + source/src/BNFC/Options.hs | 8 ++- source/test/BNFC/Backend/HaskellSpec.hs | 6 ++ testing/Main.hs | 5 +- testing/src/HaskellCabalTests.hs | 44 ++++++++++++ 9 files changed, 149 insertions(+), 9 deletions(-) create mode 100644 source/src/BNFC/Backend/Haskell/CFtoCabal.hs create mode 100644 testing/src/HaskellCabalTests.hs diff --git a/source/BNFC.cabal b/source/BNFC.cabal index fece5f6ef..18da67a18 100644 --- a/source/BNFC.cabal +++ b/source/BNFC.cabal @@ -50,7 +50,8 @@ Executable bnfc containers, pretty >=1.1 && <1.2, filepath, - deepseq + deepseq, + Cabal == 1.22.* if impl(ghc < 7.6.1) Build-depends: ghc-prim build-tools: alex, happy @@ -94,6 +95,7 @@ Executable bnfc BNFC.Backend.Haskell, BNFC.Backend.Haskell.ToCNF, BNFC.Backend.Haskell.RegToAlex, + BNFC.Backend.Haskell.CFtoCabal, BNFC.Backend.Haskell.CFtoTemplate, BNFC.Backend.Haskell.CFtoAlex3, BNFC.Backend.Haskell.CFtoAlex2, @@ -191,7 +193,7 @@ Test-suite unit-tests Type: exitcode-stdio-1.0 Build-Depends: base>=4 && <5, mtl, directory, array, process, filepath, pretty, hspec, QuickCheck >= 2.5, HUnit, - temporary, containers, deepseq + temporary, containers, deepseq, Cabal == 1.22.* Main-is: unit-tests.hs HS-source-dirs: src test extensions: OverloadedStrings RecordWildCards FlexibleContexts diff --git a/source/src/BNFC/Backend/Haskell.hs b/source/src/BNFC/Backend/Haskell.hs index 6c7fb7f36..18a1ddc90 100644 --- a/source/src/BNFC/Backend/Haskell.hs +++ b/source/src/BNFC/Backend/Haskell.hs @@ -34,6 +34,7 @@ import BNFC.Backend.Haskell.CFtoAbstract import BNFC.Backend.Haskell.CFtoTemplate import BNFC.Backend.Haskell.CFtoPrinter import BNFC.Backend.Haskell.CFtoLayout +import BNFC.Backend.Haskell.CFtoCabal import BNFC.Backend.XML import BNFC.Backend.Haskell.HsOpts import BNFC.Backend.Haskell.ToCNF as ToCNF @@ -81,6 +82,7 @@ makeHaskell opts cf = do mkfile (txtFile opts) $ cfToTxt (lang opts) cf mkfile (templateFile opts) $ cf2Template (templateFileM opts) absMod errMod (functor opts) cf mkfile (printerFile opts) $ cf2Printer (byteStrings opts) (functor opts) False prMod absMod cf + mkfile (cabalFile opts) $ cf2Cabal opts when (hasLayout cf) $ mkfile (layoutFile opts) $ cf2Layout (alex1 opts) (inDir opts) layMod lexMod cf mkfile (errFile opts) $ mkErrM errMod (ghcExtensions opts) when (shareStrings opts) $ mkfile (shareFile opts) $ sharedString shareMod (byteStrings opts) cf @@ -106,9 +108,10 @@ makefile opts = makeA where [ if cnf opts then "ghc --make TestCNF.hs" else "ghc --make " ++ tFile opts ++ " -o " ++ mkFile withLang "Test" "" opts]) - , Makefile.mkRule "clean" [] + , Makefile.mkRule "clean" [] $ [ "-rm -f " ++ unwords - (map (dir++) [ "*.log", "*.aux", "*.hi", "*.o", "*.dvi" ]) ] + (map (dir++) [ "*.log", "*.aux", "*.hi", "*.o", "*.dvi" ]) ]++ + [ "cabal clean" | cabal opts ] , Makefile.mkRule "distclean" ["clean"] [ "-rm -f " ++ unwords [ mkFile withLang "Doc" "*" opts @@ -120,6 +123,7 @@ makefile opts = makeA where , mkFile withLang "Test" "*" opts , mkFile withLang "Abs" "*" opts , mkFile withLang "Test" "" opts + , mkFile withLang "" "cabal*" opts , mkFile noLang "ErrM" "*" opts , mkFile noLang "SharedString" "*" opts , mkFile noLang "ComposOp" "*" opts @@ -278,4 +282,3 @@ liftParser , " dec_fn f = decode (find f) r" , " in GLR_Result (\\ff -> dec_fn $ ff f) (dec_fn f)" ] - diff --git a/source/src/BNFC/Backend/Haskell/CFtoCabal.hs b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs new file mode 100644 index 000000000..3d0772717 --- /dev/null +++ b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs @@ -0,0 +1,76 @@ +{- + BNF Converter: Abstract syntax Generator + Copyright (C) 2016 Author: Pascal Hof + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-} + +module BNFC.Backend.Haskell.CFtoCabal (cf2Cabal) where + +import Distribution.Simple hiding (Language) +import Distribution.ModuleName(ModuleName,fromString) +import Distribution.PackageDescription +import Distribution.PackageDescription.Parse(showPackageDescription) + +import BNFC.Backend.Haskell.HsOpts +import BNFC.Options hiding (Version) + +-- to produce a Cabal file +cf2Cabal :: SharedOptions -> String +cf2Cabal = showPackageDescription . buildPackageDescription + +buildPackageDescription :: SharedOptions -> PackageDescription +buildPackageDescription opt = emptyPackageDescription + { package = + PackageIdentifier + { pkgName = PackageName (lang opt) + , pkgVersion = Version [0,1] []} + , library = + Just Library + { exposedModules = exposedMods opt + , reexportedModules = [] + , requiredSignatures = [] + , exposedSignatures = [] + , libExposed = True + , libBuildInfo = emptyBuildInfo + { buildable = True + , hsSourceDirs = ["."] + , targetBuildDepends = dependencies opt + } + } + , extraSrcFiles = [ happyFile opt, alexFile opt ] + , buildType = Just Simple + , license = AllRightsReserved + } + +dependencies :: SharedOptions -> [Dependency] +dependencies opt = + [ Dependency (PackageName "base") (laterVersion $ Version [4] []) + , Dependency (PackageName "array") anyVersion + ] ++ + [ Dependency (PackageName "mtl") anyVersion | TargetHaskellGadt == target opt ] + + +-- |returns a list of all exposed modules +exposedMods :: SharedOptions -> [ModuleName] +exposedMods opt = map fromString $ + [absFileM opt + ,errFileM opt + ,printerFileM opt + ,alexFileM opt + ,happyFileM opt + ] ++ + [xmlFileM opt | xml opt > 0] ++ + [composOpFileM opt | TargetHaskellGadt == target opt ] diff --git a/source/src/BNFC/Backend/Haskell/HsOpts.hs b/source/src/BNFC/Backend/Haskell/HsOpts.hs index a37757b9f..d2727ca3b 100644 --- a/source/src/BNFC/Backend/Haskell/HsOpts.hs +++ b/source/src/BNFC/Backend/Haskell/HsOpts.hs @@ -45,7 +45,7 @@ xmlFile = mkFile withLang "XML" "hs" xmlFileM = mkMod withLang "XML" composOpFile = mkFile noLang "ComposOp" "hs" composOpFileM = mkMod noLang "ComposOp" - +cabalFile opt = lang opt ++ ".cabal" noLang :: Options -> String -> String noLang _ name = name diff --git a/source/src/BNFC/Backend/HaskellGADT.hs b/source/src/BNFC/Backend/HaskellGADT.hs index b0dc6c82d..dc2de2eb4 100644 --- a/source/src/BNFC/Backend/HaskellGADT.hs +++ b/source/src/BNFC/Backend/HaskellGADT.hs @@ -34,6 +34,7 @@ import BNFC.Backend.HaskellGADT.CFtoAbstractGADT import BNFC.Backend.HaskellGADT.CFtoTemplateGADT import BNFC.Backend.Haskell.CFtoPrinter import BNFC.Backend.Haskell.CFtoLayout +import BNFC.Backend.Haskell.CFtoCabal import BNFC.Backend.XML import BNFC.Backend.Haskell.MkErrM import BNFC.Backend.Haskell.MkSharedString @@ -71,6 +72,7 @@ makeHaskellGadt opts cf = do liftIO $ putStrLn " (Tested with Happy 1.15)" mkfile (templateFile opts) $ cf2Template (templateFileM opts) absMod errMod cf mkfile (printerFile opts) $ cf2Printer False False True prMod absMod cf + mkfile (cabalFile opts) $ cf2Cabal opts when (hasLayout cf) $ mkfile (layoutFile opts) $ cf2Layout (alexMode opts == Alex1) (inDir opts) layMod lexMod cf mkfile (tFile opts) $ Haskell.testfile opts cf mkfile (errFile opts) $ mkErrM errMod (ghcExtensions opts) diff --git a/source/src/BNFC/Options.hs b/source/src/BNFC/Options.hs index c21ddc394..98a695b00 100644 --- a/source/src/BNFC/Options.hs +++ b/source/src/BNFC/Options.hs @@ -76,6 +76,7 @@ data SharedOptions = Options , glr :: HappyMode , xml :: Int , ghcExtensions :: Bool + , cabal :: Bool -- C++ specific , linenumbers :: Bool -- ^ Add and set line_number field for syntax classes -- C# specific @@ -103,6 +104,7 @@ defaultOptions = Options , glr = Standard , xml = 0 , ghcExtensions = False + , cabal = False , lang = error "lang not set" , linenumbers = False , visualStudio = False @@ -122,7 +124,7 @@ globalOptions = [ -- | Options for the target languages -- targetOptions :: [ OptDescr Target ] targetOptions :: [ OptDescr (SharedOptions -> SharedOptions)] -targetOptions = +targetOptions = [ Option "" ["java"] (NoArg (\o -> o {target = TargetJava})) "Output Java code [default: for use with JLex and CUP]" , Option "" ["haskell"] (NoArg (\o -> o {target = TargetHaskell})) @@ -206,6 +208,9 @@ specificOptions = , ( Option [] ["ghc"] (NoArg (\o -> o {ghcExtensions = True})) "Use ghc-specific language extensions" , [TargetHaskell, TargetHaskellGadt, TargetProfile] ) + , ( Option [] ["cabal"] (NoArg (\o -> o {cabal = True})) + "Also generate cabal file" + , [TargetHaskell,TargetHaskellGadt] ) , ( Option [] ["functor"] (NoArg (\o -> o {functor = True})) "Make the AST a functor and use it to store the position of the nodes" , [TargetHaskell] ) @@ -301,4 +306,3 @@ translateOldOptions = concatMap translateOne translateOne "-vs" = return "--vs" translateOne "-wcf" = return "--wcf" translateOne other = return other - diff --git a/source/test/BNFC/Backend/HaskellSpec.hs b/source/test/BNFC/Backend/HaskellSpec.hs index 28cf78db4..3340d4e85 100644 --- a/source/test/BNFC/Backend/HaskellSpec.hs +++ b/source/test/BNFC/Backend/HaskellSpec.hs @@ -56,3 +56,9 @@ spec = do calc <- getCalc let options = calcOptions { make = Just "MyMakefile" } makeHaskell options calc `shouldGenerate` "MyMakefile" + + context "with option --cabal and the Calc grammar" $ do + it "generates a cabal file" $ do + calc <- getCalc + let options = calcOptions { cabal = True } + makeHaskell options calc `shouldGenerate` "Calc.cabal" diff --git a/testing/Main.hs b/testing/Main.hs index 2862c0152..2a41e00e2 100644 --- a/testing/Main.hs +++ b/testing/Main.hs @@ -2,6 +2,7 @@ module Main (main) where import Test.Framework (htfMain) +import HaskellCabalTests import HaskellCnfTests import ParameterizedTests import PygmentsTests @@ -12,4 +13,6 @@ main = htfMain [ ParameterizedTests.all , RegressionTests.all , PygmentsTests.all , HaskellCnfTests.all - , OutputParser.tests ] + , OutputParser.tests + , HaskellCabalTests.all + ] diff --git a/testing/src/HaskellCabalTests.hs b/testing/src/HaskellCabalTests.hs new file mode 100644 index 000000000..6dd06cc43 --- /dev/null +++ b/testing/src/HaskellCabalTests.hs @@ -0,0 +1,44 @@ +module HaskellCabalTests (all) where + +import Shelly +import Prelude hiding (all,unlines) +import Data.Text(Text,unlines,unpack) +import TestUtils(Test,makeShellyTest,makeTestSuite,assertFileExists) + +all = makeTestSuite "Haskell/Cabal" + [ mkTest target desc ps + | (desc,ps) <- params + , target <- ["--haskell","--haskell-gadt"] + ] + +-- |a list of test description and the respective arguments to bnfc +params :: [(String,[Text])] +params = + [("Cabal only",[]) + ,("Ghc",["--ghc"]) + ,("Functor",["--functor"]) + ,("Xml",["--xml"]) + ,("Xmlt",["--xmlt"]) + ,("Qualified",["-d"]) + ,("Namespace",["-p","Foobar"]) + ,("Qualified namespace",["-p","Foobar","-d"]) + ] + +-- |building the Shelly Test +mkTest :: Text -> String -> [Text] -> Test +mkTest target desc bnfcParams = + makeShellyTest description $ withTmpDir $ \tmp -> do + cd tmp + writefile "Test.cf" $ unlines + [ "Start. S ::= S \"a\" ;" + , "End. S ::= ;" ] + run_ "bnfc" args + assertFileExists "Test.cabal" + cmd "cabal" "configure" + cmd "cabal" "build" + where + args :: [Text] + args = target:"--cabal":bnfcParams ++ ["Test.cf"] + + description :: String + description = desc++",Target "++drop 2 (unpack target) From 37315e2b9e36c736aca2e65eb7159ffbb3f633b5 Mon Sep 17 00:00:00 2001 From: Pascal Hof Date: Mon, 7 Mar 2016 14:42:52 +0100 Subject: [PATCH 02/12] widened cabal dependencies --- source/BNFC.cabal | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/BNFC.cabal b/source/BNFC.cabal index 18da67a18..113adf39f 100644 --- a/source/BNFC.cabal +++ b/source/BNFC.cabal @@ -51,7 +51,7 @@ Executable bnfc pretty >=1.1 && <1.2, filepath, deepseq, - Cabal == 1.22.* + Cabal >= 1.18 && < 1.23 if impl(ghc < 7.6.1) Build-depends: ghc-prim build-tools: alex, happy @@ -193,7 +193,7 @@ Test-suite unit-tests Type: exitcode-stdio-1.0 Build-Depends: base>=4 && <5, mtl, directory, array, process, filepath, pretty, hspec, QuickCheck >= 2.5, HUnit, - temporary, containers, deepseq, Cabal == 1.22.* + temporary, containers, deepseq, Cabal >= 1.18 && < 1.23 Main-is: unit-tests.hs HS-source-dirs: src test extensions: OverloadedStrings RecordWildCards FlexibleContexts From ed6e8665c5734f9f2ff42cbeaaa75667608d80c0 Mon Sep 17 00:00:00 2001 From: Pascal Hof Date: Mon, 7 Mar 2016 14:50:11 +0100 Subject: [PATCH 03/12] even cabal 1.16 should work --- source/BNFC.cabal | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/BNFC.cabal b/source/BNFC.cabal index 113adf39f..d8a62a925 100644 --- a/source/BNFC.cabal +++ b/source/BNFC.cabal @@ -51,7 +51,7 @@ Executable bnfc pretty >=1.1 && <1.2, filepath, deepseq, - Cabal >= 1.18 && < 1.23 + Cabal >= 1.16 && < 1.23 if impl(ghc < 7.6.1) Build-depends: ghc-prim build-tools: alex, happy @@ -193,7 +193,7 @@ Test-suite unit-tests Type: exitcode-stdio-1.0 Build-Depends: base>=4 && <5, mtl, directory, array, process, filepath, pretty, hspec, QuickCheck >= 2.5, HUnit, - temporary, containers, deepseq, Cabal >= 1.18 && < 1.23 + temporary, containers, deepseq, Cabal >= 1.16 && < 1.23 Main-is: unit-tests.hs HS-source-dirs: src test extensions: OverloadedStrings RecordWildCards FlexibleContexts From 0ecf0003f9cbb299f827309cddf7bb5c702360dc Mon Sep 17 00:00:00 2001 From: Pascal Hof Date: Mon, 7 Mar 2016 14:59:18 +0100 Subject: [PATCH 04/12] using mempty as default value for a cabal library --- source/src/BNFC/Backend/Haskell/CFtoCabal.hs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/source/src/BNFC/Backend/Haskell/CFtoCabal.hs b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs index 3d0772717..d28c71e3e 100644 --- a/source/src/BNFC/Backend/Haskell/CFtoCabal.hs +++ b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs @@ -38,11 +38,8 @@ buildPackageDescription opt = emptyPackageDescription { pkgName = PackageName (lang opt) , pkgVersion = Version [0,1] []} , library = - Just Library + Just mempty { exposedModules = exposedMods opt - , reexportedModules = [] - , requiredSignatures = [] - , exposedSignatures = [] , libExposed = True , libBuildInfo = emptyBuildInfo { buildable = True From 0a28b279f68871349e7514285dfd3b953a9ee2a2 Mon Sep 17 00:00:00 2001 From: Pascal Hof Date: Mon, 7 Mar 2016 15:25:26 +0100 Subject: [PATCH 05/12] import mempty --- source/src/BNFC/Backend/Haskell/CFtoCabal.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/source/src/BNFC/Backend/Haskell/CFtoCabal.hs b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs index d28c71e3e..bb5b901e7 100644 --- a/source/src/BNFC/Backend/Haskell/CFtoCabal.hs +++ b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs @@ -26,6 +26,7 @@ import Distribution.PackageDescription.Parse(showPackageDescription) import BNFC.Backend.Haskell.HsOpts import BNFC.Options hiding (Version) +import Data.Monoid(mempty) -- to produce a Cabal file cf2Cabal :: SharedOptions -> String From 457808d30f76683e828e58188a2b48268b678f49 Mon Sep 17 00:00:00 2001 From: Pascal Hof Date: Sat, 19 Nov 2016 11:35:07 +0100 Subject: [PATCH 06/12] created cabal file offers building the test program (executable) --- source/src/BNFC/Backend/Haskell/CFtoCabal.hs | 45 ++++++++++++++------ testing/src/HaskellCabalTests.hs | 3 +- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/source/src/BNFC/Backend/Haskell/CFtoCabal.hs b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs index bb5b901e7..9b64894f9 100644 --- a/source/src/BNFC/Backend/Haskell/CFtoCabal.hs +++ b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs @@ -38,32 +38,49 @@ buildPackageDescription opt = emptyPackageDescription PackageIdentifier { pkgName = PackageName (lang opt) , pkgVersion = Version [0,1] []} - , library = - Just mempty - { exposedModules = exposedMods opt - , libExposed = True - , libBuildInfo = emptyBuildInfo - { buildable = True - , hsSourceDirs = ["."] - , targetBuildDepends = dependencies opt - } - } + , library = Just (createLibrary opt) + , executables = [createExecutable opt] , extraSrcFiles = [ happyFile opt, alexFile opt ] , buildType = Just Simple , license = AllRightsReserved + , specVersionRaw = Right (orLaterVersion $ Version [1,22] []) } dependencies :: SharedOptions -> [Dependency] dependencies opt = - [ Dependency (PackageName "base") (laterVersion $ Version [4] []) + [ Dependency (PackageName "base") (orLaterVersion $ Version [4] []) , Dependency (PackageName "array") anyVersion ] ++ [ Dependency (PackageName "mtl") anyVersion | TargetHaskellGadt == target opt ] +createLibrary :: SharedOptions -> Library +createLibrary opt = mempty + { exposedModules = exposedLibMods opt + , libExposed = True + , libBuildInfo = emptyBuildInfo + { buildable = True + , hsSourceDirs = ["."] + , targetBuildDepends = dependencies opt + } + } + +createExecutable :: SharedOptions -> Executable +createExecutable opt = Executable name mainIs buildInfo where + name :: String + name = "Test" ++ lang opt + + mainIs :: FilePath + mainIs = tFile opt + + buildInfo :: BuildInfo + buildInfo = mempty + { targetBuildDepends = dependencies opt + , otherModules = exposedLibMods opt + } --- |returns a list of all exposed modules -exposedMods :: SharedOptions -> [ModuleName] -exposedMods opt = map fromString $ +-- |returns a list of all modules the library exposes +exposedLibMods :: SharedOptions -> [ModuleName] +exposedLibMods opt = map fromString $ [absFileM opt ,errFileM opt ,printerFileM opt diff --git a/testing/src/HaskellCabalTests.hs b/testing/src/HaskellCabalTests.hs index 6dd06cc43..d4da7fa6d 100644 --- a/testing/src/HaskellCabalTests.hs +++ b/testing/src/HaskellCabalTests.hs @@ -30,12 +30,13 @@ mkTest target desc bnfcParams = makeShellyTest description $ withTmpDir $ \tmp -> do cd tmp writefile "Test.cf" $ unlines - [ "Start. S ::= S \"a\" ;" + [ "Start. S ::= S \"parseMe\" ;" , "End. S ::= ;" ] run_ "bnfc" args assertFileExists "Test.cabal" cmd "cabal" "configure" cmd "cabal" "build" + cmd "echo" "parseMe" -|- cmd "cabal" "run" where args :: [Text] args = target:"--cabal":bnfcParams ++ ["Test.cf"] From 1f159da689b3053dd4f3f5e42c12bd47591abe06 Mon Sep 17 00:00:00 2001 From: Pascal Hof Date: Mon, 7 Mar 2016 14:23:46 +0100 Subject: [PATCH 07/12] create cabal files --- source/BNFC.cabal | 6 +- source/src/BNFC/Backend/Haskell.hs | 9 ++- source/src/BNFC/Backend/Haskell/CFtoCabal.hs | 76 ++++++++++++++++++++ source/src/BNFC/Backend/Haskell/HsOpts.hs | 2 +- source/src/BNFC/Backend/HaskellGADT.hs | 2 + source/src/BNFC/Options.hs | 56 ++++++++------- source/test/BNFC/Backend/HaskellSpec.hs | 6 ++ testing/Main.hs | 2 + testing/src/HaskellCabalTests.hs | 44 ++++++++++++ 9 files changed, 171 insertions(+), 32 deletions(-) create mode 100644 source/src/BNFC/Backend/Haskell/CFtoCabal.hs create mode 100644 testing/src/HaskellCabalTests.hs diff --git a/source/BNFC.cabal b/source/BNFC.cabal index 8f4e20138..090c6e4ea 100644 --- a/source/BNFC.cabal +++ b/source/BNFC.cabal @@ -55,7 +55,8 @@ Executable bnfc containers, pretty >=1.1 && <1.2, filepath, - deepseq + deepseq, + Cabal == 1.22.* build-tools: alex, happy Main-is: Main.hs HS-source-dirs: src/ @@ -101,6 +102,7 @@ Executable bnfc BNFC.Backend.Haskell, BNFC.Backend.Haskell.ToCNF, BNFC.Backend.Haskell.RegToAlex, + BNFC.Backend.Haskell.CFtoCabal, BNFC.Backend.Haskell.CFtoTemplate, BNFC.Backend.Haskell.CFtoAlex3, BNFC.Backend.Haskell.CFtoAlex2, @@ -198,7 +200,7 @@ Test-suite unit-tests Type: exitcode-stdio-1.0 Build-Depends: base>=4 && <5, mtl, directory, array, process, filepath, pretty, hspec, QuickCheck >= 2.5, HUnit, - temporary, containers, deepseq + temporary, containers, deepseq, Cabal == 1.22.* Main-is: unit-tests.hs HS-source-dirs: src test extensions: diff --git a/source/src/BNFC/Backend/Haskell.hs b/source/src/BNFC/Backend/Haskell.hs index 6c7fb7f36..18a1ddc90 100644 --- a/source/src/BNFC/Backend/Haskell.hs +++ b/source/src/BNFC/Backend/Haskell.hs @@ -34,6 +34,7 @@ import BNFC.Backend.Haskell.CFtoAbstract import BNFC.Backend.Haskell.CFtoTemplate import BNFC.Backend.Haskell.CFtoPrinter import BNFC.Backend.Haskell.CFtoLayout +import BNFC.Backend.Haskell.CFtoCabal import BNFC.Backend.XML import BNFC.Backend.Haskell.HsOpts import BNFC.Backend.Haskell.ToCNF as ToCNF @@ -81,6 +82,7 @@ makeHaskell opts cf = do mkfile (txtFile opts) $ cfToTxt (lang opts) cf mkfile (templateFile opts) $ cf2Template (templateFileM opts) absMod errMod (functor opts) cf mkfile (printerFile opts) $ cf2Printer (byteStrings opts) (functor opts) False prMod absMod cf + mkfile (cabalFile opts) $ cf2Cabal opts when (hasLayout cf) $ mkfile (layoutFile opts) $ cf2Layout (alex1 opts) (inDir opts) layMod lexMod cf mkfile (errFile opts) $ mkErrM errMod (ghcExtensions opts) when (shareStrings opts) $ mkfile (shareFile opts) $ sharedString shareMod (byteStrings opts) cf @@ -106,9 +108,10 @@ makefile opts = makeA where [ if cnf opts then "ghc --make TestCNF.hs" else "ghc --make " ++ tFile opts ++ " -o " ++ mkFile withLang "Test" "" opts]) - , Makefile.mkRule "clean" [] + , Makefile.mkRule "clean" [] $ [ "-rm -f " ++ unwords - (map (dir++) [ "*.log", "*.aux", "*.hi", "*.o", "*.dvi" ]) ] + (map (dir++) [ "*.log", "*.aux", "*.hi", "*.o", "*.dvi" ]) ]++ + [ "cabal clean" | cabal opts ] , Makefile.mkRule "distclean" ["clean"] [ "-rm -f " ++ unwords [ mkFile withLang "Doc" "*" opts @@ -120,6 +123,7 @@ makefile opts = makeA where , mkFile withLang "Test" "*" opts , mkFile withLang "Abs" "*" opts , mkFile withLang "Test" "" opts + , mkFile withLang "" "cabal*" opts , mkFile noLang "ErrM" "*" opts , mkFile noLang "SharedString" "*" opts , mkFile noLang "ComposOp" "*" opts @@ -278,4 +282,3 @@ liftParser , " dec_fn f = decode (find f) r" , " in GLR_Result (\\ff -> dec_fn $ ff f) (dec_fn f)" ] - diff --git a/source/src/BNFC/Backend/Haskell/CFtoCabal.hs b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs new file mode 100644 index 000000000..3d0772717 --- /dev/null +++ b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs @@ -0,0 +1,76 @@ +{- + BNF Converter: Abstract syntax Generator + Copyright (C) 2016 Author: Pascal Hof + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-} + +module BNFC.Backend.Haskell.CFtoCabal (cf2Cabal) where + +import Distribution.Simple hiding (Language) +import Distribution.ModuleName(ModuleName,fromString) +import Distribution.PackageDescription +import Distribution.PackageDescription.Parse(showPackageDescription) + +import BNFC.Backend.Haskell.HsOpts +import BNFC.Options hiding (Version) + +-- to produce a Cabal file +cf2Cabal :: SharedOptions -> String +cf2Cabal = showPackageDescription . buildPackageDescription + +buildPackageDescription :: SharedOptions -> PackageDescription +buildPackageDescription opt = emptyPackageDescription + { package = + PackageIdentifier + { pkgName = PackageName (lang opt) + , pkgVersion = Version [0,1] []} + , library = + Just Library + { exposedModules = exposedMods opt + , reexportedModules = [] + , requiredSignatures = [] + , exposedSignatures = [] + , libExposed = True + , libBuildInfo = emptyBuildInfo + { buildable = True + , hsSourceDirs = ["."] + , targetBuildDepends = dependencies opt + } + } + , extraSrcFiles = [ happyFile opt, alexFile opt ] + , buildType = Just Simple + , license = AllRightsReserved + } + +dependencies :: SharedOptions -> [Dependency] +dependencies opt = + [ Dependency (PackageName "base") (laterVersion $ Version [4] []) + , Dependency (PackageName "array") anyVersion + ] ++ + [ Dependency (PackageName "mtl") anyVersion | TargetHaskellGadt == target opt ] + + +-- |returns a list of all exposed modules +exposedMods :: SharedOptions -> [ModuleName] +exposedMods opt = map fromString $ + [absFileM opt + ,errFileM opt + ,printerFileM opt + ,alexFileM opt + ,happyFileM opt + ] ++ + [xmlFileM opt | xml opt > 0] ++ + [composOpFileM opt | TargetHaskellGadt == target opt ] diff --git a/source/src/BNFC/Backend/Haskell/HsOpts.hs b/source/src/BNFC/Backend/Haskell/HsOpts.hs index a37757b9f..d2727ca3b 100644 --- a/source/src/BNFC/Backend/Haskell/HsOpts.hs +++ b/source/src/BNFC/Backend/Haskell/HsOpts.hs @@ -45,7 +45,7 @@ xmlFile = mkFile withLang "XML" "hs" xmlFileM = mkMod withLang "XML" composOpFile = mkFile noLang "ComposOp" "hs" composOpFileM = mkMod noLang "ComposOp" - +cabalFile opt = lang opt ++ ".cabal" noLang :: Options -> String -> String noLang _ name = name diff --git a/source/src/BNFC/Backend/HaskellGADT.hs b/source/src/BNFC/Backend/HaskellGADT.hs index b0dc6c82d..dc2de2eb4 100644 --- a/source/src/BNFC/Backend/HaskellGADT.hs +++ b/source/src/BNFC/Backend/HaskellGADT.hs @@ -34,6 +34,7 @@ import BNFC.Backend.HaskellGADT.CFtoAbstractGADT import BNFC.Backend.HaskellGADT.CFtoTemplateGADT import BNFC.Backend.Haskell.CFtoPrinter import BNFC.Backend.Haskell.CFtoLayout +import BNFC.Backend.Haskell.CFtoCabal import BNFC.Backend.XML import BNFC.Backend.Haskell.MkErrM import BNFC.Backend.Haskell.MkSharedString @@ -71,6 +72,7 @@ makeHaskellGadt opts cf = do liftIO $ putStrLn " (Tested with Happy 1.15)" mkfile (templateFile opts) $ cf2Template (templateFileM opts) absMod errMod cf mkfile (printerFile opts) $ cf2Printer False False True prMod absMod cf + mkfile (cabalFile opts) $ cf2Cabal opts when (hasLayout cf) $ mkfile (layoutFile opts) $ cf2Layout (alexMode opts == Alex1) (inDir opts) layMod lexMod cf mkfile (tFile opts) $ Haskell.testfile opts cf mkfile (errFile opts) $ mkErrM errMod (ghcExtensions opts) diff --git a/source/src/BNFC/Options.hs b/source/src/BNFC/Options.hs index 636f27057..98a695b00 100644 --- a/source/src/BNFC/Options.hs +++ b/source/src/BNFC/Options.hs @@ -76,6 +76,7 @@ data SharedOptions = Options , glr :: HappyMode , xml :: Int , ghcExtensions :: Bool + , cabal :: Bool -- C++ specific , linenumbers :: Bool -- ^ Add and set line_number field for syntax classes -- C# specific @@ -103,6 +104,7 @@ defaultOptions = Options , glr = Standard , xml = 0 , ghcExtensions = False + , cabal = False , lang = error "lang not set" , linenumbers = False , visualStudio = False @@ -122,7 +124,7 @@ globalOptions = [ -- | Options for the target languages -- targetOptions :: [ OptDescr Target ] targetOptions :: [ OptDescr (SharedOptions -> SharedOptions)] -targetOptions = +targetOptions = [ Option "" ["java"] (NoArg (\o -> o {target = TargetJava})) "Output Java code [default: for use with JLex and CUP]" , Option "" ["haskell"] (NoArg (\o -> o {target = TargetHaskell})) @@ -206,6 +208,9 @@ specificOptions = , ( Option [] ["ghc"] (NoArg (\o -> o {ghcExtensions = True})) "Use ghc-specific language extensions" , [TargetHaskell, TargetHaskellGadt, TargetProfile] ) + , ( Option [] ["cabal"] (NoArg (\o -> o {cabal = True})) + "Also generate cabal file" + , [TargetHaskell,TargetHaskellGadt] ) , ( Option [] ["functor"] (NoArg (\o -> o {functor = True})) "Make the AST a functor and use it to store the position of the nodes" , [TargetHaskell] ) @@ -277,28 +282,27 @@ isUsageError _ = False -- A translating function to maintain backward compatiblicy -- with the old option syntay translateOldOptions :: [String] -> [String] -translateOldOptions = map translateOne - where translateOne "-java" = "--java" - translateOne "-java1.5" = "--java" - translateOne "-c" = "--c" - translateOne "-cpp" = "--cpp" - translateOne "-cpp_stl" = "--cpp" - translateOne "-cpp_no_stl" = "--cpp-nostl" - translateOne "-csharp" = "--csharp" - translateOne "-ocaml" = "--ocaml" - translateOne "-fsharp" = "fsharp" - translateOne "-haskell" = "--haskell" - translateOne "-prof" = "--profile" - translateOne "-gadt" = "--haskell-gadt" - translateOne "-alex1" = "--alex1" - translateOne "-alex2" = "--alex2" - translateOne "-alex3" = "--alex3" - translateOne "-sharestrings" = "--sharestring" - translateOne "-bytestrings" = "--bytestring" - translateOne "-glr" = "--glr" - translateOne "-xml" = "--xml" - translateOne "-xmlt" = "--xmlt" - translateOne "-vs" = "--vs" - translateOne "-wcf" = "--wcf" - translateOne other = other - +translateOldOptions = concatMap translateOne + where translateOne "-java" = return "--java" + translateOne "-java1.5" = return "--java" + translateOne "-c" = return "--c" + translateOne "-cpp" = return "--cpp" + translateOne "-cpp_stl" = return "--cpp" + translateOne "-cpp_no_stl" = return "--cpp-nostl" + translateOne "-csharp" = return "--csharp" + translateOne "-ocaml" = return "--ocaml" + translateOne "-fsharp" = return "fsharp" + translateOne "-haskell" = return "--haskell" + translateOne "-prof" = return "--profile" + translateOne "-gadt" = return "--haskell-gadt" + translateOne "-alex1" = return "--alex1" + translateOne "-alex2" = return "--alex2" + translateOne "-alex3" = return "--alex3" + translateOne "-sharestrings" = return "--sharestring" + translateOne "-bytestrings" = return "--bytestring" + translateOne "-glr" = return "--glr" + translateOne "-xml" = return "--xml" + translateOne "-xmlt" = return "--xmlt" + translateOne "-vs" = return "--vs" + translateOne "-wcf" = return "--wcf" + translateOne other = return other diff --git a/source/test/BNFC/Backend/HaskellSpec.hs b/source/test/BNFC/Backend/HaskellSpec.hs index 28cf78db4..3340d4e85 100644 --- a/source/test/BNFC/Backend/HaskellSpec.hs +++ b/source/test/BNFC/Backend/HaskellSpec.hs @@ -56,3 +56,9 @@ spec = do calc <- getCalc let options = calcOptions { make = Just "MyMakefile" } makeHaskell options calc `shouldGenerate` "MyMakefile" + + context "with option --cabal and the Calc grammar" $ do + it "generates a cabal file" $ do + calc <- getCalc + let options = calcOptions { cabal = True } + makeHaskell options calc `shouldGenerate` "Calc.cabal" diff --git a/testing/Main.hs b/testing/Main.hs index 98b68f930..df3dc1610 100644 --- a/testing/Main.hs +++ b/testing/Main.hs @@ -2,6 +2,7 @@ module Main (main) where import Test.Framework (htfMain) +import HaskellCabalTests import HaskellCnfTests import ParameterizedTests import PygmentsTests @@ -14,4 +15,5 @@ main = htfMain , PygmentsTests.all , HaskellCnfTests.all , OutputParser.tests + , HaskellCabalTests.all ] diff --git a/testing/src/HaskellCabalTests.hs b/testing/src/HaskellCabalTests.hs new file mode 100644 index 000000000..6dd06cc43 --- /dev/null +++ b/testing/src/HaskellCabalTests.hs @@ -0,0 +1,44 @@ +module HaskellCabalTests (all) where + +import Shelly +import Prelude hiding (all,unlines) +import Data.Text(Text,unlines,unpack) +import TestUtils(Test,makeShellyTest,makeTestSuite,assertFileExists) + +all = makeTestSuite "Haskell/Cabal" + [ mkTest target desc ps + | (desc,ps) <- params + , target <- ["--haskell","--haskell-gadt"] + ] + +-- |a list of test description and the respective arguments to bnfc +params :: [(String,[Text])] +params = + [("Cabal only",[]) + ,("Ghc",["--ghc"]) + ,("Functor",["--functor"]) + ,("Xml",["--xml"]) + ,("Xmlt",["--xmlt"]) + ,("Qualified",["-d"]) + ,("Namespace",["-p","Foobar"]) + ,("Qualified namespace",["-p","Foobar","-d"]) + ] + +-- |building the Shelly Test +mkTest :: Text -> String -> [Text] -> Test +mkTest target desc bnfcParams = + makeShellyTest description $ withTmpDir $ \tmp -> do + cd tmp + writefile "Test.cf" $ unlines + [ "Start. S ::= S \"a\" ;" + , "End. S ::= ;" ] + run_ "bnfc" args + assertFileExists "Test.cabal" + cmd "cabal" "configure" + cmd "cabal" "build" + where + args :: [Text] + args = target:"--cabal":bnfcParams ++ ["Test.cf"] + + description :: String + description = desc++",Target "++drop 2 (unpack target) From 8ca1dcdab8cf1f9ee5b4c9567d30e95ec0a19b31 Mon Sep 17 00:00:00 2001 From: Pascal Hof Date: Mon, 7 Mar 2016 14:42:52 +0100 Subject: [PATCH 08/12] widened cabal dependencies --- source/BNFC.cabal | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/BNFC.cabal b/source/BNFC.cabal index 090c6e4ea..18c649177 100644 --- a/source/BNFC.cabal +++ b/source/BNFC.cabal @@ -56,7 +56,7 @@ Executable bnfc pretty >=1.1 && <1.2, filepath, deepseq, - Cabal == 1.22.* + Cabal >= 1.18 && < 1.23 build-tools: alex, happy Main-is: Main.hs HS-source-dirs: src/ @@ -200,7 +200,7 @@ Test-suite unit-tests Type: exitcode-stdio-1.0 Build-Depends: base>=4 && <5, mtl, directory, array, process, filepath, pretty, hspec, QuickCheck >= 2.5, HUnit, - temporary, containers, deepseq, Cabal == 1.22.* + temporary, containers, deepseq, Cabal >= 1.18 && < 1.23 Main-is: unit-tests.hs HS-source-dirs: src test extensions: From 2aef69db79319f44e0a30b5c08cf8e885ba29b64 Mon Sep 17 00:00:00 2001 From: Pascal Hof Date: Mon, 7 Mar 2016 14:50:11 +0100 Subject: [PATCH 09/12] even cabal 1.16 should work --- source/BNFC.cabal | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/BNFC.cabal b/source/BNFC.cabal index 18c649177..f6f1a5813 100644 --- a/source/BNFC.cabal +++ b/source/BNFC.cabal @@ -56,7 +56,13 @@ Executable bnfc pretty >=1.1 && <1.2, filepath, deepseq, +<<<<<<< 8ca1dcdab8cf1f9ee5b4c9567d30e95ec0a19b31 Cabal >= 1.18 && < 1.23 +======= + Cabal >= 1.16 && < 1.23 + if impl(ghc < 7.6.1) + Build-depends: ghc-prim +>>>>>>> even cabal 1.16 should work build-tools: alex, happy Main-is: Main.hs HS-source-dirs: src/ @@ -200,7 +206,7 @@ Test-suite unit-tests Type: exitcode-stdio-1.0 Build-Depends: base>=4 && <5, mtl, directory, array, process, filepath, pretty, hspec, QuickCheck >= 2.5, HUnit, - temporary, containers, deepseq, Cabal >= 1.18 && < 1.23 + temporary, containers, deepseq, Cabal >= 1.16 && < 1.23 Main-is: unit-tests.hs HS-source-dirs: src test extensions: From eac127ad22c436213065aafe784de68a18d4c9bd Mon Sep 17 00:00:00 2001 From: Pascal Hof Date: Mon, 7 Mar 2016 14:59:18 +0100 Subject: [PATCH 10/12] using mempty as default value for a cabal library --- source/src/BNFC/Backend/Haskell/CFtoCabal.hs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/source/src/BNFC/Backend/Haskell/CFtoCabal.hs b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs index 3d0772717..d28c71e3e 100644 --- a/source/src/BNFC/Backend/Haskell/CFtoCabal.hs +++ b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs @@ -38,11 +38,8 @@ buildPackageDescription opt = emptyPackageDescription { pkgName = PackageName (lang opt) , pkgVersion = Version [0,1] []} , library = - Just Library + Just mempty { exposedModules = exposedMods opt - , reexportedModules = [] - , requiredSignatures = [] - , exposedSignatures = [] , libExposed = True , libBuildInfo = emptyBuildInfo { buildable = True From cdc421aee4d3d6db20c3eb9cf76347658ba59b07 Mon Sep 17 00:00:00 2001 From: Pascal Hof Date: Mon, 7 Mar 2016 15:25:26 +0100 Subject: [PATCH 11/12] import mempty --- source/src/BNFC/Backend/Haskell/CFtoCabal.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/source/src/BNFC/Backend/Haskell/CFtoCabal.hs b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs index d28c71e3e..bb5b901e7 100644 --- a/source/src/BNFC/Backend/Haskell/CFtoCabal.hs +++ b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs @@ -26,6 +26,7 @@ import Distribution.PackageDescription.Parse(showPackageDescription) import BNFC.Backend.Haskell.HsOpts import BNFC.Options hiding (Version) +import Data.Monoid(mempty) -- to produce a Cabal file cf2Cabal :: SharedOptions -> String From e8c958d3ea0e80028b00f061a201536e6f052826 Mon Sep 17 00:00:00 2001 From: Pascal Hof Date: Sat, 19 Nov 2016 11:35:07 +0100 Subject: [PATCH 12/12] created cabal file offers building the test program (executable) --- source/src/BNFC/Backend/Haskell/CFtoCabal.hs | 45 ++++++++++++++------ testing/src/HaskellCabalTests.hs | 3 +- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/source/src/BNFC/Backend/Haskell/CFtoCabal.hs b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs index bb5b901e7..9b64894f9 100644 --- a/source/src/BNFC/Backend/Haskell/CFtoCabal.hs +++ b/source/src/BNFC/Backend/Haskell/CFtoCabal.hs @@ -38,32 +38,49 @@ buildPackageDescription opt = emptyPackageDescription PackageIdentifier { pkgName = PackageName (lang opt) , pkgVersion = Version [0,1] []} - , library = - Just mempty - { exposedModules = exposedMods opt - , libExposed = True - , libBuildInfo = emptyBuildInfo - { buildable = True - , hsSourceDirs = ["."] - , targetBuildDepends = dependencies opt - } - } + , library = Just (createLibrary opt) + , executables = [createExecutable opt] , extraSrcFiles = [ happyFile opt, alexFile opt ] , buildType = Just Simple , license = AllRightsReserved + , specVersionRaw = Right (orLaterVersion $ Version [1,22] []) } dependencies :: SharedOptions -> [Dependency] dependencies opt = - [ Dependency (PackageName "base") (laterVersion $ Version [4] []) + [ Dependency (PackageName "base") (orLaterVersion $ Version [4] []) , Dependency (PackageName "array") anyVersion ] ++ [ Dependency (PackageName "mtl") anyVersion | TargetHaskellGadt == target opt ] +createLibrary :: SharedOptions -> Library +createLibrary opt = mempty + { exposedModules = exposedLibMods opt + , libExposed = True + , libBuildInfo = emptyBuildInfo + { buildable = True + , hsSourceDirs = ["."] + , targetBuildDepends = dependencies opt + } + } + +createExecutable :: SharedOptions -> Executable +createExecutable opt = Executable name mainIs buildInfo where + name :: String + name = "Test" ++ lang opt + + mainIs :: FilePath + mainIs = tFile opt + + buildInfo :: BuildInfo + buildInfo = mempty + { targetBuildDepends = dependencies opt + , otherModules = exposedLibMods opt + } --- |returns a list of all exposed modules -exposedMods :: SharedOptions -> [ModuleName] -exposedMods opt = map fromString $ +-- |returns a list of all modules the library exposes +exposedLibMods :: SharedOptions -> [ModuleName] +exposedLibMods opt = map fromString $ [absFileM opt ,errFileM opt ,printerFileM opt diff --git a/testing/src/HaskellCabalTests.hs b/testing/src/HaskellCabalTests.hs index 6dd06cc43..d4da7fa6d 100644 --- a/testing/src/HaskellCabalTests.hs +++ b/testing/src/HaskellCabalTests.hs @@ -30,12 +30,13 @@ mkTest target desc bnfcParams = makeShellyTest description $ withTmpDir $ \tmp -> do cd tmp writefile "Test.cf" $ unlines - [ "Start. S ::= S \"a\" ;" + [ "Start. S ::= S \"parseMe\" ;" , "End. S ::= ;" ] run_ "bnfc" args assertFileExists "Test.cabal" cmd "cabal" "configure" cmd "cabal" "build" + cmd "echo" "parseMe" -|- cmd "cabal" "run" where args :: [Text] args = target:"--cabal":bnfcParams ++ ["Test.cf"]