Ответ 1
Я решил это сам, используя chainl1
:
prefix p = Prefix . chainl1 p $ return (.)
postfix p = Postfix . chainl1 p $ return (flip (.))
Эти комбинаторы используют chainl1
с парсером op
, который всегда преуспевает, и просто составляет функции, возвращаемые парсером term
в порядке слева направо или справа налево. Они могут использоваться в таблице buildExprParser
; где вы бы это сделали:
exprTable = [ [ Postfix subscr
, Postfix dot
]
, [ Prefix pos
, Prefix neg
]
]
сделайте следующее:
exprTable = [ [ postfix $ choice [ subscr
, dot
]
]
, [ prefix $ choice [ pos
, neg
]
]
]
таким образом, buildExprParser
все еще может использоваться для установки приоритета оператора, но теперь он видит только один оператор Prefix
или Postfix
при каждом приоритете. Тем не менее, этот оператор имеет возможность размножать столько копий, сколько может, и возвращать функцию, которая заставляет ее выглядеть так, как если бы был только один оператор.