diff options
| author | Matthew Hall <hallmatthew314@gmail.com> | 2023-03-19 23:21:36 +1300 |
|---|---|---|
| committer | Matthew Hall <hallmatthew314@gmail.com> | 2023-03-19 23:21:36 +1300 |
| commit | 4732d4312a3df624c4ea3d861279ab186788979f (patch) | |
| tree | 31ce3ccfca9e3a0462fdf6f51cdb0b9db7c1db84 /src | |
| parent | 9734fa2d530b9496b70a388a117ea57fe5730772 (diff) | |
sep_by, and some small tweaks
Diffstat (limited to 'src')
| -rw-r--r-- | src/parcom/parser.cr | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/src/parcom/parser.cr b/src/parcom/parser.cr index d9919e1..d91ac84 100644 --- a/src/parcom/parser.cr +++ b/src/parcom/parser.cr @@ -255,7 +255,7 @@ module Parcom end # Same as `#+`, but discards the second parser's result. - def <<(p2 : Parser(T, V)) : Parser(T, U) forall V + def <<(p2 : Parser(T, _)) : Parser(T, U) p1 = self (p1 + p2).map(&.first).named("#{p1.name} << #{p2.name}") end @@ -267,7 +267,7 @@ module Parcom end # Creates a new parser from `self` that parses with `self` as many times - # as possible. If it never succeeds, returns an empty list. + # as possible. Returns an empty list if it never succeeds. def many : Parser(T, Array(U)) p = self Parser(T, Array(U)).new("Many: #{p.name}") do |tokens| @@ -371,7 +371,6 @@ module Parcom min = n < m ? n : m extra = (n - m).abs - p = self (exactly(min) + at_most(extra)).map do |t| t.first + t.last end.named("Between #{min}-#{extra} <#{@name}>") @@ -412,6 +411,17 @@ module Parcom at_least(r.begin).named("Between #{r.begin}-infinity <#{@name}> (from inifnite range)") end + + # Creates a new parser from `self` and another parser that tries to + # parse with `self` repeatedly, alternating with `sep` and discarding + # the results of `sep`. This parser will fail if it cannot parse the first + # instance of `self`. It will succeed if it can parse an instance of `self` + # that is not followed by any `sep` instances. + def sep_by(sep : Parser(T, _)) : Parser(T, Array(U)) + (self + (sep >> self).many).map do |tup| + tup.last.unshift(tup.first) + end.named("<#{@name}> sep by <#{sep.name}>") + end end end |
