我需要为编程语言创建一个解析器。到目前为止,我完成了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)
我知道这似乎很容易,但我尝试了很多东西而且无法让它发挥作用。请帮忙。
答案 0 :(得分:3)
如果输出规则如下所示:
output = do name <- ident
string ":= output of"
type <- ident
char ';'
return $ Out name type
并且您的输入规则看起来相同,除了“输入”,然后问题是两个规则都以ident
开头,并且由于parsec不会自动回溯,它只会尝试应用{{1首先,消耗output
然后当它与“输出”不匹配时失败。
要解决此问题,您可以将ident
和output
包裹在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之外,通常最好避免尝试并使用左分解来改进语法(尝试可以使解析器非常脆弱)。不幸的是,你工作的语法对左分解并不是特别友好,在这种情况下它可能不值得打扰。