<commit_before>{-
Copyrights (c) 2016. Samsung Electronics Ltd. All right reserved. 

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-}
{-# LANGUAGE RecordWildCards, ImplicitParams #-}

import System.Environment
import Text.Parsec.Prim
import Control.Monad
import System.FilePath.Posix
import Text.PrettyPrint
import Text.Printf
import Data.Maybe
import Data.List
import System.Directory
import System.IO.Error
import System.IO
import System.Console.GetOpt

import Parse
import Validate
import P4.P4
import Topology
import MiniNet.MiniNet
import Name
import Syntax
import NS
import Expr
import PP
import Boogie.Boogie
import Util
import qualified NetKAT.NetKAT as NK

data TOption = CCN String
             | CFG String
             | Bound String
             | DoBoogie
             | DoP4
             | DoNetKAT
        
options :: [OptDescr TOption]
options = [ Option ['i'] []             (ReqArg CCN "FILE")            "input Cocoon file"
          , Option []    ["cfg"]        (ReqArg CFG "FILE")            "Cocoon config file"
          , Option ['b'] ["bound"]      (ReqArg Bound "BOUND")         "integer bound on the number of hops"
          , Option []    ["boogie"]     (NoArg DoBoogie)               "enable Boogie backend"
          , Option []    ["p4"]         (NoArg DoP4)                   "enable P4 backend"
          , Option []    ["netkat"]     (NoArg DoNetKAT)               "enable NetKAT backend"
          ]

data Config = Config { confCCNFile      :: FilePath
                     , confCfgFile      :: Maybe FilePath
                     , confBound        :: Int
                     , confDoBoogie     :: Bool
                     , confDoP4         :: Bool
                     , confDoNetKAT     :: Bool
                     }

defaultConfig = Config { confCCNFile      = ""
                       , confCfgFile      = Nothing
                       , confBound        = 15
                       , confDoBoogie     = False
                       , confDoP4         = False
                       , confDoNetKAT     = False
                       }


addOption :: TOption -> Config -> Config
addOption (CCN f)   config = config{ confCCNFile  = f}
addOption (CFG f)   config = config{ confCfgFile  = Just f}
addOption (Bound b) config = config{ confBound    = case reads b of
                                                         []        -> error "invalid bound specified"
                                                         ((i,_):_) -> i}
addOption DoBoogie  config = config{ confDoBoogie = True}
addOption DoP4      config = config{ confDoP4     = True}
addOption DoNetKAT  config = config{ confDoNetKAT = True}

main = do
    args <- getArgs
    prog <- getProgName
    config <- case getOpt Permute options args of
                   (flags, [], []) -> return $ foldr addOption defaultConfig flags
                   _ -> fail $ usageInfo ("Usage: " ++ prog ++ " [OPTION...]") options 

    let fname  = confCCNFile config
        cfname = confCfgFile config
        (dir, file) = splitFileName fname
        (basename,_) = splitExtension file
        workdir = dir </> basename
        bound = confBound config
    createDirectoryIfMissing False workdir
    fdata <- readFile fname
    spec <- case parse cocoonGrammar fname fdata of
                 Left  e    -> fail $ "Failed to parse input file: " ++ show e
                 Right spec -> return spec
    combined <- case validate spec of
                     Left e   -> fail $ "Validation error: " ++ e
                     Right rs -> return rs
    let final = last combined
    putStrLn "Validation complete"<commit_msg>dump parsed spec for debugging<commit_after>{-
Copyrights (c) 2016. Samsung Electronics Ltd. All right reserved. 

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-}
{-# LANGUAGE RecordWildCards, ImplicitParams #-}

import System.Environment
import Text.Parsec.Prim
import Control.Monad
import System.FilePath.Posix
import Text.PrettyPrint
import Text.Printf
import Data.Maybe
import Data.List
import System.Directory
import System.IO.Error
import System.IO
import System.Console.GetOpt

import Parse
import Validate
import P4.P4
import Topology
import MiniNet.MiniNet
import Name
import Syntax
import NS
import Expr
import PP
import Boogie.Boogie
import Util
import qualified NetKAT.NetKAT as NK

data TOption = CCN String
             | CFG String
             | Bound String
             | DoBoogie
             | DoP4
             | DoNetKAT
        
options :: [OptDescr TOption]
options = [ Option ['i'] []             (ReqArg CCN "FILE")            "input Cocoon file"
          , Option []    ["cfg"]        (ReqArg CFG "FILE")            "Cocoon config file"
          , Option ['b'] ["bound"]      (ReqArg Bound "BOUND")         "integer bound on the number of hops"
          , Option []    ["boogie"]     (NoArg DoBoogie)               "enable Boogie backend"
          , Option []    ["p4"]         (NoArg DoP4)                   "enable P4 backend"
          , Option []    ["netkat"]     (NoArg DoNetKAT)               "enable NetKAT backend"
          ]

data Config = Config { confCCNFile      :: FilePath
                     , confCfgFile      :: Maybe FilePath
                     , confBound        :: Int
                     , confDoBoogie     :: Bool
                     , confDoP4         :: Bool
                     , confDoNetKAT     :: Bool
                     }

defaultConfig = Config { confCCNFile      = ""
                       , confCfgFile      = Nothing
                       , confBound        = 15
                       , confDoBoogie     = False
                       , confDoP4         = False
                       , confDoNetKAT     = False
                       }


addOption :: TOption -> Config -> Config
addOption (CCN f)   config = config{ confCCNFile  = f}
addOption (CFG f)   config = config{ confCfgFile  = Just f}
addOption (Bound b) config = config{ confBound    = case reads b of
                                                         []        -> error "invalid bound specified"
                                                         ((i,_):_) -> i}
addOption DoBoogie  config = config{ confDoBoogie = True}
addOption DoP4      config = config{ confDoP4     = True}
addOption DoNetKAT  config = config{ confDoNetKAT = True}

main = do
    args <- getArgs
    prog <- getProgName
    config <- case getOpt Permute options args of
                   (flags, [], []) -> return $ foldr addOption defaultConfig flags
                   _ -> fail $ usageInfo ("Usage: " ++ prog ++ " [OPTION...]") options 

    let fname  = confCCNFile config
        cfname = confCfgFile config
        (dir, file) = splitFileName fname
        (basename,_) = splitExtension file
        workdir = dir </> basename
        bound = confBound config
    createDirectoryIfMissing False workdir
    fdata <- readFile fname
    spec <- case parse cocoonGrammar fname fdata of
                 Left  e    -> fail $ "Failed to parse input file: " ++ show e
                 Right spec -> return spec
    combined <- case validate spec of
                     Left e   -> fail $ "Validation error: " ++ e
                     Right rs -> return rs
    --mapM_ (putStrLn . ("\n" ++)  . render . pp) combined 
    let final = last combined
    putStrLn "Validation complete"
{'fraction_non_alphanumeric': 0.07787823990355636, 'fraction_numerical': 0.004822182037371911, 'mean_word_length': 1.7388577088147903, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6911593', 'n_tokens_mistral': 2232, 'n_tokens_neox': 2129, 'n_words': 779}