Fix conflation of finished items w/ different precedence
This commit is contained in:
parent
84fe01e145
commit
1983bcfb60
16 changed files with 19073 additions and 18250 deletions
|
|
@ -35,28 +35,32 @@ describe("item_set_closure", []() {
|
|||
}),
|
||||
}, {}, {}};
|
||||
|
||||
auto production = [&](int variable_index, int production_index) -> const Production & {
|
||||
return grammar.variables[variable_index].productions[production_index];
|
||||
};
|
||||
|
||||
ParseItemSet item_set = item_set_closure(ParseItemSet({
|
||||
{
|
||||
ParseItem(Symbol(0), 0, 0, 100),
|
||||
ParseItem(Symbol(0), production(0, 0), 0),
|
||||
LookaheadSet({ Symbol(10, true) }),
|
||||
}
|
||||
}), grammar);
|
||||
|
||||
AssertThat(item_set, Equals(ParseItemSet({
|
||||
{
|
||||
ParseItem(Symbol(0), 0, 0, 100),
|
||||
ParseItem(Symbol(0), production(0, 0), 0),
|
||||
LookaheadSet({ Symbol(10, true) })
|
||||
},
|
||||
{
|
||||
ParseItem(Symbol(1), 0, 0, 102),
|
||||
ParseItem(Symbol(1), production(1, 0), 0),
|
||||
LookaheadSet({ Symbol(11, true) })
|
||||
},
|
||||
{
|
||||
ParseItem(Symbol(1), 1, 0, 104),
|
||||
ParseItem(Symbol(1), production(1, 1), 0),
|
||||
LookaheadSet({ Symbol(11, true) })
|
||||
},
|
||||
{
|
||||
ParseItem(Symbol(2), 0, 0, 105),
|
||||
ParseItem(Symbol(2), production(2, 0), 0),
|
||||
LookaheadSet({ Symbol(11, true) })
|
||||
},
|
||||
})));
|
||||
|
|
@ -79,24 +83,28 @@ describe("item_set_closure", []() {
|
|||
}),
|
||||
}, {}, {}};
|
||||
|
||||
auto production = [&](int variable_index, int production_index) -> const Production & {
|
||||
return grammar.variables[variable_index].productions[production_index];
|
||||
};
|
||||
|
||||
ParseItemSet item_set = item_set_closure(ParseItemSet({
|
||||
{
|
||||
ParseItem(Symbol(0), 0, 0, 100),
|
||||
ParseItem(Symbol(0), production(0, 0), 0),
|
||||
LookaheadSet({ Symbol(10, true) }),
|
||||
}
|
||||
}), grammar);
|
||||
|
||||
AssertThat(item_set, Equals(ParseItemSet({
|
||||
{
|
||||
ParseItem(Symbol(0), 0, 0, 100),
|
||||
ParseItem(Symbol(0), production(0, 0), 0),
|
||||
LookaheadSet({ Symbol(10, true) })
|
||||
},
|
||||
{
|
||||
ParseItem(Symbol(1), 0, 0, 102),
|
||||
ParseItem(Symbol(1), production(1, 0), 0),
|
||||
LookaheadSet({ Symbol(11, true) })
|
||||
},
|
||||
{
|
||||
ParseItem(Symbol(1), 1, 0, 0),
|
||||
ParseItem(Symbol(1), production(1, 1), 0),
|
||||
LookaheadSet({ Symbol(11, true) })
|
||||
},
|
||||
})));
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ describe("ParseConflictManager", []() {
|
|||
delete conflict_manager;
|
||||
});
|
||||
|
||||
const Production &production = syntax_grammar.variables[0].productions[0];
|
||||
|
||||
describe(".resolve", [&]() {
|
||||
describe("errors", [&]() {
|
||||
ParseAction error = ParseAction::Error();
|
||||
|
|
@ -65,7 +67,7 @@ describe("ParseConflictManager", []() {
|
|||
describe("shift/reduce conflicts", [&]() {
|
||||
describe("when the shift has higher precedence", [&]() {
|
||||
ParseAction shift = ParseAction::Shift(2, {3, 4});
|
||||
ParseAction reduce = ParseAction::Reduce(sym2, 1, 2, AssociativityLeft, 0);
|
||||
ParseAction reduce = ParseAction::Reduce(sym2, 1, 2, AssociativityLeft, production);
|
||||
|
||||
it("favors the shift and reports the conflict as resolved", [&]() {
|
||||
result = conflict_manager->resolve(shift, reduce, sym1);
|
||||
|
|
@ -80,7 +82,7 @@ describe("ParseConflictManager", []() {
|
|||
|
||||
describe("when the reduce has higher precedence", [&]() {
|
||||
ParseAction shift = ParseAction::Shift(2, {1, 2});
|
||||
ParseAction reduce = ParseAction::Reduce(sym2, 1, 3, AssociativityLeft, 0);
|
||||
ParseAction reduce = ParseAction::Reduce(sym2, 1, 3, AssociativityLeft, production);
|
||||
|
||||
it("favors the reduce and reports the conflict as resolved", [&]() {
|
||||
result = conflict_manager->resolve(shift, reduce, sym1);
|
||||
|
|
@ -95,7 +97,7 @@ describe("ParseConflictManager", []() {
|
|||
|
||||
describe("when the precedences are equal and the reduce's rule is left associative", [&]() {
|
||||
ParseAction shift = ParseAction::Shift(2, { 0, 0 });
|
||||
ParseAction reduce = ParseAction::Reduce(sym2, 1, 0, AssociativityLeft, 0);
|
||||
ParseAction reduce = ParseAction::Reduce(sym2, 1, 0, AssociativityLeft, production);
|
||||
|
||||
it("favors the reduce and reports the conflict as resolved", [&]() {
|
||||
result = conflict_manager->resolve(reduce, shift, sym1);
|
||||
|
|
@ -110,7 +112,7 @@ describe("ParseConflictManager", []() {
|
|||
|
||||
describe("when the precedences are equal and the reduce's rule is right-associative", [&]() {
|
||||
ParseAction shift = ParseAction::Shift(2, { 0, 0 });
|
||||
ParseAction reduce = ParseAction::Reduce(sym2, 1, 0, AssociativityRight, 0);
|
||||
ParseAction reduce = ParseAction::Reduce(sym2, 1, 0, AssociativityRight, production);
|
||||
|
||||
it("favors the shift, and reports the conflict as resolved", [&]() {
|
||||
result = conflict_manager->resolve(reduce, shift, sym1);
|
||||
|
|
@ -126,7 +128,7 @@ describe("ParseConflictManager", []() {
|
|||
describe("when the precedences are equal and the reduce's rule has no associativity", [&]() {
|
||||
it("reports an unresolved conflict", [&]() {
|
||||
ParseAction shift = ParseAction::Shift(2, { 0, 0 });
|
||||
ParseAction reduce = ParseAction::Reduce(Symbol(2), 1, 0, AssociativityNone, 0);
|
||||
ParseAction reduce = ParseAction::Reduce(Symbol(2), 1, 0, AssociativityNone, production);
|
||||
|
||||
result = conflict_manager->resolve(reduce, shift, lookahead_sym);
|
||||
AssertThat(result.first, IsFalse());
|
||||
|
|
@ -139,7 +141,7 @@ describe("ParseConflictManager", []() {
|
|||
|
||||
describe("when the shift has conflicting precedences compared to the reduce", [&]() {
|
||||
ParseAction shift = ParseAction::Shift(2, { 1, 3 });
|
||||
ParseAction reduce = ParseAction::Reduce(Symbol(2), 1, 2, AssociativityLeft, 0);
|
||||
ParseAction reduce = ParseAction::Reduce(Symbol(2), 1, 2, AssociativityLeft, production);
|
||||
|
||||
it("returns false and reports an unresolved conflict", [&]() {
|
||||
result = conflict_manager->resolve(reduce, shift, lookahead_sym);
|
||||
|
|
@ -155,8 +157,8 @@ describe("ParseConflictManager", []() {
|
|||
|
||||
describe("reduce/reduce conflicts", [&]() {
|
||||
describe("when one action has higher precedence", [&]() {
|
||||
ParseAction left = ParseAction::Reduce(sym2, 1, 0, AssociativityLeft, 0);
|
||||
ParseAction right = ParseAction::Reduce(sym2, 1, 2, AssociativityLeft, 0);
|
||||
ParseAction left = ParseAction::Reduce(sym2, 1, 0, AssociativityLeft, production);
|
||||
ParseAction right = ParseAction::Reduce(sym2, 1, 2, AssociativityLeft, production);
|
||||
|
||||
it("favors that action", [&]() {
|
||||
result = conflict_manager->resolve(left, right, sym1);
|
||||
|
|
@ -171,8 +173,8 @@ describe("ParseConflictManager", []() {
|
|||
|
||||
describe("when the actions have the same precedence", [&]() {
|
||||
it("returns false and reports a conflict", [&]() {
|
||||
ParseAction left = ParseAction::Reduce(Symbol(2), 1, 0, AssociativityLeft, 0);
|
||||
ParseAction right = ParseAction::Reduce(Symbol(3), 1, 0, AssociativityLeft, 0);
|
||||
ParseAction left = ParseAction::Reduce(Symbol(2), 1, 0, AssociativityLeft, production);
|
||||
ParseAction right = ParseAction::Reduce(Symbol(3), 1, 0, AssociativityLeft, production);
|
||||
|
||||
result = conflict_manager->resolve(right, left, lookahead_sym);
|
||||
AssertThat(result.first, IsFalse());
|
||||
|
|
|
|||
|
|
@ -32,27 +32,31 @@ describe("parse_item_set_transitions(ParseItemSet, SyntaxGrammar)", [&]() {
|
|||
})
|
||||
}, {}, {}};
|
||||
|
||||
auto production = [&](int variable_index, int production_index) -> const Production & {
|
||||
return grammar.variables[variable_index].productions[production_index];
|
||||
};
|
||||
|
||||
ParseItemSet set1({
|
||||
{
|
||||
ParseItem(Symbol(0), 0, 2, 103),
|
||||
ParseItem(Symbol(0), production(0, 0), 2),
|
||||
LookaheadSet({ Symbol(16, true) })
|
||||
},
|
||||
{
|
||||
ParseItem(Symbol(1), 0, 0, 106),
|
||||
ParseItem(Symbol(1), production(1, 0), 0),
|
||||
LookaheadSet({ Symbol(17, true) })
|
||||
},
|
||||
{
|
||||
ParseItem(Symbol(2), 0, 1, 106),
|
||||
ParseItem(Symbol(2), production(2, 0), 1),
|
||||
LookaheadSet({ Symbol(17, true) })
|
||||
}
|
||||
});
|
||||
|
||||
AssertThat(set1.transitions(grammar), Equals(map<Symbol, ParseItemSet>({
|
||||
AssertThat(set1.transitions(), Equals(map<Symbol, ParseItemSet>({
|
||||
{
|
||||
Symbol(1),
|
||||
ParseItemSet({
|
||||
{
|
||||
ParseItem(Symbol(0), 0, 3, 104),
|
||||
ParseItem(Symbol(0), production(0, 0), 3),
|
||||
LookaheadSet({ Symbol(16, true) })
|
||||
}
|
||||
})
|
||||
|
|
@ -62,7 +66,7 @@ describe("parse_item_set_transitions(ParseItemSet, SyntaxGrammar)", [&]() {
|
|||
Symbol(2),
|
||||
ParseItemSet({
|
||||
{
|
||||
ParseItem(Symbol(1), 0, 1, 106),
|
||||
ParseItem(Symbol(1), production(1, 0), 1),
|
||||
LookaheadSet({ Symbol(17, true) })
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -126,9 +126,8 @@ ostream &operator<<(ostream &stream, const LexItemSet &item_set) {
|
|||
|
||||
ostream &operator<<(ostream &stream, const ParseItem &item) {
|
||||
return stream << string("(item variable:") << to_string(item.variable_index)
|
||||
<< string(" production:") << to_string(item.production_index)
|
||||
<< string(" production:") << to_string((size_t)&item.production % 1000)
|
||||
<< string(" step:") << to_string(item.step_index)
|
||||
<< string(" remaining_rule:") << to_string(item.rule_id)
|
||||
<< string(")");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue