diff --git a/spec/ast_spec.cr b/spec/ast_spec.cr index 2b52183..1332818 100644 --- a/spec/ast_spec.cr +++ b/spec/ast_spec.cr @@ -36,4 +36,21 @@ describe Pegasus::ParseTree do res = parser.parse("abcdef") res.parse_tree.dump.should eq(expected_parse_tree.dump) end + + it "ignores ignored nodes while still matching" do + parser = Pegasus::Parser.define do |p| + p.rule(:def) { |p| p.str("def") } + p.rule(:abcdef) { |p| p.rule(:abc).aka(:a2c) >> p.rule(:def).ignore } + p.rule(:abc) { |p| p.str("abc") } + + p.root(:abcdef) + end + + expected_parse_tree = Pegasus::Branch(String).new(:seq).tap do |tree| + tree << Pegasus::Leaf.new(:a2c, "abc") + end + + res = parser.parse("abcdef") + res.parse_tree.dump.should eq(expected_parse_tree.dump) + end end diff --git a/src/pegasus/ast.cr b/src/pegasus/ast.cr index 28f85b4..7816a77 100644 --- a/src/pegasus/ast.cr +++ b/src/pegasus/ast.cr @@ -17,6 +17,10 @@ module Pegasus to_json end + def prune + self + end + JSON.mapping( label: Symbol, item: T @@ -46,6 +50,14 @@ module Pegasus to_json end + def prune + Branch(T).new(@label).tap do |branch| + @children.each do |child| + branch << child if child.label != :ignore + end + end + end + JSON.mapping( label: Symbol, children: Array(Branch(T) | Leaf(T)) diff --git a/src/pegasus/extensions/ignored.cr b/src/pegasus/extensions/ignored.cr index 1ae8dc1..8e6c0e0 100644 --- a/src/pegasus/extensions/ignored.cr +++ b/src/pegasus/extensions/ignored.cr @@ -9,7 +9,11 @@ module Pegasus old_context = context.dup match, _ = @rule.match?(context) - {match, old_context} + if match.success? + {MatchResult.success(Leaf.new(@label, match.parse_tree.value)), old_context} + else + {MatchResult.failure(Leaf.new(@label, match.parse_tree.value)), old_context} + end end def flatten diff --git a/src/pegasus/match_result.cr b/src/pegasus/match_result.cr index 4e6ca69..6830470 100644 --- a/src/pegasus/match_result.cr +++ b/src/pegasus/match_result.cr @@ -3,6 +3,7 @@ module Pegasus getter :parse_tree def initialize(@result : Bool, @parse_tree : Pegasus::ParseTree) + @parse_tree = parse_tree.prune end def self.success(tree : Pegasus::ParseTree)