content: module GF.Command.Importing (importGrammar, importSource) where
  
  import PGF
  import PGF.Internal(optimizePGF,unionPGF,msgUnionPGF)
  
  import GF.Compile
  import GF.Compile.Multi (readMulti)
  import GF.Compile.GetGrammar (getBNFCRules, getEBNFRules)
  import GF.Grammar (SourceGrammar) -- for cc command
  import GF.Grammar.BNFC
  import GF.Grammar.EBNF
  import GF.Grammar.CFG
  import GF.Compile.CFGtoPGF
  import GF.Infra.UseIO(die,tryIOE)
  import GF.Infra.Option
  import GF.Data.ErrM
  
  import System.FilePath
  import qualified Data.Set as Set
  
  -- import a grammar in an environment where it extends an existing grammar
  importGrammar :: PGF -> Options -> [FilePath] -> IO PGF
  importGrammar pgf0 _ [] = return pgf0
  importGrammar pgf0 opts files =
    case takeExtensions (last files) of
      ".cf"   -> importCF opts files getBNFCRules bnfc2cf
      ".ebnf" -> importCF opts files getEBNFRules ebnf2cf
      ".gfm"  -> do
        ascss <- mapM readMulti files
        let cs = concatMap snd ascss
        importGrammar pgf0 opts cs
      s | elem s [".gf",".gfo"] -> do
        res <- tryIOE $ compileToPGF opts files
        case res of
          Ok pgf2 -> ioUnionPGF pgf0 pgf2
          Bad msg -> do putStrLn ('\n':'\n':msg)
                        return pgf0
      ".pgf" -> do
        pgf2 <- mapM readPGF files >>= return . foldl1 unionPGF
        ioUnionPGF pgf0 pgf2
      ext -> die $ "Unknown filename extension: " ++ show ext
  
  ioUnionPGF :: PGF -> PGF -> IO PGF
  ioUnionPGF one two = case msgUnionPGF one two of
    (pgf, Just msg) -> putStrLn msg >> return pgf
    (pgf,_)         -> return pgf
  
  importSource :: Options -> [FilePath] -> IO SourceGrammar
  importSource opts files = fmap (snd.snd) (batchCompile opts files)
  
  -- for different cf formats
  importCF opts files get convert = impCF
    where
      impCF = do
        rules <- fmap (convert . concat) $ mapM (get opts) files
        startCat <- case rules of
                      (Rule cat _ _ : _) -> return cat
                      _                  -> fail "empty CFG"
        let pgf = cf2pgf (last files) (mkCFG startCat Set.empty rules)
        probs <- maybe (return . defaultProbabilities) readProbabilitiesFromFile (flag optProbsFile opts) pgf
        return $ setProbabilities probs 
               $ if flag optOptimizePGF opts then optimizePGF pgf else pgf
  