From a80ccf9a8685d308a314414551a30dc8a798cb51 Mon Sep 17 00:00:00 2001 From: Moxvallix Mox Date: Sat, 20 May 2023 21:31:54 +0930 Subject: [PATCH] feat(combinators): add the ability to ignore a combinator's output in a group --- Gemfile.lock | 6 +++--- lib/parsby.rb | 9 ++++++--- lib/parsby/combinators.rb | 5 +++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index ff34371..f6f7dd9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -17,12 +17,12 @@ GEM rspec-core (~> 3.12.0) rspec-expectations (~> 3.12.0) rspec-mocks (~> 3.12.0) - rspec-core (3.12.1) + rspec-core (3.12.2) rspec-support (~> 3.12.0) - rspec-expectations (3.12.2) + rspec-expectations (3.12.3) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) - rspec-mocks (3.12.3) + rspec-mocks (3.12.5) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) rspec-support (3.12.0) diff --git a/lib/parsby.rb b/lib/parsby.rb index 5c3fcb0..93fa349 100644 --- a/lib/parsby.rb +++ b/lib/parsby.rb @@ -105,7 +105,7 @@ def start(p) end def end(p) - Parsby.new("splicer.end(#{p.label})") { |c| + Parsby.new("splicer.end(#{p.label})", p.ignore) { |c| begin p.parse c ensure @@ -600,12 +600,14 @@ def label end attr_writer :label + attr_accessor :ignore # Initialize parser with optional label argument, and parsing block. The # parsing block is given an IO as argument, and its result is the result # when parsing. - def initialize(label = nil, &b) + def initialize(label = nil, ignore = false, &b) self.label = label if label + self.ignore = ignore @parser = b end @@ -706,7 +708,8 @@ def <<(p) x = parse c y = p.parse c # like x << y, but without modifying x. - x + [y] + # return x if it is ignored + p.ignore ? x : x + [y] end end diff --git a/lib/parsby/combinators.rb b/lib/parsby/combinators.rb index 3e94e24..28d0e47 100644 --- a/lib/parsby/combinators.rb +++ b/lib/parsby/combinators.rb @@ -21,7 +21,7 @@ def define_combinator(name, wrap: true, &b) # Lambda used to access private module method from instance method. inspectable_labels_lambda = lambda {|x| inspectable_labels(x) } - define_method name do |*args, &b2| + define_method name do |*args, ignore: false, &b2| inspected_args = inspectable_labels_lambda.call(args).map(&:inspect) label = name.to_s label += "(#{inspected_args.join(", ")})" unless inspected_args.empty? @@ -29,8 +29,9 @@ def define_combinator(name, wrap: true, &b) # label. p = m.bind(self).call(*args, &b2) if wrap - Parsby.new(label) {|c| p.parse c } + Parsby.new(label, ignore) {|c| p.parse c } else + p.ignore = ignore p % label end end