2

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

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

outputs
inputs
expressions

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

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

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

我的主要解析器如下所示:

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

我知道这看起来很容易,但我尝试了很多东西,但无法让它发挥作用。请帮忙。

4

2 回答 2

3

如果您的输出规则如下所示:

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

并且您的输入规则看起来相同,除了“输入”,那么问题是这两个规则都以 an 开头,ident并且由于 parsec 不会自动回溯,它只会尝试先应用output,使用ident然后失败时可以' t 匹配“输出”。

要解决这个问题,你可以只换行outputinputin try,即

outs <- many1 (try output)
ins <- many1 (try input)
于 2010-10-30T12:59:15.200 回答
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,通常最好避免尝试,除了字符解析器并使用左分解来改进语法(尝试会使解析器非常脆弱)。不幸的是,您正在使用的语法对左分解不是特别友好,在这种情况下可能不值得打扰。

于 2010-10-30T16:50:41.297 回答