Skip to content

Supporting BNFC #6726

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ivanperez-keera opened this issue Apr 21, 2020 · 7 comments
Open

Supporting BNFC #6726

ivanperez-keera opened this issue Apr 21, 2020 · 7 comments
Labels
Cabal: other re: build-tool Concerning `build-tools` and `build-tool-depends` re: preprocessors Concerning preprocessors such as alex and happy type: enhancement

Comments

@ivanperez-keera
Copy link
Contributor

ivanperez-keera commented Apr 21, 2020

I'd like to propose that Cabal support BNFC as a build tool. BNFC is a well-known, multi-language parser generator that supports Haskell via Happy & Alex.

Additional context
From what I understand, the required changes would be:

  • Adding bnfc to this list here:
    -- The first cases matches first.
    desugarBuildTool :: PackageDescription
    -> LegacyExeDependency
    -> Maybe ExeDependency
    desugarBuildTool pkg led =
    if foundLocal
    then Just $ ExeDependency (packageName pkg) toolName reqVer
    else Map.lookup name whiteMap
    where
    LegacyExeDependency name reqVer = led
    toolName = mkUnqualComponentName name
    foundLocal = toolName `elem` map exeName (executables pkg)
    whitelist = [ "hscolour", "haddock", "happy", "alex", "hsc2hs", "c2hs"
    , "cpphs", "greencard", "hspec-discover"
    ]
  • Adding "fc" to "bnfc" here:
    -- Unfortunately we cannot use the version exported by Distribution.Simple.Program
    knownSuffixHandlers :: [(String,String)]
    knownSuffixHandlers =
    [ ("gc", "greencard")
    , ("chs", "chs")
    , ("hsc", "hsc2hs")
    , ("x", "alex")
    , ("y", "happy")
    , ("ly", "happy")
    , ("cpphs", "cpp")
    ]
  • Adding bnfcProgram to this export list:
    module Distribution.Simple.Program.Builtin (
    and this list:
    builtinPrograms :: [Program]
    builtinPrograms =
    , and introducing a bnfcProgram definition in that module. For bnfc, it appears that just --version is enough to detect the version number.

Questions:

  • Would such a patch be accepted?
  • If so, would those changes be enough?
  • How to handle the need to arguments to bnfc (e.g., --haskell -p <PATH> -o <directory> <file.cf>? Would doing this immediately make cabal understand --with-bnfc, --with-bnfc-options and bnfc-options:?
@phadej
Copy link
Collaborator

phadej commented Apr 21, 2020

  • I'm ok about adding bnfc to known suffix preprocessors, but
  • I think we have strong assumption that packagename and exename is the same, which isn't: bnfc and BNFC which might require some bigger changes.
  • desugarBuildTool is for legacy build-tools, and I think shouldn't be changed
  • I suspect things need changes if there is no one-to-one mapping between source MyLanguage.fc and generated MyLanguage.hs. I guess bnfc generates some .x and .y (and .hs) files. I suspect the multiple output file would case architectural problems.

Adding bnfc-options: to .cabal file syntax is a big deal, so everything else have to be figured out until we can commit to that change, we'll need to live with if forever. Note, we don't have alex-options nor happy-options as these tools self-configure from the input file. I'd appreciate that kind of working mode.

@ivanperez-keera
Copy link
Contributor Author

I suspect things need changes if there is no one-to-one mapping between source MyLanguage.cf and generated MyLanguage.hs. I guess bnfc generates some .x and .y (and .hs) files. I suspect the multiple output file would case architectural problems.

This assumption is correct. From one .cf file, BNFC generates:

  • A .x alex file
  • A .y happy file.
  • Several .hs files (containing e.g., the AST).

Adding bnfc-options: to .cabal file syntax is a big deal, so everything else have to be figured out until we can commit to that change, we'll need to live with if forever.

Makes sense not to add it then.

I think we have strong assumption that packagename and exename is the same [...] which might require some bigger changes.
[...] I suspect the multiple output file would case architectural problems.

I certainly would not expect all of these changes to happen in Cabal just for this. Is this versatility (i.e., more than one file being generated, having different package and executable names) generally desired for the future of cabal, or would this just be annoying to maintain and not provide much benefit? I see their benefit in theory, but I'm just not sure if you've every encountered this before, or expect to.

@phadej
Copy link
Collaborator

phadej commented Apr 22, 2020

  • having different package and executable names

I don't think this is big issue, it's just not done. built-tool-depends already requires to specify BNFC:bnfc (optional version range) format. But the knownSuffixHandlers is [(String, String)], where it should be [(PackageName, UnqualComponentName, Extension)]. I think it will be a good change anyway (less stringy types, even Extension is String in filepath).

  • more than one file being generated

Is the tricky bit build-system wise. Cabal have to know what files are generated. I suspect one-to-one processing is very deep in how Cabal is made. There are e.g. issues with ordering of c2hs flle processing which Cabal doesn't known anything about (see #6233 for more).

@andreasabel
Copy link
Member

* more than one file being generated

Is the tricky bit build-system wise. Cabal have to know what files are generated. I suspect one-to-one processing is very deep in how Cabal is made. There are e.g. issues with ordering of c2hs flle processing which Cabal doesn't known anything about (see #6233 for more).

Found this comment on situations where several files are generated:
#3545 (comment)

@ivanperez-keera
Copy link
Contributor Author

Just a comment which I don't know if/how it is related.

Currently, with cabal-3.4, adding BNFC to the setup build dependencies does not seem to be enough (or I don't know how to do it):

custom-setup                                                                    
  setup-depends:                                                                
      base    >= 4.11.0.0                                                       
    , Cabal   >= 2.0                                                            
    , process                                                                   
    , BNFC    >= 2.9.1   

Instead of installing BNFC as an executable, therefore letting me run it, it installs BNFC as a library. The result is that the following setup program:

-- | Custom Setup that runs bnfc to generate the language sub-libraries         
-- for the parsers included in Ogma.                                            
module Main (main) where                                                        
                                                                                
import Distribution.Simple         ( defaultMainWithHooks, hookedPrograms,      
                                     postConf, preBuild, simpleUserHooks )      
import Distribution.Simple.Program ( Program (..), findProgramVersion,          
                                     simpleProgram )                            
import System.Process              ( system )                                   
                                                                                
-- | Run BNFC on the grammar before the actual build step.                      
--                                                                              
-- All options for bnfc are hard-coded here. There is an open bug in Cabal's    
-- github repo about supporting BNFC.                                           
main :: IO ()                                                                   
main = defaultMainWithHooks $ simpleUserHooks                                   
  { hookedPrograms = [ bnfcProgram ]                                            
  , postConf       = \args flags packageDesc localBuildInfo -> do               
      _ <- system "bnfc --haskell -p Language.W -o src/ grammar/W.cf"           
      postConf simpleUserHooks args flags packageDesc localBuildInfo            
  }                                                                             
                                                                                
-- | TODO: This should be in Cabal.Distribution.Simple.Program.Builtin.         
bnfcProgram :: Program                                                          
bnfcProgram = (simpleProgram "bnfc")                                            
  { programFindVersion = findProgramVersion "--version" id                      
  }

cannot find bnfc in the PATH:

Warning: 'hs-source-dirs: src' directory does not exist.
/bin/sh: 1: bnfc: not found
Preprocessing library for xyz-language-w-0.0.1..
setup: can't find source for Language/W/AbsW in src, dist/build/autogen,
dist/build/global-autogen

although the directory src does exist in the repo. Btw, if I first install BNFC first with:

cabal install bnfc

then it puts the executable in $HOME/.cabal/bin and my package compiles and installs correctly.

@gbaz
Copy link
Collaborator

gbaz commented Sep 14, 2021

Correct, as discussed in the ticket you linked, build-tool-depends is the correct thing to specify.

@ivanperez-keera
Copy link
Contributor Author

Indeed. Unfortunately, that did not work for me on 3.6 because of #7644.

@fgaz fgaz added the re: preprocessors Concerning preprocessors such as alex and happy label Jan 14, 2022
@ulysses4ever ulysses4ever added the re: build-tool Concerning `build-tools` and `build-tool-depends` label Jun 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Cabal: other re: build-tool Concerning `build-tools` and `build-tool-depends` re: preprocessors Concerning preprocessors such as alex and happy type: enhancement
Projects
None yet
Development

No branches or pull requests

7 participants