不支持Parsec.Expr重复前缀/后缀操作符 [英] Parsec.Expr repeated Prefix/Postfix operator not supported

查看:122
本文介绍了不支持Parsec.Expr重复前缀/后缀操作符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Parsec.Expr.buildExpressionParser 的文件说:


前缀和具有相同优先级的后缀运算符只能出现
一次(例如,如果 - 前缀为否定,则不允许使用-2)。



<事实上,这是咬我的,因为我想解析的语言允许任意重复它的前缀和后缀操作符(想想C表达式就像 ** a [1] [2] )。



那么,为什么 Parsec 这个限制,我该如何工作我认为我可以将我的前缀/后缀解析器向下移动到术语解析器中,因为它们具有最高优先权。



  ** a + 1 

被解析为

 (*(*(a)))+(1)

如果我想将它解析为

  *(*((a)+(1)))

如果 buildExpressionParser 做了我想要的,我可以简单地重新排列表中的运算符。


$ b 注意请参阅在这里更好的解决方案

我通过使用 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 = [[后缀$ choice [subscr 
,dot
]
]
,[前缀$ choice [pos
,neg
]
]
]

通过这种方式, buildExprParser 仍可用于设置运算符优先级,但现在只能看到单个前缀后缀运算符在每个优先级。但是,该运算符有能力尽可能多地复制它自己的副本,并返回一个函数,使其看起来好像只有一个运算符。


The documentation for Parsec.Expr.buildExpressionParser says:

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

and indeed, this is biting me, since the language I am trying to parse allows arbitrary repetition of its prefix and postfix operators (think of a C expression like **a[1][2]).

So, why does Parsec make this restriction, and how can I work around it?

I think I can move my prefix/postfix parsers down into the term parser since they have the highest precedence.

i.e.

**a + 1

is parsed as

(*(*(a)))+(1)

but what could I have done if I wanted it to parse as

*(*((a)+(1)))

if buildExpressionParser did what I want, I could simply have rearranged the order of the operators in the table.

Note See here for a better solution

解决方案

I solved it myself by using chainl1:

prefix  p = Prefix  . chainl1 p $ return       (.)
postfix p = Postfix . chainl1 p $ return (flip (.))

These combinators use chainl1 with an op parser that always succeeds, and simply composes the functions returned by the term parser in left-to-right or right-to-left order. These can be used in the buildExprParser table; where you would have done this:

exprTable = [ [ Postfix subscr
              , Postfix dot
              ]
            , [ Prefix pos
              , Prefix neg
              ]
            ]

you now do this:

exprTable = [ [ postfix $ choice [ subscr
                                 , dot
                                 ]
              ]
            , [ prefix $ choice [ pos
                                , neg
                                ]
              ]
            ]

in this way, buildExprParser can still be used to set operator precedence, but now only sees a single Prefix or Postfix operator at each precedence. However, that operator has the ability to slurp up as many copies of itself as it can, and return a function which makes it look as if there were only a single operator.

这篇关于不支持Parsec.Expr重复前缀/后缀操作符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆