微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 Megaparsec 解析时的运算符优先级问题

如何解决使用 Megaparsec 解析时的运算符优先级问题

我正在用数组和结构解析类似 C 的语言。在 C 运算符优先级之后,.[] 具有相同的优先级。

opTable :: [[Operator Parser Expr]]
opTable = [[ InfixL $ Access <$ symbol ".",opSubscript]]

opSubscript = Postfix $ foldr1 (.) <$> some singleIndex
singleIndex = do
    index < brackets expr
    return $ \l -> ArrayIndex l index

解析时

Struct S {
  int[3] a;
}
Struct S s;
s.a[1]

它产生了 Access (Var "s") (ArrayIndex (Var "a") 1) 代替 ArrayIndex (Access (Var "s") (Var "a")) 1 为什么?是不是因为 [] 没有被解析为 InfixL?

更新: 在changing之后

opTable :: [[Operator Parser Expr]]
opTable = [[ PostFix $ (\ident expr -> Access expr ident) <$ symbol "." <*> identifier,opSubscript]]

我又犯了一个错误

s.a[1]
|  ^
unexpected '['
expecting ')','_',alphanumeric character,or operator

解决方法

来自 makeExprParserparser-combinators 文档在前缀和后缀运算符方面很糟糕。

首先,它无法解释在假定的“相同”优先级上混合使用前缀/后缀/中缀运算符,前缀/后缀运算符总是被视为比中缀运算符更高的优先级。

其次,当它声称“相同优先级的前缀和后缀运算符只能出现一次”,然后以--2作为前缀运算符-的例子时,实际上意味着即使不允许使用两个 separate 前缀运算符(或两个 separate 后缀运算符),因此 +-2 带有单独的前缀运算符 + 和 {{1} } 也不允许。 允许的是单个前缀运算符和单个后缀运算符,在同一级别,在这种情况下,关联在左侧,因此 - 是可以的(假设 {{1} } 和 -2! 是具有相同优先级的前缀和后缀运算符)并被解析为 -

哦,第三,文档从未明确说明 ! 的示例代码仅适用于多个前缀运算符,并且需要进行不明显的更改才能以正确的顺序获得多个后缀运算符。

因此,您的第一次尝试不起作用,因为后缀运算符的优先级秘密高于中缀运算符。您的第二次尝试不起作用,因为无法解析具有相同优先级的两个不同的后缀运算符。

最好的办法是解析由访问和索引操作链组成的单个“后缀运算符”。请注意需要 (-2)! 才能获得后缀运算符的正确排序。

manyUnaryOp

一个独立的例子:

flip

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。