2

編集: 問題は部分的に解決されました。更新のために一番下までスキップしてください。

私は 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

エラー レポートを理解しようとしましたが、何も問題を解決できませんでした。

4

2 に答える 2

4

>>より>>=きつく締め$ます。使ってみて

return (While c t)

それ以外の

return $ While c t

また、 の右側のラムダ式を括弧で囲みます>>=

または、do 表記を使用します。

whilestmt = do
    symbol "while"
    c <- parens expr
    symbol "\n"
    symbol "{"
    t <- stmt
    symbol "}"
    return $ While c t
于 2012-10-14T14:24:22.140 に答える
0

問題は、Haskellでは、ifステートメントは常にelseに加えてを持たなければならないということthenです。execforの実装は、条件がでWhileあるときに何をするかを指定しますが、条件がTrueであるときの動作については何も述べていませんFalse。実際、コードは、条件がであるときにwhileループの本体を1回だけ実行しますが、True条件がになるまでそれを実行し続ける(そして更新を環境にスレッド化する)必要がありますFalse。だから、このようなもの:

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
于 2012-10-14T22:16:48.707 に答える