Now works as a simple calculator of s-exprs, with + - * / and numbers
This commit is contained in:
parent
a00e5b46be
commit
a02176ee18
|
@ -17,4 +17,10 @@ executable picolisp
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
build-depends: base >= 4.7 && < 5
|
other-modules: Parser,
|
||||||
|
Evaluator,
|
||||||
|
Expression,
|
||||||
|
Primitives
|
||||||
|
build-depends: base >= 4.7 && < 5,
|
||||||
|
parsec,
|
||||||
|
haskeline
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
module Evaluator where
|
||||||
|
|
||||||
|
import Expression
|
||||||
|
import Primitives
|
||||||
|
|
||||||
|
eval :: Expression -> Expression
|
||||||
|
eval n@(Number _) = n
|
||||||
|
eval s@(Symbol _) = s
|
||||||
|
eval (SExpr es) = apply $ SExpr (map eval es)
|
||||||
|
|
||||||
|
apply :: Expression -> Expression
|
||||||
|
apply (SExpr (f:args)) = case f of
|
||||||
|
Symbol "+" -> pAdd args
|
||||||
|
Symbol "-" -> pSub args
|
||||||
|
Symbol "*" -> pMul args
|
||||||
|
Symbol "/" -> pDiv args
|
||||||
|
Symbol _ -> error "no primitive functions not supported"
|
||||||
|
_ -> error "object not applicable"
|
||||||
|
apply _ = error "Object not applicable"
|
|
@ -0,0 +1,14 @@
|
||||||
|
module Expression where
|
||||||
|
|
||||||
|
-- The basic unit of the language are Expressions, so we make an
|
||||||
|
-- Expression data with the primitive expression values as the
|
||||||
|
-- constructors
|
||||||
|
data Expression = Number Double
|
||||||
|
| Symbol String
|
||||||
|
| SExpr [Expression]
|
||||||
|
deriving (Eq)
|
||||||
|
|
||||||
|
instance Show Expression where
|
||||||
|
show (Number n) = show n
|
||||||
|
show (Symbol s) = show s
|
||||||
|
show (SExpr es) = "(" ++ unwords (map show es) ++ ")"
|
20
src/Main.hs
20
src/Main.hs
|
@ -1,5 +1,21 @@
|
||||||
module Main where
|
module Main where
|
||||||
|
|
||||||
|
import Parser
|
||||||
|
import Evaluator
|
||||||
|
import System.Console.Haskeline
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = runInputT defaultSettings repl
|
||||||
putStrLn "hello world"
|
where repl = do
|
||||||
|
line <- getInputLine "picolisp> "
|
||||||
|
case line of
|
||||||
|
Nothing -> return ()
|
||||||
|
Just s -> do
|
||||||
|
let eithE = parseExpression s
|
||||||
|
case eithE of
|
||||||
|
Left err -> do
|
||||||
|
outputStrLn $ show err
|
||||||
|
repl
|
||||||
|
Right e -> do
|
||||||
|
outputStrLn . show $ eval e
|
||||||
|
repl
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
module Parser where
|
||||||
|
|
||||||
|
import Text.ParserCombinators.Parsec
|
||||||
|
import Data.Char
|
||||||
|
|
||||||
|
import Expression
|
||||||
|
|
||||||
|
-- Receives a string, parses it, and returns an expression
|
||||||
|
parseExpression :: String -> Either ParseError Expression
|
||||||
|
parseExpression s = do
|
||||||
|
e <- parse anyExpressionParser "" s
|
||||||
|
return e
|
||||||
|
|
||||||
|
-- Parser any possible expression
|
||||||
|
anyExpressionParser :: GenParser Char st Expression
|
||||||
|
anyExpressionParser = numberParser <|> symbolParser <|> sexprParser
|
||||||
|
|
||||||
|
-- Parses an S-expr
|
||||||
|
sexprParser :: GenParser Char st Expression
|
||||||
|
sexprParser = do
|
||||||
|
_ <- spaces
|
||||||
|
_ <- char '('
|
||||||
|
es <- many1 (try $ spaces >> anyExpressionParser)
|
||||||
|
_ <- spaces
|
||||||
|
_ <- char ')' >> spaces
|
||||||
|
return $ SExpr es
|
||||||
|
|
||||||
|
-- Parses a symbol
|
||||||
|
symbolParser :: GenParser Char st Expression
|
||||||
|
symbolParser = Symbol <$> do
|
||||||
|
c <- symbolChar
|
||||||
|
cs <- many (symbolChar <|> digit)
|
||||||
|
return $ c:cs
|
||||||
|
where symbolChar = letter <|> oneOf "!#$%&*+-/:<=>?@\\^_`~"
|
||||||
|
|
||||||
|
-- Parses a number
|
||||||
|
numberParser :: GenParser Char st Expression
|
||||||
|
numberParser = do
|
||||||
|
num <- read <$> many1 digit
|
||||||
|
return $ Number num
|
|
@ -0,0 +1,10 @@
|
||||||
|
module Primitives where
|
||||||
|
|
||||||
|
import Expression
|
||||||
|
|
||||||
|
pAdd, pSub, pMul, pDiv :: [Expression] -> Expression
|
||||||
|
|
||||||
|
pAdd = foldr1 $ \(Number a) (Number b) -> Number (a+b)
|
||||||
|
pSub = foldr1 $ \(Number a) (Number b) -> Number (a-b)
|
||||||
|
pMul = foldr1 $ \(Number a) (Number b) -> Number (a*b)
|
||||||
|
pDiv = foldr1 $ \(Number a) (Number b) -> Number (a/b)
|
Loading…
Reference in New Issue