blob: a2e35639c9fcab05ba0f89ca0bf4148b347aa683 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
require "./parser.cr"
require "./assert.cr"
require "./many.cr"
module Parcom
# `Some` is a `Parser` that repeatedly tries to parse with another parser.
# The `Some` object will collect all success values in an array, and
# return them with the final state of the input stream. If the wrapped
# parser ever fails or succeeds without parsing any input, the `Some`
# object will stop attempting to parse and will return the array of
# previous successes.
#
# `Some` will raise a `ParserFail` exception if the parser never succeeds
# or consumes input. For cases where parsing should allow for 0 successes,
# use `Many`.
class Some(T, V) < Parser(T, Array(V))
@p : Assert(T, Array(V))
# Accepts the parser to use.
def initialize(p : Parser(T, V))
@p = Many.new(p).assert { |arr| !arr.empty? }
end
# Continuously parses with the wrapped parser, returns all successes.
# Fails if there are no successes.
def parse(tokens : Tokens(T)) : Result(T, Array(V))
@p.parse(tokens)
rescue ex : ParserFail
raise ParserFail.new("Some: #{ex.message}")
end
end
end
|