[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