aboutsummaryrefslogtreecommitdiff
path: root/src/__OLD_parcom/many.cr
blob: a734c63d9626cb92faa6b8c1e462b74d2967b81a (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
34
35
36
require "./parser.cr"

module Parcom
  # `Many` is a `Parser` that repeatedly tries to parse with another parser.
  # The `Many` 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 `Many` object will stop
  # attempting to parse will will return the array of prrevious successes.
  #
  # `Many` will return an empty array if the parser never succeeds or consumes
  # input. For cases where at least one parserr success is needed, use `Some`.
  class Many(T, V) < Parser(T, Array(V))
    # Accepts the parser to use.
    def initialize(@p : Parser(T, V))
    end

    # Continuously parses with the wrapped parser, returns all successes.
    # Parsing stops when the parser fails, or succeeds without consuming input.
    def parse(tokens : Tokens(T)) : Result(T, Array(V))
      parsed = [] of V

      loop do
        result = @p.parse?(tokens)
        break unless !result.nil? && result.tokens != tokens

        parsed << result.value
        tokens = result.tokens
      end

      Result.new(tokens, parsed)
    rescue ex : ParserFail
      raise ParserFail.new("Many: #{ex.message}")
    end
  end
end