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
|