BNFC-2.5.0: src/Main.hs
{-
BNF Converter: Main file
Copyright (C) 2002-2013 Authors:
Jonas Almström Duregård, Krasimir Angelov, Jean-Philippe Bernardy, Björn Bringert, Johan Broberg, Paul Callaghan,
Grégoire Détrez, Markus Forsberg, Ola Frid, Peter Gammie, Thomas Hallgren, Patrik Jansson,
Kristofer Johannisson, Antti-Juhani Kaijanaho, Ulf Norell,
Michael Pellauer and Aarne Ranta 2002 - 2013.
Björn Bringert, Johan Broberg, Markus Forberg, Peter Gammie,
Patrik Jansson, Antti-Juhani Kaijanaho, Ulf Norell,
Michael Pellauer, Aarne Ranta
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 Main where
-- import Utils
import CF (cfp2cf)
import HaskellTop
import HaskellTopGADT
import ProfileTop
import JavaTop
import JavaTop15
import CPPTop
import CSharpTop
import STLTop
import CTop
import OCamlTop
import FSharpTop
import CFtoXML
import Utils
import Options
import GetCF
import MultiView (preprocessMCF, mkTestMulti, mkMakefileMulti)
import System.Environment (getEnv,getArgs )
import System.Exit (exitFailure,exitSuccess)
import System.Cmd (system)
import Data.Char
import Data.List (elemIndex, foldl')
import Control.Monad (when,unless)
import Paths_BNFC ( version )
import Data.Version ( showVersion )
title = unlines [
"The BNF Converter, "++showVersion version,
"(c) Jonas Almström Duregård, Krasimir Angelov, Jean-Philippe Bernardy, Björn Bringert, Johan Broberg, Paul Callaghan, ",
" Grégoire Détrez, Markus Forsberg, Ola Frid, Peter Gammie, Thomas Hallgren, Patrik Jansson, ",
" Kristofer Johannisson, Antti-Juhani Kaijanaho, Ulf Norell, ",
" Michael Pellauer and Aarne Ranta 2002 - 2013.",
"Free software under GNU General Public License (GPL).",
"Bug reports to bnfc-dev@googlegroups.com."
]
main :: IO ()
main = do
xx <- getArgs
case xx of
["--numeric-version"] -> do
putStrLn (showVersion version)
exitSuccess
[] -> printUsage
_ | elem "-multi" xx -> do
putStrLn "preprocessing multilingual BNF"
let file = last xx
(files,entryp) <- preprocessMCF file
mapM_ mkOne [init xx ++ [f] | f <- files]
mkTestMulti entryp xx file files
mkMakefileMulti xx file files
_ -> mkOne xx
mkOne :: [String] -> IO ()
mkOne xx = do
let args = (map (filter (not . isSpace)) xx)
let file = last args
if (head file == '-') then printUsage
else do
let name = takeWhile (/= '.') $ basename file
let make = elem "-m" args
let multi = elem "-multi" args
let c = elem "-c" args
let cpp_no_stl = elem "-cpp_no_stl" args
let cpp_stl = elem "-cpp_stl" args || elem "-cpp" args
let csharp = elem "-csharp" args
let java14 = elem "-java1.4" args
let java15 = elem "-java1.5" args || elem "-java" args
let ocaml = elem "-ocaml" args
let fsharp = elem "-fsharp" args
let haskell = elem "-haskell" args
let haskellGADT = elem "-gadt" args
let profile = elem "-prof" args
let alexMode = foldl' (\m arg ->
case arg of
"-alex1" -> Alex1
"-alex2" -> Alex2
"-alex3" -> Alex3
_ -> m
) Alex3 args
alex1 = alexMode == Alex1
alex2StringSharing = elem "-sharestrings" args
alex2ByteString = elem "-bytestrings" args
glr = "-glr" `elem` args
let xml = if elem "-xml" args then 1 else
if elem "-xmlt" args then 2 else 0
let inDir = elem "-d" args
let vsfiles = elem "-vs" args
let wcfSupport = elem "-wcf" args
let linenumbers = elem "-l" args -- for C++ STL target
inPackage <- case elemIndex "-p" args of
Nothing -> return Nothing
Just i | i < length args - 1 -> return (Just (args!!(i+1)))
_ -> do
putStrLn "-p option requires an argument"
printUsage
let options = Options {make = make,
alexMode = alexMode,
inDir = inDir,
shareStrings = alex2StringSharing,
byteStrings = alex2ByteString,
glr = if glr then GLR else Standard,
xml = xml,
inPackage = inPackage,
lang = name,
multi = multi,
cnf = elem "-cnf" args,
targets = targets
}
targets0 = [ TargetC |c] ++ [ TargetCPP | cpp_no_stl ] ++ [TargetCPP_STL | cpp_stl
] ++ [ TargetCSharp | csharp] ++ [ TargetFSharp |fsharp] ++ [TargetHaskellGADT|haskellGADT
] ++ [ TargetJava15 |java15] ++ [TargetJava |java14] ++ [TargetOCAML |ocaml] ++ [TargetProfile|profile]
targets = if null targets0 then [TargetHaskell] else targets0
putStrLn title
unless (length targets == 1) $
fail "Error: only one language mode may be chosen"
unless (isCF (reverse file)) $
fail "Error: the input file must end with .cf"
(cfp, isOk) <- tryReadCFP options file
let cf = cfp2cf cfp
unless isOk $
fail "Error: Failed"
case () of
_ | c -> makeC make name cf
_ | cpp_no_stl -> makeCPP make name cf
_ | cpp_stl-> makeSTL make linenumbers inPackage name cf
_ | csharp -> makeCSharp make vsfiles wcfSupport inPackage cf file
_ | java14 -> makeJava make name cf
_ | java15 -> makeJava15 make inPackage name cf
_ | ocaml -> makeOCaml options cf
_ | fsharp -> makeFSharp options cf
_ | profile-> makeAllProfile make alex1 False xml name cfp
_ | haskellGADT -> makeAllGADT options cf
_ -> makeAll options cf
when (make && multi) $ do
system ("cp Makefile Makefile_" ++ name)
return ()
putStrLn "Done!"
where isCF ('f':'c':'.':_) = True
isCF ('f':'n':'b':'.':_) = True
isCF ('f':'n':'b':'l':'.':_) = True
isCF ('c':'f':'n':'b':'.':_) = True
isCF _ = False
printUsage = do
putStrLn title
putStrLn "Usage: bnfc <makeoption>* <language>? <special>* file.cf"
putStrLn ""
putStrLn "Version options:"
putStrLn " --numeric-version Print just the version number"
putStrLn ""
putStrLn "Make option:"
putStrLn " -m generate Makefile"
putStrLn ""
putStrLn "Languages (Only one language mode may be selected.)"
putStrLn " -java Output Java 1.5 code for use with JLex and CUP"
putStrLn " -java1.5 Output Java 1.5 code for use with JLex and CUP (same as -java)"
putStrLn " -java1.4 Output Java 1.4 code for use with JLex and CUP (before 2.5 was: -java)"
putStrLn " -c Output C code for use with FLex and Bison"
putStrLn " -cpp Output C++ code for use with FLex and Bison (same as -cpp_stl)"
putStrLn " -cpp_stl Output C++ code for use with FLex and Bison (same as -cpp)"
putStrLn " -cpp_no_stl Output C++ code (without STL) for use with FLex and Bison (before 2.5 was: -cpp)"
putStrLn " and the Standard Template Library"
putStrLn " -csharp Output C# code for use with GPLEX and GPPG"
putStrLn " -ocaml Output OCaml code for use with ocamllex and ocamlyacc"
putStrLn " -fsharp Output F# code for use with fslex and fsyacc"
putStrLn " -haskell Output Haskell code for use with Alex and Happy (default)"
putStrLn " -prof Output Haskell code for rules with permutation profiles"
putStrLn " -gadt Output Haskell code which uses GADTs"
putStrLn ""
putStrLn "Special options for the Haskell back-end:"
putStrLn " -d Put Haskell code in modules Lang.* instead of Lang*"
putStrLn " -p <name> Prepend <name> to the Haskell module names."
putStrLn " Dots in the module name create hierarchical modules."
putStrLn " -alex1 Use Alex 1.1 as Haskell lexer tool"
putStrLn " -alex2 Use Alex 2 as Haskell lexer tool"
putStrLn " -alex3 Use Alex 3 as Haskell lexer tool (default)"
putStrLn " -sharestrings Use string sharing in Alex 2 lexer"
putStrLn " -bytestrings Use byte string in Alex 2 lexer"
putStrLn " -glr Output Happy GLR parser"
putStrLn " -xml Also generate a DTD and an XML printer"
putStrLn " -xmlt DTD and an XML printer, another encoding"
putStrLn ""
putStrLn "Special options for the C++ (with STL) back-end:"
putStrLn " -l Add and set line_number field for all syntax classes"
putStrLn " -p <namespace> Use <namespace> as the C++ namespace"
putStrLn ""
putStrLn "Special options for the Java (v 1.5) back-end:"
putStrLn " -p <package> Prepend <package> to the Java package name"
putStrLn ""
putStrLn "Special options for the C# backend:"
putStrLn " -p <namespace> Use <namespace> as the C# namespace"
putStrLn " -vs Generate Visual Studio solution/project files"
putStrLn " -wcf Add support for Windows Communication Foundation, by"
putStrLn " marking abstract syntax classes as DataContracts"
exitFailure