Text.Parsec 许多解析器不会完全解析自定义解析器

Mr.*_*oom 5 parsing haskell eval

我有一个问题,我的 if 块(和 Do-While 块,因为问题是相同的)的解析器不会在解析字符串“fi”时终止。If-Block 采用以下形式:

if P -> p
[] Q -> q
fi
Run Code Online (Sandbox Code Playgroud)

如果我使用Text.Parsec的字符串解析器来解析,"fi"就像我使用它来解析"if"甚至进入循环一样,程序会停止。当我打印出应该评估的内容时,它甚至不存在,因此程序在以"fi".

"fi"然而,当我删除解析的解析器时,发生的情况是程序可以运行并且 If-Block 的评估符合预期,但我必须以与块"fi"中表达式相同数量(或任何字符串)的数量结束块本身。如果我没有以相同数量的"fi"'s结束块,那么在无限评估块之后的任何语句都会发生什么。例如,如果变量为偶数,则向运行总数加 1 的块将如下所示:

if ((x mod 2) = 0)-> r := r + 1
[] ((x mod 2) = 1)-> r := r + 0
fi
fi
Run Code Online (Sandbox Code Playgroud)

如果有一个"fi",并且我在块之后打印了 r 的值,它将无限打印 r

if ((x mod 2) = 0)-> r := r + 1
[] ((x mod 2) = 1)-> r := r + 0
fi

print(r)

./Main prog
1
1
1
1
1
...
Run Code Online (Sandbox Code Playgroud)

问题可能是对该spaces函数的误用,但即使我删除了所有空格实例,使所有内容都在连接在一起的一行上,我似乎也无法正确解析。即使我这样做,它也不会"fi"在解析器代码中接受,但如果它在删除时与表达式相同,它将接受它。

parseIf :: Parser HStatement
parseIf = do
        try (string "if") <|> try (string "[]")
        spaces
        string "("
        cond  <- parseVals
        string ")->"
        spaces
        expr  <- many1 $ parseStatements
        spaces
        return $ If (cond, expr)


parseSelection :: Parser HStatement
parseSelection = do
        selection <- many1 parseIf
        spaces
        --try (string "fi")
        return $ Selection selection

parseStatements :: Parser HStatement
parseStatements = try (parseDo) <* spaces <|> try (parseSelection) <|> try (parsePrint) <|> try (parseEvalHVal)
Run Code Online (Sandbox Code Playgroud)