never executed always true always false
    1 -- All extensions should be enabled explicitly due to doctest in this module.
    2 {-# LANGUAGE Arrows #-}
    3 {-# LANGUAGE ImportQualifiedPost #-}
    4 {-# LANGUAGE NamedFieldPuns #-}
    5 {-# LANGUAGE OverloadedStrings #-}
    6 
    7 {- |
    8 Module      : NITTA.Frontends.XMILE.DocumentParser
    9 Description : Parses XMILE source file to internal tree structure
   10 Copyright   : (c) Artur Gogiyan, 2022
   11 License     : BSD3
   12 Maintainer  : artur.gogiyan@gmail.com
   13 Stability   : experimental
   14 -}
   15 module NITTA.Frontends.XMILE.DocumentParser (
   16     parseDocument,
   17     Content (..),
   18     Stock (..),
   19     Aux (..),
   20     Flow (..),
   21     SimSpec (..),
   22 ) where
   23 
   24 import Data.Text qualified as T
   25 import NITTA.Frontends.XMILE.MathParser
   26 import Text.XML.HXT.Arrow.ReadDocument
   27 import Text.XML.HXT.Core
   28 
   29 data Content = Content
   30     { xcSimSpecs :: SimSpec
   31     , xcFlows :: [Flow]
   32     , xcAuxs :: [Aux]
   33     , xcStocks :: [Stock]
   34     }
   35     deriving (Show, Eq)
   36 
   37 data SimSpec = SimSpec
   38     { xssStart :: Double
   39     , xssStop :: Double
   40     , xssDt :: Double
   41     }
   42     deriving (Show, Eq)
   43 
   44 newtype Model = Model
   45     {xmVariables :: Variables}
   46     deriving (Show, Eq)
   47 
   48 data Variables = Variables
   49     { xvFlows :: [Flow]
   50     , xvAuxs :: [Aux]
   51     , xvStocks :: [Stock]
   52     }
   53     deriving (Show, Eq)
   54 
   55 data Flow = Flow
   56     { xfName :: T.Text
   57     , xfEquation :: XMExpr
   58     }
   59     deriving (Show, Eq)
   60 
   61 data Aux = Aux
   62     { xaName :: T.Text
   63     , xaEquation :: XMExpr
   64     }
   65     deriving (Show, Eq)
   66 
   67 data Stock = Stock
   68     { xsName :: T.Text
   69     , xsEquation :: XMExpr
   70     , xsInflow :: Maybe T.Text
   71     , xsOutflow :: Maybe T.Text
   72     }
   73     deriving (Show, Eq)
   74 
   75 data AlgState v x = AlgState
   76     { xasSimSpec :: SimSpec
   77     , xasModel :: Model
   78     }
   79     deriving (Show, Eq)
   80 
   81 parseDocument src =
   82     head $
   83         runLA
   84             ( xreadDoc
   85                 >>> removeAllWhiteSpace
   86                 >>> proc st -> do
   87                     xcSimSpecs <- parseSimSpec -< st
   88                     xcFlows <- parseFlows -< st
   89                     xcAuxs <- parseAuxs -< st
   90                     xcStocks <- parseStocks -< st
   91                     returnA -< Content{xcSimSpecs, xcFlows, xcAuxs, xcStocks}
   92             )
   93             src
   94 
   95 parseSimSpec =
   96     atTag "sim_specs"
   97         >>> proc x -> do
   98             stop <- text <<< atTag "stop" -< x
   99             start <- text <<< atTag "start" -< x
  100             dt <- text <<< atTag "dt" -< x
  101             returnA -< SimSpec{xssStart = read start, xssStop = read stop, xssDt = read dt}
  102 
  103 parseFlows =
  104     atTag "variables"
  105         >>> listA
  106             ( atTag "flow"
  107                 >>> proc flow -> do
  108                     eqn <- text <<< atTag "eqn" -< flow
  109                     name <- atAttr "name" -< flow
  110                     returnA -< Flow{xfEquation = parseXmileEquation eqn, xfName = replaceSpaces $ T.pack name}
  111             )
  112 
  113 parseAuxs =
  114     atTag "variables"
  115         >>> listA
  116             ( atTag "aux"
  117                 >>> proc aux -> do
  118                     eqn <- text <<< atTag "eqn" -< aux
  119                     name <- atAttr "name" -< aux
  120                     returnA -< Aux{xaEquation = parseXmileEquation eqn, xaName = replaceSpaces $ T.pack name}
  121             )
  122 
  123 parseStocks =
  124     atTag "variables"
  125         >>> listA
  126             ( atTag "stock"
  127                 >>> proc stock -> do
  128                     eqn <- text <<< atTag "eqn" -< stock
  129                     outflow <- getTagOrNothing "outflow" -< stock
  130                     inflow <- getTagOrNothing "inflow" -< stock
  131                     name <- atAttr "name" -< stock
  132                     returnA
  133                         -<
  134                             Stock
  135                                 { xsEquation = parseXmileEquation eqn
  136                                 , xsName = replaceSpaces $ T.pack name
  137                                 , xsOutflow = replaceSpaces <$> outflow
  138                                 , xsInflow = replaceSpaces <$> inflow
  139                                 }
  140             )
  141     where
  142         getTagOrNothing name =
  143             (atTag name >>> text >>> arr (\x -> Just (T.pack x)))
  144                 `orElse` arr (const Nothing)
  145 
  146 replaceSpaces str = T.filter (/= '"') $ T.replace " " "_" str
  147 
  148 atTag tag = deep (isElem >>> hasName tag)
  149 atAttr attrName = deep (isElem >>> getAttrValue attrName)
  150 text = getChildren >>> getText