{-# LANGUAGE OverloadedStrings #-} module Main where import System.Environment import System.IO import Control.Applicative import Data.Maybe import Data.Attoparsec.Text as A import Text.Printf import Data.Ratio import Data.List as L import qualified Data.Text as T import qualified Data.Text.IO as T import qualified Data.Vector as V data Expr a = Num a | Var Int | Add (Expr a) (Expr a) | Sub (Expr a) (Expr a) | Mul (Expr a) (Expr a) | Div (Expr a) (Expr a) main :: IO () main = do (tExpr:vars) <- getArgs let Right rExpr = parseOnly expr (T.pack tExpr) let Just res = eval rExpr $ V.fromList $ map (pNum . T.pack) vars output res pNum :: T.Text -> Rational pNum t = res where Right res = parseOnly (rational <* endOfInput) t output :: Rational -> IO () output = putStrLn . display 10 display :: (Integral i, Show i) => Int -> Ratio i -> String display len rat = (if num < 0 then "-" else "") ++ show ip ++ (if remStr == "" then "" else "." ++ remStr) where num = numerator rat den = denominator rat ip = abs num `quot` den go 0 = "" go x = shows d (go next) where (d, next) = (10 * x) `quotRem` den remStr = L.take len (go (abs num - ip * den)) eval :: (Fractional a) => Expr a -> V.Vector a -> Maybe a eval (Num d) _ = Just d eval (Var i) v = v V.!? i eval (Add x y) v = (+) <$> eval x v <*> eval y v eval (Sub x y) v = (-) <$> eval x v <*> eval y v eval (Mul x y) v = (*) <$> eval x v <*> eval y v eval (Div x y) v = (/) <$> eval x v <*> eval y v expr :: (Fractional a) => Parser (Expr a) expr = skipSpace *> rExpr <* skipSpace term :: (Fractional a) => Parser (Expr a) term = skipSpace *> rTerm <* skipSpace rExpr :: (Fractional a) => Parser (Expr a) rExpr = Add <$> term <* "+" <*> expr <|> Sub <$> term <* "-" <*> expr <|> term rTerm :: (Fractional a) => Parser (Expr a) rTerm = Mul <$> num <* "*" <*> term <|> Div <$> num <* "/" <*> term <|> num num :: (Fractional a) => Parser (Expr a) num = Num <$> (skipSpace *> rational <* skipSpace) <|> skipSpace *> "(" *> expr <* ")" <* skipSpace <|> Var <$> (skipSpace *> "[" *> decimal <* "]" <* skipSpace)