aboutsummaryrefslogtreecommitdiff
path: root/src/__OLD_parcom/some.cr
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