Show line numbers of rules upon conflict - close #23

This commit is contained in:
Josh Holtrop 2024-07-14 20:52:52 -04:00
parent 2dd89445fc
commit 3aced70356
2 changed files with 9 additions and 7 deletions

View File

@ -68,8 +68,10 @@ class Propane
end end
if item_set.reduce_actions if item_set.reduce_actions
shift_entries.each do |shift_entry| shift_entries.each do |shift_entry|
if item_set.reduce_actions.include?(shift_entry[:symbol]) token = shift_entry[:symbol]
@warnings << "Shift/Reduce conflict between token #{shift_entry[:symbol].name} and rule #{item_set.reduce_actions[shift_entry[:symbol]].name}" if item_set.reduce_actions.include?(token)
rule = item_set.reduce_actions[token]
@warnings << "Shift/Reduce conflict (state #{item_set.id}) between token #{token.name} and rule #{rule.name} (defined on line #{rule.line_number})"
end end
end end
end end
@ -163,7 +165,7 @@ class Propane
lookahead_tokens_for_rule = build_lookahead_tokens_to_reduce(reduce_rule, item_sets) lookahead_tokens_for_rule = build_lookahead_tokens_to_reduce(reduce_rule, item_sets)
lookahead_tokens_for_rule.each do |lookahead_token| lookahead_tokens_for_rule.each do |lookahead_token|
if existing_reduce_rule = reduce_actions[lookahead_token] if existing_reduce_rule = reduce_actions[lookahead_token]
raise Error.new("Error: reduce/reduce conflict between rule #{existing_reduce_rule.id} (#{existing_reduce_rule.name}) and rule #{reduce_rule.id} (#{reduce_rule.name})") raise Error.new("Error: reduce/reduce conflict (state #{item_set.id}) between rule #{existing_reduce_rule.name}##{existing_reduce_rule.id} (defined on line #{existing_reduce_rule.line_number}) and rule #{reduce_rule.name}##{reduce_rule.id} (defined on line #{reduce_rule.line_number})")
end end
reduce_actions[lookahead_token] = reduce_rule reduce_actions[lookahead_token] = reduce_rule
end end

View File

@ -196,7 +196,7 @@ EOF
results = run_propane(capture: true) results = run_propane(capture: true)
expect(results.stderr).to eq "" expect(results.stderr).to eq ""
expect(results.status).to eq 0 expect(results.status).to eq 0
expect(File.binread("spec/run/testparser.log")).to match %r{Shift/Reduce conflict between token b and rule As2} expect(File.binread("spec/run/testparser.log")).to match %r{Shift/Reduce conflict \(state \d+\) between token b and rule As2\? \(defined on line 4\)}
end end
it "errors on shift/reduce conflicts with -w" do it "errors on shift/reduce conflicts with -w" do
@ -208,9 +208,9 @@ As -> a As2?;
As2 -> b a As2?; As2 -> b a As2?;
EOF EOF
results = run_propane(extra_args: %w[-w], capture: true) results = run_propane(extra_args: %w[-w], capture: true)
expect(results.stderr).to match %r{Fatal errors \(-w\).*Shift/Reduce conflict between token b and rule As2}m expect(results.stderr).to match %r{Shift/Reduce conflict \(state \d+\) between token b and rule As2\? \(defined on line 4\)}m
expect(results.status).to_not eq 0 expect(results.status).to_not eq 0
expect(File.binread("spec/run/testparser.log")).to match %r{Shift/Reduce conflict between token b and rule As2} expect(File.binread("spec/run/testparser.log")).to match %r{Shift/Reduce conflict \(state \d+\) between token b and rule As2\? \(defined on line 4\)}
end end
%w[d c].each do |language| %w[d c].each do |language|
@ -652,7 +652,7 @@ F -> e;
EOF EOF
results = run_propane(capture: true, language: language) results = run_propane(capture: true, language: language)
expect(results.status).to_not eq 0 expect(results.status).to_not eq 0
expect(results.stderr).to match %r{reduce/reduce conflict.*\(E\).*\(F\)} expect(results.stderr).to match %r{Error: reduce/reduce conflict \(state \d+\) between rule E#\d+ \(defined on line 10\) and rule F#\d+ \(defined on line 11\)}
end end
it "provides matched text to user code blocks" do it "provides matched text to user code blocks" do