Advertisement
Guest User

Untitled

a guest
May 23rd, 2018
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Haskell 10.03 KB | None | 0 0
  1. module Main where
  2.  
  3. import qualified Data.Map.Lazy              as Map
  4. import           Control.Monad.State.Lazy
  5. import           Control.Monad.Reader
  6. import           Control.Monad.Cont
  7. import qualified Control.Exception          as Exc
  8. import qualified Text.Megaparsec            as P
  9. import qualified Text.Megaparsec.Char.Lexer as L
  10. import           Text.Megaparsec.Char
  11. import           Text.Megaparsec.Expr
  12. import qualified Data.Void                  as Void  
  13. import           System.IO
  14. import           System.Environment
  15. import           Data.Foldable
  16. import           Data.Text                  as T
  17.  
  18.  
  19. data Expr = Lit Int            
  20.           | Var T.Text          
  21.           | Add Expr   Expr      
  22.           | Sub Expr   Expr      
  23.           | Mul Expr   Expr      
  24.           | Div Expr   Expr      
  25.           | Let T.Text Expr Expr
  26.           deriving Show
  27.  
  28. data ExprException = DivisionByZero        
  29.                    | UnknownVariable T.Text
  30.                    deriving Show
  31.  
  32. instance Exc.Exception ExprException
  33.  
  34. evaluate :: Expr -> Reader (Map.Map T.Text Int) Int
  35. evaluate (Lit c)               = return c
  36. evaluate (Var name)            = do result <- asks (Map.lookup name)
  37.                                     case result of
  38.                                       Nothing -> Exc.throw (UnknownVariable name)
  39.                                       Just x  -> return x
  40. evaluate (Add first second)    = liftM2 (+) (evaluate first) (evaluate second)
  41. evaluate (Sub first second)    = liftM2 (-) (evaluate first) (evaluate second)
  42. evaluate (Mul first second)    = liftM2 (*) (evaluate first) (evaluate second)
  43. evaluate (Div first second)    = do a <- evaluate first
  44.                                     b <- evaluate second
  45.                                     case b of
  46.                                       0 -> Exc.throw DivisionByZero
  47.                                       _ -> return (a `div` b)
  48. evaluate (Let name expr expr1) = do a <- evaluate expr
  49.                                     local (Map.insert name a) (evaluate expr1)
  50.  
  51. newtype Program = Program [Statement]
  52.                 deriving Show
  53.  
  54. data Statement = Define T.Text Expr
  55.                | Update T.Text Expr
  56.                | For T.Text Expr Expr [Statement]
  57.                | Break
  58.                | Read T.Text
  59.                | Write Expr
  60.                | Pure Expr
  61.                deriving Show
  62.  
  63. type Parser = P.Parsec Void.Void T.Text
  64.  
  65. spaceConsumer :: Parser ()
  66. spaceConsumer = L.space space1 (L.skipLineComment "//") (L.skipBlockComment "/*" "*/")
  67.  
  68. lexeme :: Parser a -> Parser a
  69. lexeme = L.lexeme spaceConsumer
  70.  
  71. symbol :: T.Text -> Parser T.Text
  72. symbol a = P.try $ L.symbol spaceConsumer a
  73.  
  74. parenthesis :: Parser a -> Parser a
  75. parenthesis = P.between (symbol "(") (symbol ")")
  76.  
  77. integer :: Parser Int
  78. integer = P.try $ lexeme L.decimal
  79.  
  80. signedInteger :: Parser Int
  81. signedInteger = P.try $ L.signed spaceConsumer integer
  82.  
  83. rword :: T.Text -> Parser ()
  84. rword w = (lexeme . P.try) (string w *> P.notFollowedBy alphaNumChar)
  85.  
  86. reservedWords :: [T.Text]
  87. reservedWords = ["let", "in", "=", "mut", "for", "{", "}", ";", "break", "until", "<", ">"]
  88.  
  89. identifier :: Parser T.Text
  90. identifier = P.try $ (lexeme . P.try) (p >>= check)
  91.   where
  92.     p :: Parser T.Text
  93.     p = T.pack <$> ((:) <$> letterChar <*> P.many alphaNumChar)
  94.     check :: T.Text -> Parser T.Text
  95.     check x = if x `elem` reservedWords
  96.               then fail $ "keyword " ++ show x ++ " cannot be an identifier"
  97.               else return x
  98.  
  99. parseStatement :: Parser Statement
  100. parseStatement = P.try forStatement P.<|> statementsWithSemi
  101.  
  102. statementsWithSemi :: Parser Statement
  103. statementsWithSemi = P.try $ Data.Foldable.foldr1 (P.<|>) (Prelude.map (P.try . parseSemi)
  104.      [updateStatement,
  105.       defineStatement,  
  106.       readStatement,    
  107.       writeStatement,    
  108.       breakStatement,
  109.       pureStatement])
  110.   where
  111.     parseSemi a = a >>= \b -> P.try (symbol ";") >> return b
  112.  
  113. programParser :: Parser Program
  114. programParser = P.try $ Program <$> P.between spaceConsumer P.eof (P.many parseStatement)
  115.  
  116. pureStatement :: Parser Statement
  117. pureStatement = P.try $ Pure <$> parseExpr
  118.  
  119. breakStatement :: Parser Statement
  120. breakStatement = P.try $ const Break <$> symbol "break"
  121.  
  122. forStatement :: Parser Statement
  123. forStatement = do rword "for"
  124.                   name <- identifier
  125.                   rword "="
  126.                   expr <- parseExpr
  127.                   rword "until"
  128.                   expr1 <- parseExpr
  129.                   rword "{"
  130.                   statements <- P.many parseStatement
  131.                   rword "}"
  132.                   return (For name expr expr1 statements)
  133.  
  134. readStatement :: Parser Statement
  135. readStatement = do rword ">"
  136.                    name <- identifier
  137.                    return (Read name)
  138.  
  139. writeStatement :: Parser Statement
  140. writeStatement = do rword "<"
  141.                     expr <- parseExpr
  142.                     return (Write expr)
  143.  
  144. updateStatement :: Parser Statement
  145. updateStatement = do name <- identifier
  146.                      rword "="
  147.                      expr <- arithmeticExpr
  148.                      return (Update name expr)
  149.  
  150. defineStatement :: Parser Statement
  151. defineStatement = do rword "mut"
  152.                      name <- identifier
  153.                      rword "="
  154.                      expr <- arithmeticExpr
  155.                      return (Define name expr)
  156.  
  157. letExpr :: Parser Expr
  158. letExpr = do rword "let"
  159.              name <- identifier
  160.              rword "="
  161.              expF <- parseExpr
  162.              rword "in"
  163.              expS <- parseExpr
  164.              return (Let name expF expS)
  165.  
  166. whileExpr :: Parser Expr
  167. whileExpr = P.between spaceConsumer P.eof parseExpr
  168.  
  169. parseExpr :: Parser Expr
  170. parseExpr = Data.Foldable.foldr1 (P.<|>)
  171.            [arithmeticExpr,
  172.             variable,
  173.             literal,              
  174.             letExpr,
  175.             parenthesis parseExpr]
  176.  
  177. parseExpr1 :: Parser Expr
  178. parseExpr1 = Data.Foldable.foldr1 (P.<|>)
  179.             [variable,
  180.              literal,              
  181.              letExpr,              
  182.              parenthesis parseExpr]
  183.  
  184. arithmeticExpr :: Parser Expr
  185. arithmeticExpr = makeExprParser (P.try parseExpr1) arithmeticOperators
  186.  
  187. arithmeticOperators :: [[Operator Parser Expr]]
  188. arithmeticOperators = [[InfixL (Mul <$ symbol "*"),
  189.                         InfixL (Div <$ symbol "/")],
  190.                        [InfixL (Add <$ symbol "+"),
  191.                         InfixL (Sub <$ symbol "-")]]
  192.  
  193. variable :: Parser Expr
  194. variable = Var <$> identifier
  195.  
  196. literal :: Parser Expr
  197. literal = Lit <$> signedInteger
  198.  
  199. data ContextException = VariableNotInContext T.Text
  200.                       | VariableIsAlreadyInContext T.Text
  201.                       deriving Show
  202.  
  203. instance Exc.Exception ContextException
  204.  
  205. updateCtx :: T.Text -> Int -> StateT (Map.Map T.Text Int) IO ()
  206. updateCtx key val = do truth <- gets (Map.member key)
  207.                        {-(lift . putStrLn) $ "updating " ++ key-}
  208.                        if truth then modify (Map.insert key val)
  209.                        else     Exc.throw $ VariableNotInContext key
  210.  
  211. setCtx :: T.Text -> Int -> StateT (Map.Map T.Text Int) IO ()
  212. setCtx key val = do truth <- gets (Map.member key)
  213.                     {-(lift . putStrLn) $ "setting " ++ key-}
  214.                     if truth then Exc.throw $ VariableIsAlreadyInContext key
  215.                     else     modify (Map.insert key val)
  216.  
  217. removeCtx :: T.Text -> StateT (Map.Map T.Text Int) IO ()
  218. removeCtx key = do truth <- gets (Map.member key)
  219.                    {-(lift . putStrLn) $ "removing " ++ key-}
  220.                    if truth then modify (Map.delete key)
  221.                    else     Exc.throw $ VariableNotInContext key
  222.  
  223. data BreakInfo = NeedBreak
  224.                | NeedNotBreak
  225.  
  226. evaluateState :: [Statement] -> ContT BreakInfo (StateT (Map.Map T.Text Int) IO) ()
  227. evaluateState statements = Data.Foldable.foldl (>>=) (return ()) $ Prelude.map func statements
  228.   where
  229.     func :: Statement -> () -> ContT BreakInfo (StateT (Map.Map T.Text Int) IO) ()
  230.     func statement _ = ContT $ \f ->
  231.       case statement of
  232.         Define name expr -> do
  233.           context <- get
  234.           setCtx name $ runReader (evaluate expr) context
  235.           result <- f ()
  236.           removeCtx name
  237.           return result
  238.         Update name expr -> do
  239.           context <- get
  240.           updateCtx name $ runReader (evaluate expr) context
  241.           f ()
  242.         Write expr -> do
  243.           context <- get
  244.           (lift . putStrLn) $ show (runReader (evaluate expr) context)
  245.           f ()
  246.         Read name -> do
  247.           value <- lift getLine
  248.           let num = read value :: Int
  249.           updateCtx name num
  250.           f ()
  251.         For name from untiL st -> do
  252.           context <- get
  253.           let first = runReader (evaluate from) context
  254.           setCtx name first
  255.           let monad = runContT (evaluateState st) $ const (return NeedNotBreak)
  256.           let recursive = do ctx <- get
  257.                              let second = runReader (evaluate untiL) ctx
  258.                              curVal <- gets (Map.! name)
  259.                              if curVal >= second
  260.                              then return NeedNotBreak
  261.                              else monad >>= \a ->
  262.                                case a of
  263.                                  NeedBreak -> return NeedNotBreak
  264.                                  _ -> gets (Map.! name) >>= \val -> updateCtx name (val + 1) >> recursive
  265.           _ <- recursive
  266.           removeCtx name
  267.           f ()
  268.         Pure _ -> f ()
  269.         Break  -> return NeedBreak
  270.  
  271. main :: IO ()
  272. main = do fileName   <- Prelude.head <$> getArgs
  273.           fileHandle <- openFile fileName ReadMode
  274.           content    <- hGetContents fileHandle
  275.           let parsed = P.parse programParser "" (T.pack content)
  276.           {-print parsed-}
  277.           case parsed of
  278.             Right (Program statements) -> Control.Monad.Cont.void (runStateT (runContT (evaluateState statements) $ const (return NeedNotBreak)) Map.empty)
  279.             Left  _                    -> return ()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement