From 4732d4312a3df624c4ea3d861279ab186788979f Mon Sep 17 00:00:00 2001 From: Matthew Hall Date: Sun, 19 Mar 2023 23:21:36 +1300 Subject: sep_by, and some small tweaks --- src/parcom/parser.cr | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'src') 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 -- cgit v1.2.1