我目前正在使用Text.Parsec.Expr模块来解析脚本语言的子集。
基本上,这种语言有两种命令:分配形式$var = expr
和命令形式$var = $array[$index]
- 当然还有其他命令,但这足以解释我的问题
我创建了一个类型Command
来表示这个,以及相应的解析器,其中expr
用于分配由Parsec的buildExpressionParser
处理。
现在,问题。首先是解析代码:
main = case parse p "" "$c = $a[$b]" of
Left err -> putStrLn . show $ err
Right r -> putStrLn . show $ r
where p = (try assignment <|> command) <* eof -- (1)
整个代码(50行)粘贴在这里:Link(如果你安装了parsec就应该编译)
问题是,解析失败,因为assignment
无法成功解析,即使之前有try
。反转解析顺序(try command <|> assignment
)可以解决问题,但在我的情况下是不可能的。
当然我试图进一步找到问题,在我看来,问题是表达式解析器(由buildExpressionParser
构建),因为如果我说expr = fail ""
解析成功。但是我在Parsec源代码中找不到可以解释这种行为的任何内容。
答案 0 :(得分:3)
您的解析器失败,因为实际上assigment
在此处成功消耗$c = $a
(尝试使用普通where p = assignment
)。然后应该是eof
(或来自expr
的{{1}}的其余部分)因此错误。在“赋值”的参数只是assigment
(如var
)的情况下,“命令”的开始似乎与“赋值”相同。
不确定为什么你不能反转$c = $a
和command
,但另一种使这个特定例子起作用的方法是:
assignment