Short overview on

Interpreter Construction in Haskell

1

Alexander Isenko

15.05.2017

https://github.com/cirquit/hjc

https://github.com/cirquit/sl-interpreter

Interpreting Code in Host Language

2

Alexander Isenko

15.05.2017

Lexer

Parser

AST-Interpreter

Source Program

Tokens

AST

Source Program

in Host Language

Lexer

3

Alexander Isenko

15.05.2017

import Text.Megaparsec

-- | 'parens' parses something between parenthesis.
parens :: Parser a -> Parser a
parens = between (symbol "(") (symbol ")")

-- | 'semi' parses a semicolon.
semi :: Parser String
semi = symbol ";"

rws :: [String] -- list of reserved words
rws = ["if","then","else","while","do","skip","true","false","not","and","or", "print"]

identifier :: Parser String
identifier = (lexeme . try) (p >>= check)
  where
    p       = (:) <$> letterChar <*> many alphaNumChar
    check x = if x `elem` rws
                then fail $ "hjc: keyword " ++ show x ++ " cannot be an identifier"
                else return x

Abstract Syntax Tree

4

Alexander Isenko

15.05.2017

data MiniJava = MiniJava
    { _mainClass    :: Class
    , _otherClasses :: [Class]
    }  deriving (Eq)

-- class <name> (extends <name>) { [attributes]; [methods]; }
data Class = Class
    { _className  :: Identifier
    , _variables  :: [Variable]
    , _methods    :: [Method]
    } deriving (Show, Eq)

-- public <type> <name> (<argument>) { <body> }
data Method = Method
    { _methodName      :: Identifier
    , _methodRetType   :: Type
    , _methodArguments :: [Variable]
    , _methodBody      :: [Statement]
    } deriving (Show, Eq)

Parser

5

Alexander Isenko

15.05.2017

miniJavaParser :: Parser MiniJava
miniJavaParser = MiniJava <$> mainClassP
                          <*> many usualClassP

mainClassP :: Parser Class
mainClassP = do
  symbol "class"
  id <- identifier
  (vars, main, methods) <- braces $ (,,) <$> many varDeclarationP
                                         <*> mainMethodP
                                         <*> many methodP
  return $ Class id vars (main:methods)

methodP :: Parser Method
methodP = do
  symbol "public"
  typ  <- typeP
  id   <- identifier
  vars <- parens $ variableP `sepBy` comma
  stms <- braces $ many statementP
  return $ Method id typ vars stms

AST - Interpreter

6

Alexander Isenko

15.05.2017

-- | not written yet, pseudocode

type ClassMember = Map Identifier Statement

data JavaMemory = JavaMemory
    { _printValues    :: [Type]
    , _curReturnValue :: Maybe Type
    , _classMap       :: Map Identifier ClassMember
--    ...
    }

evalMiniJava :: MiniJava -> StateT JavaMemory IO ()
evalMiniJava (MiniJava mainClass otherClasses) =
    mapM evalNormalClass otherClasses
    evalMainClass mainClass
        
evalNormalClass :: Class -> StateT JavaMemory IO ()
evalNormalClass (Class id vars methods) =
    evalVars id vars
    evalMethods methods