看起来您有两种不同的输入:声明(创建新变量和函数)和表达式(计算事物)。
你应该首先定义一些数据结构,这样你就可以计算出你将要处理什么样的事情。就像是:
data Command = Define Definition | Calculate Expression | Quit
type Name = String
data Definition = DefVar Name Expression | DefFunc Name [Name] Expression
-- ^ alternatively, implement variables as zero-argument functions
-- and merge these cases
data Expression = Var Name | Add Expression Expression | -- ... other stuff
type Environment = [Definition]
首先,只需将内容解析(标记化然后解析标记)到 aCommand
中,然后决定如何处理它。
表达比较容易。您假设您已经拥有所需的所有定义(an Environment
),然后只需查找任何变量或进行添加或其他任何操作。
定义有点棘手。一旦决定了要创建什么新定义,就需要将其添加到环境中。你如何做到这一点取决于你如何准确地遍历这些行,但是你需要将新环境从解释器传递回获取下一行并在其上运行解释器的东西。就像是:
main :: IO ()
main = mainLoop emptyEnv
where
emptyEnv = []
mainLoop :: Environment -> IO ()
mainLoop env = do
str <- getLine
case parseCommnad str of
Nothing -> do
putStrLn "parse failed!"
mainLoop env
Just Quit -> do
return ()
Just (Define d) -> do
mainLoop (d : env)
Just (Calculate e) -> do
putStrLn (calc env e)
mainLoop env
-- the real meat:
parseCommand :: String -> Maybe Command
calc :: Environment -> Expression -> String -- or Integer or some other appropriate type
calc
将需要在您创建的环境中查找内容,因此您可能还需要一个函数来查找Definition
对应于给定的Name
(或抱怨没有)。
您应该做出的其他一些决定:
- 当有人试图重新定义变量时我该怎么办?
- 如果我在函数定义中使用这些变量之一怎么办?我是否在创建或使用函数定义时对其进行评估?
这些问题可能会影响上述程序的设计,但我会留给你如何解决。