如何在 Scala 的解析器组合器中指定重复范围?

How to specify a range of repetitions in Scala's parser combinators?

Scala 的解析器组合器允许将某些重复指定为 0 次或多次 (.*)、1 次或多次 (.+) 等。是否可以指定范围?例如,rep(p, q)(parser) 其中解析器是 运行 至少 p 次,最多 q 次。

Scala 的解析器组合器中的组合器操作大致仿照 Regular Expressions。正则表达式只有三个组合器操作:

给定两个正则表达式 RS

  • RS 是正则表达式(串联
  • R | S 是一个正则表达式 (Alternation)
  • R* 是正则表达式 (Kleene Star)

就是这样。 Scala 添加了更多,最显着的是 +? 但这实际上并没有增加功率,因为​​ R+ 实际上只是 RR*R? 只是R | ε。这同样适用于您提出的 rep 组合器。它实际上并没有增加功率,因为​​

R{m, n}

实际上只是

RRRRRRRRRRR(ε | R | RR | RRR | RRRR | RRRRR | RRRRRR | RRRRRRR | RRRRRRRR | RRRRRRRRR)
 ↑↑ m×R ↑↑                                                                ↑↑ (m-n)×R ↑↑

现在,当然,虽然这不会增加解析器的能力,但它确实增加了表现力,从而增加了可读性和可维护性。

我相信,在 |repN 之上构建它会非常容易。

类似于:

/** A parser generator for a number of repetitions within a range.
 *
 *  `repMN(m, n, p)` uses `p` between `m` and `n` time to parse the input
 *  (the result is a `List` of the consecutive results of `p`).
 *
 * @param p   a `Parser` that is to be applied successively to the input
 * @param min the minimum number of times `p` must succeed
 * @param max the maximum number of times `p` must succeed
 * @return    A parser that returns a list of results produced by repeatedly applying `p` to the input
 *        (and that only succeeds if `p` matches between `m` and `n` times).
 */
def repMN[T](min: Int, max: Int, p: ⇒ Parser[T]) = 
  (min to max).reverse map { repN(_, p) } reduce {_ | _}

这看起来很有用,甚至可以作为增强请求提交。