Skip to content

Instantly share code, notes, and snippets.

@rewhile
Created January 27, 2022 09:13
Show Gist options
  • Save rewhile/b1f7c82c41ad838f4b850be357803d7a to your computer and use it in GitHub Desktop.
Save rewhile/b1f7c82c41ad838f4b850be357803d7a to your computer and use it in GitHub Desktop.
First math parser
import Data.Char
import System.IO
import System.Exit
import Control.Applicative
symbol = flip elem ['+', '-', '*', '/']
getOp c = case c of
"+" -> (+)
"-" -> (-)
"*" -> (*)
"/" -> div
split [] cur open close = [reverse cur]
split (x:xs) cur open close
| x == '(' = split xs (if open == 0 then cur else nxt) (open + 1) close
| x == ')' = split xs (if open == close + 1 then cur else nxt) open (close + 1)
| open == close && symbol x = reverse cur : [x] : split xs "" 0 0
| otherwise = split xs nxt open close
where nxt = x : cur
non :: Num b => a -> b -> b
non a b = b
strip str = go str 0 non
where
go :: [String] -> Int -> (Int -> Int -> Int) -> [String]
go [] res _ = [show res]
go (x:xs) res op
| x == "*" || x == "/" = go xs res (getOp x)
| x == "+" || x == "-" = show res : x : go xs 0 non
| otherwise = go xs (op res (sol x)) non
sol :: String -> Int
sol str = if head lis == str then (read str :: Int) else go (strip lis) 0 non
where
lis = (split str "" 0 0)
go [] res _ = res
go (x:xs) res op
| x == "+" || x == "-" = go xs res (getOp x)
| otherwise = go xs (op res (sol x)) non
main = do
putStr "> "
hFlush stdout
s <- getLine
if length s /= 0
then print $ sol s
else exitWith ExitSuccess
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment