Warn on shift/reduce conflicts
This commit is contained in:
parent
69cc8fa67d
commit
4ae5ab79b3
@ -669,7 +669,7 @@ typedef struct
|
|||||||
/** Parser shift table. */
|
/** Parser shift table. */
|
||||||
static const shift_t parser_shift_table[] = {
|
static const shift_t parser_shift_table[] = {
|
||||||
<% @parser.shift_table.each do |shift| %>
|
<% @parser.shift_table.each do |shift| %>
|
||||||
{<%= shift[:symbol_id] %>u, <%= shift[:state_id] %>u},
|
{<%= shift[:symbol].id %>u, <%= shift[:state_id] %>u},
|
||||||
<% end %>
|
<% end %>
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -817,7 +817,7 @@ private struct state_value_t
|
|||||||
/** Parser shift table. */
|
/** Parser shift table. */
|
||||||
private immutable shift_t[] parser_shift_table = [
|
private immutable shift_t[] parser_shift_table = [
|
||||||
<% @parser.shift_table.each do |shift| %>
|
<% @parser.shift_table.each do |shift| %>
|
||||||
shift_t(<%= shift[:symbol_id] %>u, <%= shift[:state_id] %>u),
|
shift_t(<%= shift[:symbol].id %>u, <%= shift[:state_id] %>u),
|
||||||
<% end %>
|
<% end %>
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ class Propane
|
|||||||
@log = log
|
@log = log
|
||||||
@item_sets = []
|
@item_sets = []
|
||||||
@item_sets_set = {}
|
@item_sets_set = {}
|
||||||
|
@sr_conflicts = Set.new
|
||||||
start_item = Item.new(grammar.rules.first, 0)
|
start_item = Item.new(grammar.rules.first, 0)
|
||||||
eval_item_sets = Set[ItemSet.new([start_item])]
|
eval_item_sets = Set[ItemSet.new([start_item])]
|
||||||
|
|
||||||
@ -38,8 +39,8 @@ class Propane
|
|||||||
|
|
||||||
build_reduce_actions!
|
build_reduce_actions!
|
||||||
build_follow_sets!
|
build_follow_sets!
|
||||||
write_log!
|
|
||||||
build_tables!
|
build_tables!
|
||||||
|
write_log!
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -57,10 +58,17 @@ class Propane
|
|||||||
item_set.next_item_set[next_symbol].id
|
item_set.next_item_set[next_symbol].id
|
||||||
end
|
end
|
||||||
{
|
{
|
||||||
symbol_id: next_symbol.id,
|
symbol: next_symbol,
|
||||||
state_id: state_id,
|
state_id: state_id,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
if item_set.reduce_actions
|
||||||
|
shift_entries.each do |shift_entry|
|
||||||
|
if item_set.reduce_actions.include?(shift_entry[:symbol])
|
||||||
|
@sr_conflicts << [shift_entry[:symbol], item_set.reduce_actions[shift_entry[:symbol]]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
reduce_entries =
|
reduce_entries =
|
||||||
if rule = item_set.reduce_rule
|
if rule = item_set.reduce_rule
|
||||||
[{token_id: @grammar.invalid_token_id, rule_id: rule.id, rule: rule,
|
[{token_id: @grammar.invalid_token_id, rule_id: rule.id, rule: rule,
|
||||||
@ -310,6 +318,13 @@ class Propane
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if @sr_conflicts.size > 0
|
||||||
|
@log.puts
|
||||||
|
@log.puts "Shift/Reduce Conflicts:"
|
||||||
|
@sr_conflicts.each do |sr_conflict|
|
||||||
|
@log.puts " Shift/Reduce conflict between #{sr_conflict[0].name} and #{sr_conflict[1].name}"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -184,6 +184,20 @@ EOF
|
|||||||
expect(results.status).to_not eq 0
|
expect(results.status).to_not eq 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "warns on shift/reduce conflicts" do
|
||||||
|
write_grammar <<EOF
|
||||||
|
token a;
|
||||||
|
token b;
|
||||||
|
Start -> As? b?;
|
||||||
|
As -> a As2?;
|
||||||
|
As2 -> b a As2?;
|
||||||
|
EOF
|
||||||
|
results = run_propane(capture: true)
|
||||||
|
expect(results.stderr).to eq ""
|
||||||
|
expect(results.status).to eq 0
|
||||||
|
expect(File.binread("spec/run/testparser.log")).to match %r{Shift/Reduce conflict between b and As2}
|
||||||
|
end
|
||||||
|
|
||||||
%w[d c].each do |language|
|
%w[d c].each do |language|
|
||||||
|
|
||||||
context "#{language.upcase} language" do
|
context "#{language.upcase} language" do
|
||||||
|
Loading…
x
Reference in New Issue
Block a user