[Haskell-cafe] Minim interpreter
Hugh Perkins
hughperkins at gmail.com
Fri Jul 20 20:41:58 EDT 2007
Ok, that got the variables working.
Example:
*Minim> evaluateprog $ ProgramTree ( ProgramLeaf $ AssignmentStatement(
VarAssignment (Variable "test") ( ValueFromConstant (Constant 3)))) (
PrintStatement (PrintValue( ValueFromVariable(Variable "test"))))
3.0
3.0
I'm having eval return the IO monad, the Map, and a Double. That means we
can use the same Eval class to evaluate for example the value of a Value.
Next step is either to get the parsing working for the functional eval
parts, or to get looping working.
Yes, I'm aware that this is Haskell 101 :-D
module Minim
where
import Char
import List
import Control.Monad
import Control.Monad.State
import Control.Monad.Reader
import qualified Text.ParserCombinators.Parsec as Parsec
import qualified Data.Map as Map
{-
<program> := <statement>
| <statement> <program>;
<statement> := <assignment>
| <conditional>
| <goto>
| <tag>;
| <print>
| <input>
<assignment> := (<var> is <val>) { assign a value to a variable }
| (++ <var>) { increment a variable }
| (-- <var>); { decrement a variable }
<val> := <constant> | <var>;
<var> := any symbol;
<constant> := any number
<conditional> := (if <test> then <statement> else <statement>);
<test> := (<val> <comp> <val>)
| (<test> and <test>); { boolean AND}
| (<test> or <test>) {boolean OR}
| (not <test>); {boolean NOT}
<comp> := > | < | =;
<goto> := (goto <tag>); {go to}
<tag> := any symbol
<print> := (print <string>) | (print <val>); nl; {nl is new line}
<input> := (input <var>); {input the users response to
var}
<string> := any string;
-}
testtry = Parsec.try (Parsec.string "hello")
Parsec.<|> Parsec.string "help"
string :: Parsec.Parser String
string = Parsec.many1 Parsec.letter
minimprint = do Parsec.string "print"
Parsec.many1 (Parsec.char ' ')
Parsec.char '"'
stringvalue <- string
Parsec.char '"'
return (Print stringvalue)
parens :: Parsec.Parser ()
parens = do Parsec.char '('
parens
Parsec.char ')'
parens
Parsec.<|> return ()
class Eval a where
eval :: a -> StateT (Map.Map String Double) IO Double
data Program = ProgramLeaf Statement | ProgramTree Program Statement
deriving(Show)
instance Eval Program where
eval (ProgramLeaf statement) = eval statement
eval (ProgramTree program statement) = do eval program
eval statement
data Statement = PrintStatement Print |
AssignmentStatement Assignment
deriving(Show)
instance Eval Statement where
eval ( PrintStatement print) = eval print
eval ( AssignmentStatement assignment) = eval assignment
data Print = Print String | PrintValue Value
deriving(Show)
instance Eval Print where
eval (Print value) = do liftIO $ putStrLn value
return 0
eval (PrintValue value) = do evaluatedvalue <- eval value
liftIO $ putStrLn (show(evaluatedvalue))
return evaluatedvalue
data Assignment = VarAssignment Variable Value |
Increment Variable |
Decrement Variable
deriving(Show)
instance Eval Assignment where
eval (VarAssignment (Variable varname) (ValueFromConstant (Constant
constant))) = do oldmap <- get
let newmap = Map.insert varname constant oldmap
put newmap
return constant
data Variable = Variable String
deriving(Show)
data Value = ValueFromConstant Constant | ValueFromVariable Variable
deriving(Show)
instance Eval Value where
eval (ValueFromConstant (Constant i )) = return i
eval (ValueFromVariable (Variable varname )) = do map <- get
return (map Map.!
varname)
newtype Constant = Constant Double
deriving(Show)
instance Eval Constant where
eval (Constant i) = return i
evaluateprog prog = evalStateT( eval prog ) Map.empty
minimparse minimsentence = case (Parsec.runParser minimprint () ""
minimsentence) of
(Right statement) -> evaluateprog statement
Left error -> do putStrLn("error: " ++
show(error))
return 0
test = minimparse "print \"hello\""
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20070721/086274b5/attachment.htm
More information about the Haskell-Cafe
mailing list