如何在 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。正则表达式只有三个组合器操作:
给定两个正则表达式 R
和 S
,
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 {_ | _}
这看起来很有用,甚至可以作为增强请求提交。
Scala 的解析器组合器允许将某些重复指定为 0 次或多次 (.*
)、1 次或多次 (.+
) 等。是否可以指定范围?例如,rep(p, q)(parser)
其中解析器是 运行 至少 p
次,最多 q
次。
Scala 的解析器组合器中的组合器操作大致仿照 Regular Expressions。正则表达式只有三个组合器操作:
给定两个正则表达式 R
和 S
,
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 {_ | _}
这看起来很有用,甚至可以作为增强请求提交。