Parsec解析了很多问题

时间:2010-10-30 12:50:27

标签: parsing haskell parsec

我需要为编程语言创建一个解析器。到目前为止,我完成了95%,除了一个小细节。

用这种语言编写的程序具有以下结构:

outputs
inputs
expressions

要求是输出不能与输入混合。例如:

x := output of int;
y := output of in;
.....
z := input of int;
t := input of in;
.....
expressions

我可以解析单个输出就好但如果我尝试使用(many1输出),允许多个输出,它不起作用,因为它试图将输入解析为输出。

我的主解析器如下所示:

prog =
    do outs <- many1 output
       ins <- many1 input
       exs <- expressions
       eof
       return (Prog outs ins exs) 

我知道这似乎很容易,但我尝试了很多东西而且无法让它发挥作用。请帮忙。

2 个答案:

答案 0 :(得分:3)

如果输出规则如下所示:

output = do name <- ident
            string ":= output of"
            type <- ident
            char ';'
            return $ Out name type

并且您的输入规则看起来相同,除了“输入”,然后问题是两个规则都以ident开头,并且由于parsec不会自动回溯,它只会尝试应用{{1首先,消耗output然后当它与“输出”不匹配时失败。

要解决此问题,您可以将identoutput包裹在input中,即

try

答案 1 :(得分:0)

虽然sepp2k的答案有效,但我个人希望将回溯封装在输出和输入解析器中。

虽然这会为解析器添加代码,但它会使代码更加健壮:

output = do name <- try prefix
            type <- ident
            char ';'
            return $ Out name type
  where
    prefix = do name <- ident
                string ":= output of"
                return name

使用Parsec时,除了Char Parsers之外,通常最好避免尝试并使用左分解来改进语法(尝试可以使解析器非常脆弱)。不幸的是,你工作的语法对左分解并不是特别友好,在这种情况下它可能不值得打扰。