never executed always true always false
1 {- |
2 Module : NITTA.Frontends.XMILE.MathParser
3 Description : Parses XMILE math equations
4 Copyright : (c) Artur Gogiyan, 2022
5 License : BSD3
6 Maintainer : artur.gogiyan@gmail.com
7 Stability : experimental
8 -}
9 module NITTA.Frontends.XMILE.MathParser (
10 parseXmileEquation,
11 calculateDefaultValue,
12 XMExpr (..),
13 XMDuop (..),
14 ) where
15
16 import Data.HashMap.Strict qualified as HM
17 import Data.Maybe (fromMaybe)
18 import Data.Text as T
19 import Text.Parsec
20 import Text.Parsec.Expr
21 import Text.Parsec.Language
22 import Text.Parsec.String
23 import Text.Parsec.Token
24 import Text.Read hiding (parens)
25
26 data XMExpr = Var String | Val Double | Duo {xmeOp :: XMDuop, xmeLexpr, xmeRexpr :: XMExpr}
27 deriving (Show, Eq)
28
29 data XMDuop = Mul | Div | Add | Sub deriving (Show, Eq)
30
31 languageDef =
32 emptyDef
33 { identStart = letter <|> space <|> digit <|> char '\"'
34 , identLetter = letter <|> space <|> digit <|> char '.'
35 , opStart = oneOf "+-/*"
36 , opLetter = oneOf "+-/*"
37 , reservedOpNames = ["+", "-", "/", "*"]
38 , reservedNames = ["true", "false"]
39 }
40
41 TokenParser
42 { parens = m_parens
43 , identifier = m_identifier
44 , reservedOp = m_reservedOp
45 } = makeTokenParser languageDef
46
47 parseXmileEquation eqn = case parse exprparser "" eqn of
48 Right e -> prepareTree e
49 Left _ -> error $ "error while parsing XMILE equation : " <> eqn
50
51 exprparser :: Parser XMExpr
52 exprparser = buildExpressionParser table term <?> "expression"
53 table =
54 [ [Infix (m_reservedOp "*" >> return (Duo Mul)) AssocLeft]
55 , [Infix (m_reservedOp "/" >> return (Duo Div)) AssocLeft]
56 , [Infix (m_reservedOp "+" >> return (Duo Add)) AssocLeft]
57 , [Infix (m_reservedOp "-" >> return (Duo Sub)) AssocLeft]
58 ]
59 term =
60 m_parens exprparser <|> fmap Var (between (skipMany (char '\"')) (skipMany (char '\"' <|> space)) m_identifier)
61
62 trimString str = T.unpack $ T.map repl $ T.strip $ T.pack str
63 where
64 repl ' ' = '_'
65 repl c = c
66
67 prepareTree (Var str) = maybe (Var $ trimString str) Val $ readMaybe str
68 prepareTree v@(Val _) = v
69 prepareTree (Duo op a b) = Duo op (prepareTree a) (prepareTree b)
70
71 calculateDefaultValue _ (Val value) = value
72 calculateDefaultValue defaultValues (Var name) = fromMaybe 0 $ HM.lookup (T.pack name) defaultValues
73 calculateDefaultValue defaultValues e@(Duo op expl expr) =
74 let leftValue = calculateDefaultValue defaultValues expl
75 rightValue = calculateDefaultValue defaultValues expr
76 in case op of
77 Mul -> leftValue * rightValue
78 Div
79 | rightValue == 0 -> error ("division to zero in expression '" <> show e <> "'")
80 | otherwise -> leftValue / rightValue
81 Add -> leftValue + rightValue
82 Sub -> leftValue - rightValue