Вопрос по haskell, parsec – Parsec.Expr повторный оператор префикса / постфикса не поддерживается

14

Документация дляParsec.Expr.buildExpressionParser говорит:

Prefix and postfix operators of the same precedence can only occur once (i.e. --2 is not allowed if - is prefix negate).

и действительно, это кусает меня, так как язык, который я пытаюсь разобрать, позволяет произвольное повторение его префиксных и постфиксных операторов (вспомните выражение C, например**a[1][2]).

Итак, почемуParsec сделать это ограничение, и как я могу обойти это?

Я думаю, что я могу переместить мои префиксные / постфиксные парсеры вниз вterm синтаксический анализатор, так как они имеют самый высокий приоритет.

то есть

<code>**a + 1
</code>

анализируется как

<code>(*(*(a)))+(1)
</code>

но что бы я мог сделать, если бы захотел разобрать как

<code>*(*((a)+(1)))
</code>

еслиbuildExpressionParser сделал то, что я хочу, я мог бы просто изменить порядок операторов в таблице.

Note УвидетьВот для лучшего решения

Ваш Ответ

1   ответ
14

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 оператор на каждом предшествующем. Тем не менее, этот оператор имеет возможность набирать как можно больше копий и возвращать функцию, которая заставляет его выглядеть так, как если бы был только один оператор.

Спасибо за полезный ответ. У меня возникли некоторые трудности с обобщением этой проблемы. Если у вас есть какие-либо предложения, они будут очень рады (см.stackoverflow.com/questions/33214163/…)
Я нашел ваш ответ чрезвычайно полезным, но я столкнулся с другой проблемой, подробноhereи я был бы признателен, если бы вы посмотрели, если у вас есть шанс найти решение.

Похожие вопросы