使用haskell编写迷你语言时,会遇到“while”语句和块{}的问题

使用haskell编写迷你语言时,会遇到“while”语句和块{}的问题,haskell,mini-language,Haskell,Mini Language,编辑:问题已部分解决,请跳到底部进行更新 我正在使用haskell编写一种小型语言,我已经取得了很大的进展,但是我在实现使用块的语句时遇到了困难,比如{…}。我在解析器文件中实现了对If语句的支持,如下所示: stmt = skip +++ ifstmt +++ assignment +++ whilestmt ifstmt = symbol "if" >> parens expr >>= \c -> stmt >>

编辑:问题已部分解决,请跳到底部进行更新

我正在使用haskell编写一种小型语言,我已经取得了很大的进展,但是我在实现使用块的语句时遇到了困难,比如{…}。我在解析器文件中实现了对If语句的支持,如下所示:

stmt = skip +++ ifstmt +++ assignment +++ whilestmt

ifstmt = symbol "if" >>
         parens expr >>= \c ->
         stmt >>= \t ->
         symbol "else" >>
         stmt >>= \e ->
         return $ If c t e

whilestmt = symbol "while" >>
            parens expr >>= \c ->
        symbol "\n" >>
        symbol "{" >>
        stmt >>= \t ->
        symbol "}" >>
        return $ While c t

expr = composite +++ atomic
在语法文件中:

class PP a where 
  pp :: Int -> a -> String

instance PP Stmt where
  pp ind (If c t e) = indent ind ++ 
                      "if (" ++ show c ++ ") \n" ++ 
                      pp (ind + 2) t ++
                      indent ind ++ "else\n" ++
                      pp (ind + 2) e
  pp ind (While c t) = indent ind ++
                   "while (" ++ show c ++") \n" ++
                   "{" ++ pp (ind + 2) t ++ "}" ++
                   indent ind
while语句有问题,我不明白是什么。逻辑似乎正确,但当我运行代码时,会出现以下错误:

EDIT: Fixed the first problem based on the first reply, now it is not recognizing my while statment which I assume comes from this:
exec :: Env -> Stmt -> Env
exec env (If c t e) = 
    exec env ( if eval env c == BoolLit True then t else e )
exec env (While c t) =
    exec env ( if eval env c == BoolLit True then t )
正在读取的文件如下所示:

x = 1; c = 0;
if (x < 2) c = c + 1; else ;
-- SEPARATE FILES FOR EACH
x = 1; c = 1;
while (x < 10)
{
  c = c * x;
  x = x + 1;
}
c
exec env (While c t) = execWhile env c t

execWhile env c t | eval env c == BoolLit True = let env' = exec t in execWhile env' c t
                  | otherwise = env
我试图理解错误报告,但我没有尝试解决问题。

>和>>=绑定比$更紧。试用

return (While c t)
而不是

return $ While c t
另外,在>>=右侧的lambda表达式周围加上括号

或者只使用do符号:

whilestmt = do
    symbol "while"
    c <- parens expr
    symbol "\n"
    symbol "{"
    t <- stmt
    symbol "}"
    return $ While c t
>>和>>=绑定比$更紧。试用

return (While c t)
而不是

return $ While c t
另外,在>>=右侧的lambda表达式周围加上括号

或者只使用do符号:

whilestmt = do
    symbol "while"
    c <- parens expr
    symbol "\n"
    symbol "{"
    t <- stmt
    symbol "}"
    return $ While c t

问题是在Haskell中,if语句除了then之外,还必须有else。您的exec for While实现指定了当条件为True时要执行的操作,但没有说明当条件为False时的行为。事实上,当条件为True时,您的代码只执行while循环体一次,但它应该继续执行它,并将更新线程化到环境中,直到条件变为False为止。比如说:

x = 1; c = 0;
if (x < 2) c = c + 1; else ;
-- SEPARATE FILES FOR EACH
x = 1; c = 1;
while (x < 10)
{
  c = c * x;
  x = x + 1;
}
c
exec env (While c t) = execWhile env c t

execWhile env c t | eval env c == BoolLit True = let env' = exec t in execWhile env' c t
                  | otherwise = env

问题是在Haskell中,if语句除了then之外,还必须有else。您的exec for While实现指定了当条件为True时要执行的操作,但没有说明当条件为False时的行为。事实上,当条件为True时,您的代码只执行while循环体一次,但它应该继续执行它,并将更新线程化到环境中,直到条件变为False为止。比如说:

x = 1; c = 0;
if (x < 2) c = c + 1; else ;
-- SEPARATE FILES FOR EACH
x = 1; c = 1;
while (x < 10)
{
  c = c * x;
  x = x + 1;
}
c
exec env (While c t) = execWhile env c t

execWhile env c t | eval env c == BoolLit True = let env' = exec t in execWhile env' c t
                  | otherwise = env

哦,我只是注意到你重复了这个问题,并且已经得到了答案…哦,我只是注意到你重复了这个问题,并且已经得到了答案。。。