boltzmann-brain-1.6: Data/Boltzmann/System/Parser/Rational.hs
{-|
Module : Data.Boltzmann.System.Parser.Rational
Description : Parser utilities for rational systems.
Copyright : (c) Maciej Bendkowski, 2017-2019
License : BSD3
Maintainer : maciej.bendkowski@tcs.uj.edu.pl
Stability : experimental
Parser utilities meant to deal with rational system specifications.
-}
module Data.Boltzmann.System.Parser.Rational
( systemStmt
) where
import Control.Monad (void)
import Text.Megaparsec
import Text.Megaparsec.Char
import Data.Void
import qualified Data.Set as Z
import qualified Data.Map.Strict as M
import Data.Boltzmann.Internal.Parser
import qualified Data.Boltzmann.System as S
import Data.Boltzmann.System.Annotations
type Parser = Parsec Void String
-- | Rational system specification parser.
systemStmt :: Parser (S.System Int)
systemStmt = sc *> systemStmt' <* eof
where systemStmt' = do
an <- annotationParser
alph <- alphabetStmt
ds <- some (defsStmt alph)
return S.System { S.defs = M.fromList ds
, S.annotations = M.fromList an
, S.alphabet = alph
}
-- | Letter identifier.
letterIdent :: Parser String
letterIdent = lexeme $ some (alphaNumChar <|> char '_')
-- | Letter parser.
letterStmt :: Parser S.Letter
letterStmt = do
letter <- letterIdent
letterF <- option (-1.0) (symbol ":" >> double)
letterW <- option (length letter) (parens integer)
return S.Letter { S.symb = letter
, S.freq = toFreq letterF
, S.weightL = letterW
}
-- | Alphabet specification parser.
alphabetStmt :: Parser S.Alphabet
alphabetStmt = do
ls <- setBrackets $ letterStmt `sepBy1` symbol ","
return $ Z.fromList ls
defsStmt :: S.Alphabet -> Parser (String, [S.Cons Int])
defsStmt alph = do
t <- identifier
void (symbol "->")
exprs <- exprListStmt alph
return (t, exprs)
exprListStmt :: S.Alphabet -> Parser [S.Cons Int]
exprListStmt alph = try (epsStmt <|> exprStmt alph) `sepBy1` symbol "|"
epsStmt :: Parser (S.Cons Int)
epsStmt = do
void (symbol "_")
return S.Cons { S.func = "_"
, S.args = []
, S.weight = 0
, S.frequency = Nothing
}
exprStmt :: S.Alphabet -> Parser (S.Cons Int)
exprStmt alph = do
typ <- identifier
letter <- option "" (parens letterIdent) -- potential epsilon transitions.
let x = S.Letter { S.symb = letter, S.freq = Nothing, S.weightL = 0 }
let w = case x `Z.lookupIndex` alph of
Nothing -> 0 -- epsilon transitions or not existing symbols.
Just idx -> S.weightL $ Z.elemAt idx alph
return S.Cons { S.func = letter
, S.args = [S.Type typ]
, S.frequency = Nothing
, S.weight = w
}