2010-10-30 126 views
2

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

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

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) 

我知道这似乎很容易,但我尝试了很多东西,只是不能得到它的工作。请帮忙。

回答

3

如果你的输出规则看起来是这样的:

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

和你输入规则看起来同样动作,除了“输入”,那么问题是,这两个规则开始与ident以来秒差距没有按不会自动回溯,它只会尝试先应用output,然后消耗ident,然后在与“输出”不匹配时失败。

为了解决这个问题,你可以只是包装outputtryinput,即

outs <- many1 (try output) 
ins <- many1 (try input) 
+0

非常感谢。这完全解决了它。我没有意识到它们都以一个ident开始,并且被输出解析器使用。 – HaskellNoob 2010-10-30 14:12:12

0

虽然sepp2k的答案的作品,我个人要封装的输出和输入解析器内的回溯。

虽然这增加了代码的解析器它使它们更加健壮:

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

凭借秒差距,其一般最好避免尝试除了字符解析器和使用左保理,提高语法(可以使解析器非常脆弱)。不幸的是,你正在工作的语法对左分解不是特别友好,在这种情况下,它可能不值得打扰。