Skip to content

Instantly share code, notes, and snippets.

@BRonen
Created June 23, 2024 22:16
Show Gist options
  • Save BRonen/6f976e6955e40f83d93079f1e58adfcc to your computer and use it in GitHub Desktop.
Save BRonen/6f976e6955e40f83d93079f1e58adfcc to your computer and use it in GitHub Desktop.
5 minutes math expression interpreter
module MathInterpreter (mathInterpreter) where
import Data.Char
data Token = Number Integer
| Plus
| Dash
| Star
| Slash
deriving Show
data Ast = Value Integer
| Add Ast Ast
| Minus Ast Ast
| Mult Ast Ast
| Div Ast Ast
deriving Show
takeWhileIsDigit :: [Char] -> [Char]
takeWhileIsDigit = takeWhile Data.Char.isDigit
tokenize :: String -> [Token]
tokenize [] = []
tokenize (' ':xs) = tokenize xs
tokenize ('+':xs) = Plus : (tokenize xs)
tokenize ('-':xs) = Dash : (tokenize xs)
tokenize ('*':xs) = Star : (tokenize xs)
tokenize ('/':xs) = Slash : (tokenize xs)
tokenize s = Number (read s') : tokenize r
where s' = takeWhileIsDigit s
r = drop (length s') s
parse :: [Token] -> (Ast, [Token])
parse [] = (Value 0, [])
parse ((Number n):xs) = (Value n, xs)
parse (op:xs) = (op' f s, xs'')
where (f, xs') = parse xs
(s, xs'') = parse xs'
op' = case op of
Plus -> Add
Dash -> Minus
Star -> Mult
Slash -> Div
evaluate :: Ast -> Integer
evaluate (Value v) = v
evaluate (Add left right) = (evaluate left) + (evaluate right)
evaluate (Minus left right) = (evaluate left) - (evaluate right)
evaluate (Mult left right) = (evaluate left) * (evaluate right)
evaluate (Div left right) = (evaluate left) `div` (evaluate right)
tokens :: [Token]
tokens = tokenize "+ 2 3"
ast :: Ast
ast = fst . parse $ tokens
mathInterpreter :: IO Integer
mathInterpreter = print . evaluate $ ast -- 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment