所以我正在创建自己的原始shell语言解析器,我想我会创建我的命令(例如cd)表达式,这样我就可以留出一些空间让它们返回值。
现在我已经制作了某种解析器,并且在我的声明消费者中有一个裸露的表达式。
我希望你能为我提供完整的代码。这是有问题的部分:
-- it has other patterns...
makeStatement :: Statement -> VarTable -> Maybe VarTable
makeStatement (Exp exp) vt = ???
makeStatement (If ..........
...
data Expression = Val Int
| Booly Bool
| Var String
| Cmd String [String]
deriving (Show)
data Statement = Assignment String Expression
| If Expression Statement
| IfElse Expression Statement Statement
| Exp Expression
deriving (Show)
eval :: VarTable -> Expression -> Maybe Int
所以我想强制执行exp,以防它是Cmd
但返回它开始时的相同vt。
答案 0 :(得分:4)
首先,您可能需要一些复合类型来表示表达式可以返回的三种可能类型。 像
这样的东西data Value = Number Int | Boolean Bool | String String | Unit
Unit
表示不返回任何内容的表达式。
现在,由于表达式中的某些可能会产生副作用,因此您肯定必须将所有内容包装到IO中。有没有纯表达式并不重要,因为编译器不知道哪一个是。
eval :: VarTable -> Expression -> IO Value
现在,您的makeStatement
(类似于runStatement
可能是一个更好的名字)看起来像这样
makeStatement :: Statement -> VarTable -> IO VarTable
makeStatement (Exp exp) vt = eval exp >> return vt
makeStatement (If cond th) vt = do
c <- eval cond
case c of
Boolean True -> makeStatement th vt
_ -> return vt --maybe handle the case where c isn't even Boolean
...
通过此设置,您可以看到我们可以做我猜想你想要的事情。 eval
表达式,然后丢弃它的结果,只返回VarTable
不变。