packages feed

calculator-0.4.0.0: src/Calculator/Parser/Cmd.hs

module Calculator.Parser.Cmd
    ( parseCmd
    , parseAssignCmd
    , parseAssign
    , parseFuncCmd
    , parseFunc
    ) where

--------------------------------------------------------------------------------

import           Calculator.Parser.Base        (parseId)
import           Calculator.Parser.Expr        (parseExpr)
import           Calculator.Prim.Cmd           (Cmd (..))

import           Calculator.Prim.Expr          (Expr)

--------------------------------------------------------------------------------

import           Control.Applicative           ((<*))
import           Text.ParserCombinators.Parsec

--------------------------------------------------------------------------------
-- cmd -> ':' cmd'

parseCmd :: Parser Cmd
parseCmd = char ':' >> parseCmd'

--------------------------------------------------------------------------------
-- cmd' -> show | help | reset | assign | plot

parseCmd' :: Parser Cmd
parseCmd' = parseShow
         <|> parseHelp
         <|> parseReset
         <|> parseAssignCmd
         <|> parseFuncCmd
         <|> parsePlotCmd

--------------------------------------------------------------------------------
-- help -> "?" | "help"

parseHelp :: Parser Cmd
parseHelp = (string "?" <|> string "help") >> spaces >> return Help

--------------------------------------------------------------------------------
-- show -> "show"

parseShow :: Parser Cmd
parseShow = string "show" >> spaces >> return Display

--------------------------------------------------------------------------------
-- reset -> "reset"

parseReset :: Parser Cmd
parseReset = string "reset" >> spaces >> return Reset

--------------------------------------------------------------------------------
-- plot -> "plot" id

parsePlotCmd :: Parser Cmd
parsePlotCmd = do
  _ <- string "plot"
  _ <- spaces
  f <- parseId
  _ <- spaces
  r <- pairDoubles `sepBy1` spaces
  return $ Plot f r

pairDoubles :: Parser (Expr, Expr)
pairDoubles = do
  _ <- char '('
  _ <- spaces
  l <- parseExpr
  _ <- spaces
  _ <- char ','
  _ <- spaces
  u <- parseExpr
  _ <- spaces
  _ <- char ')'
  return (l, u)

--------------------------------------------------------------------------------
-- assignCmd -> "var" id "=" expr

parseAssignCmd :: Parser Cmd
parseAssignCmd = string "var" >> space >> spaces >> parseAssign

parseAssign :: Parser Cmd
parseAssign = do
  str <- parseId
  _   <- spaces
  _   <- char '='
  _   <- spaces
  ex  <- parseExpr
  return $ Assign str ex

--------------------------------------------------------------------------------
-- func  -> "func" id (args) "=" expr

parseFuncCmd :: Parser Cmd
parseFuncCmd = string "func" >> space >> spaces >> parseFunc

parseFunc :: Parser Cmd
parseFunc = do
  ident <- try (parseId <* (spaces >> char '(' >> spaces))
  args  <- (parseId <* spaces) `sepBy` (char ',' <* spaces) <* char ')'
  _     <- spaces >> char '=' <* spaces
  expr  <- parseExpr
  return $ Func ident args expr

--------------------------------------------------------------------------------