文档Parsec.Expr.buildExpressionParser
说:
相同优先级的前缀和后缀运算符只能出现一次(如果 - 是前缀否定,则不允许--2).
事实上,这是咬我的,因为我试图解析的语言允许任意重复它的前缀和后缀运算符(想想像C表达式**a[1][2]
).
那么,为什么要Parsec
制定这个限制,我该如何解决呢?
我想我可以将我的前缀/后缀解析器移到term
解析器中,因为它们具有最高优先级.
即
**a + 1
Run Code Online (Sandbox Code Playgroud)
被解析为
(*(*(a)))+(1)
Run Code Online (Sandbox Code Playgroud)
但是如果我想要解析它,我该怎么办?
*(*((a)+(1)))
Run Code Online (Sandbox Code Playgroud)
如果buildExpressionParser
做了我想要的,我可以简单地重新排列表中运算符的顺序.
注意请参阅此处以获得更好的解决方
pat*_*pat 15
我通过使用chainl1
以下方式自行解决:
prefix p = Prefix . chainl1 p $ return (.)
postfix p = Postfix . chainl1 p $ return (flip (.))
Run Code Online (Sandbox Code Playgroud)
这些组合器使用始终成功chainl1
的op
解析器,并简单地term
以从左到右或从右到左的顺序组成解析器返回的函数.这些可以在buildExprParser
表中使用; 你会在哪里做到这一点:
exprTable = [ [ Postfix subscr
, Postfix dot
]
, [ Prefix pos
, Prefix neg
]
]
Run Code Online (Sandbox Code Playgroud)
你现在这样做:
exprTable = [ [ postfix $ choice [ subscr
, dot
]
]
, [ prefix $ choice [ pos
, neg
]
]
]
Run Code Online (Sandbox Code Playgroud)
通过这种方式,buildExprParser
仍然可以用于设置运算符优先级,但现在每个优先级只能看到一个Prefix
或Postfix
运算符.但是,该运算符能够尽可能多地填充自身的副本,并返回一个函数,使其看起来好像只有一个运算符.
归档时间: |
|
查看次数: |
888 次 |
最近记录: |