Replace LexConflictManager class with action_takes_precedence function
This commit is contained in:
parent
5dc08ccce9
commit
0d267e41aa
7 changed files with 56 additions and 109 deletions
|
|
@ -20,7 +20,6 @@
|
|||
'src/compiler/build_tables/item.cc',
|
||||
'src/compiler/build_tables/item_set_closure.cc',
|
||||
'src/compiler/build_tables/item_set_transitions.cc',
|
||||
'src/compiler/build_tables/lex_conflict_manager.cc',
|
||||
'src/compiler/build_tables/lex_item.cc',
|
||||
'src/compiler/build_tables/parse_item.cc',
|
||||
'src/compiler/build_tables/rule_can_be_blank.cc',
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#include "compiler/rules/built_in_symbols.h"
|
||||
#include "compiler/parse_table.h"
|
||||
#include "compiler/build_tables/action_takes_precedence.h"
|
||||
#include "compiler/build_tables/lex_conflict_manager.h"
|
||||
#include "compiler/prepared_grammar.h"
|
||||
|
||||
using namespace rules;
|
||||
|
|
@ -10,7 +9,7 @@ using namespace build_tables;
|
|||
|
||||
START_TEST
|
||||
|
||||
describe("resolving parse conflicts", []() {
|
||||
describe("action_takes_precedence", []() {
|
||||
bool update;
|
||||
|
||||
SyntaxGrammar parse_grammar({
|
||||
|
|
@ -18,41 +17,25 @@ describe("resolving parse conflicts", []() {
|
|||
{ "rule2", sym("token1") },
|
||||
}, {}, set<rules::Symbol>());
|
||||
|
||||
LexicalGrammar lex_grammar({
|
||||
{ "token1", pattern("[a-c]") },
|
||||
{ "token2", pattern("[b-d]") },
|
||||
{ "token3", keyword("stuff") },
|
||||
}, {}, {});
|
||||
|
||||
describe("LexConflictManager", [&]() {
|
||||
describe("lexical conflicts", [&]() {
|
||||
Symbol sym1(0, SymbolOptionToken);
|
||||
Symbol sym2(1, SymbolOptionToken);
|
||||
Symbol sym3(2, SymbolOptionToken);
|
||||
|
||||
LexConflictManager *manager;
|
||||
|
||||
before_each([&]() {
|
||||
manager = new LexConflictManager(lex_grammar);
|
||||
});
|
||||
|
||||
after_each([&]() {
|
||||
delete manager;
|
||||
});
|
||||
|
||||
it("favors non-errors over lexical errors", [&]() {
|
||||
update = manager->resolve_lex_action(LexAction::Error(), LexAction::Advance(2, {0}));
|
||||
update = action_takes_precedence(LexAction::Advance(2, {0}), LexAction::Error());
|
||||
AssertThat(update, IsTrue());
|
||||
|
||||
update = manager->resolve_lex_action(LexAction::Advance(2, {0}), LexAction::Error());
|
||||
update = action_takes_precedence(LexAction::Error(), LexAction::Advance(2, {0}));
|
||||
AssertThat(update, IsFalse());
|
||||
});
|
||||
|
||||
describe("accept-token/advance conflicts", [&]() {
|
||||
it("prefers the advance", [&]() {
|
||||
update = manager->resolve_lex_action(LexAction::Accept(sym3, 3), LexAction::Advance(1, { 0 }));
|
||||
update = action_takes_precedence(LexAction::Advance(1, { 0 }), LexAction::Accept(sym3, 3));
|
||||
AssertThat(update, IsTrue());
|
||||
|
||||
update = manager->resolve_lex_action(LexAction::Advance(1, { 0 }), LexAction::Accept(sym3, 3));
|
||||
update = action_takes_precedence(LexAction::Accept(sym3, 3), LexAction::Advance(1, { 0 }));
|
||||
AssertThat(update, IsFalse());
|
||||
});
|
||||
});
|
||||
|
|
@ -60,27 +43,27 @@ describe("resolving parse conflicts", []() {
|
|||
describe("accept-token/accept-token conflicts", [&]() {
|
||||
describe("when one token has a higher precedence than the other", [&]() {
|
||||
it("prefers the token with the higher precedence", [&]() {
|
||||
update = manager->resolve_lex_action(LexAction::Accept(sym3, 2), LexAction::Accept(sym2, 0));
|
||||
update = action_takes_precedence(LexAction::Accept(sym2, 0), LexAction::Accept(sym3, 2));
|
||||
AssertThat(update, IsFalse());
|
||||
|
||||
update = manager->resolve_lex_action(LexAction::Accept(sym2, 0), LexAction::Accept(sym3, 2));
|
||||
update = action_takes_precedence(LexAction::Accept(sym3, 2), LexAction::Accept(sym2, 0));
|
||||
AssertThat(update, IsTrue());
|
||||
});
|
||||
});
|
||||
|
||||
describe("when both tokens have the same precedence", [&]() {
|
||||
it("prefers the token listed earlier in the grammar", [&]() {
|
||||
update = manager->resolve_lex_action(LexAction::Accept(sym1, 0), LexAction::Accept(sym2, 0));
|
||||
update = action_takes_precedence(LexAction::Accept(sym2, 0), LexAction::Accept(sym1, 0));
|
||||
AssertThat(update, IsFalse());
|
||||
|
||||
update = manager->resolve_lex_action(LexAction::Accept(sym2, 0), LexAction::Accept(sym1, 0));
|
||||
update = action_takes_precedence(LexAction::Accept(sym1, 0), LexAction::Accept(sym2, 0));
|
||||
AssertThat(update, IsTrue());
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("action_takes_precedence", [&]() {
|
||||
describe("parsing conflicts", [&]() {
|
||||
pair<bool, bool> result;
|
||||
Symbol sym1(0);
|
||||
Symbol sym2(1);
|
||||
|
|
@ -68,5 +68,42 @@ pair<bool, bool> action_takes_precedence(const ParseAction &new_action,
|
|||
return { has_precedence, has_conflict };
|
||||
}
|
||||
|
||||
bool action_takes_precedence(const LexAction &new_action,
|
||||
const LexAction &old_action) {
|
||||
if (new_action.type < old_action.type)
|
||||
return !action_takes_precedence(old_action, new_action);
|
||||
|
||||
switch (old_action.type) {
|
||||
case LexActionTypeError:
|
||||
return true;
|
||||
|
||||
case LexActionTypeAccept: {
|
||||
int old_precedence = *old_action.precedence_values.begin();
|
||||
|
||||
switch (new_action.type) {
|
||||
case LexActionTypeAccept: {
|
||||
int new_precedence = *new_action.precedence_values.begin();
|
||||
if (new_precedence > old_precedence)
|
||||
return true;
|
||||
else if (new_precedence < old_precedence)
|
||||
return false;
|
||||
else
|
||||
return new_action.symbol.index < old_action.symbol.index;
|
||||
}
|
||||
|
||||
case LexActionTypeAdvance:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace build_tables
|
||||
} // namespace tree_sitter
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ std::pair<bool, bool> action_takes_precedence(const ParseAction &new_action,
|
|||
const rules::Symbol &symbol,
|
||||
const SyntaxGrammar &grammar);
|
||||
|
||||
bool action_takes_precedence(const LexAction &new_action,
|
||||
const LexAction &old_action);
|
||||
|
||||
} // namespace build_tables
|
||||
} // namespace tree_sitter
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "compiler/build_tables/action_takes_precedence.h"
|
||||
#include "compiler/build_tables/item_set_transitions.h"
|
||||
#include "compiler/build_tables/lex_conflict_manager.h"
|
||||
#include "compiler/build_tables/lex_item.h"
|
||||
#include "compiler/parse_table.h"
|
||||
#include "compiler/prepared_grammar.h"
|
||||
|
|
@ -31,15 +31,12 @@ using rules::Symbol;
|
|||
class LexTableBuilder {
|
||||
const LexicalGrammar lex_grammar;
|
||||
ParseTable *parse_table;
|
||||
LexConflictManager conflict_manager;
|
||||
unordered_map<const LexItemSet, LexStateId> lex_state_ids;
|
||||
LexTable lex_table;
|
||||
|
||||
public:
|
||||
LexTableBuilder(ParseTable *parse_table, const LexicalGrammar &lex_grammar)
|
||||
: lex_grammar(lex_grammar),
|
||||
parse_table(parse_table),
|
||||
conflict_manager(LexConflictManager(lex_grammar)) {}
|
||||
: lex_grammar(lex_grammar), parse_table(parse_table) {}
|
||||
|
||||
LexTable build() {
|
||||
for (auto &parse_state : parse_table->states) {
|
||||
|
|
@ -98,8 +95,8 @@ class LexTableBuilder {
|
|||
LexStateId new_state_id = add_lex_state(new_item_set);
|
||||
auto action = LexAction::Advance(
|
||||
new_state_id, precedence_values_for_item_set(new_item_set));
|
||||
if (conflict_manager.resolve_lex_action(
|
||||
lex_table.state(state_id).default_action, action))
|
||||
if (action_takes_precedence(action,
|
||||
lex_table.state(state_id).default_action))
|
||||
lex_table.state(state_id).actions[rule] = action;
|
||||
}
|
||||
}
|
||||
|
|
@ -109,7 +106,7 @@ class LexTableBuilder {
|
|||
if (item.is_done()) {
|
||||
auto current_action = lex_table.state(state_id).default_action;
|
||||
auto new_action = LexAction::Accept(item.lhs, item.precedence());
|
||||
if (conflict_manager.resolve_lex_action(current_action, new_action))
|
||||
if (action_takes_precedence(new_action, current_action))
|
||||
lex_table.state(state_id).default_action = new_action;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
#include "compiler/build_tables/lex_conflict_manager.h"
|
||||
#include "compiler/util/string_helpers.h"
|
||||
#include "compiler/prepared_grammar.h"
|
||||
|
||||
namespace tree_sitter {
|
||||
namespace build_tables {
|
||||
|
||||
LexConflictManager::LexConflictManager(const LexicalGrammar &grammar)
|
||||
: grammar(grammar) {}
|
||||
|
||||
bool LexConflictManager::resolve_lex_action(const LexAction &old_action,
|
||||
const LexAction &new_action) {
|
||||
if (new_action.type < old_action.type)
|
||||
return !resolve_lex_action(new_action, old_action);
|
||||
|
||||
switch (old_action.type) {
|
||||
case LexActionTypeError:
|
||||
return true;
|
||||
|
||||
case LexActionTypeAccept: {
|
||||
int old_precedence = *old_action.precedence_values.begin();
|
||||
|
||||
switch (new_action.type) {
|
||||
case LexActionTypeAccept: {
|
||||
int new_precedence = *new_action.precedence_values.begin();
|
||||
if (new_precedence > old_precedence)
|
||||
return true;
|
||||
else if (new_precedence < old_precedence)
|
||||
return false;
|
||||
else
|
||||
return new_action.symbol.index < old_action.symbol.index;
|
||||
}
|
||||
|
||||
case LexActionTypeAdvance:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace build_tables
|
||||
} // namespace tree_sitter
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
#ifndef COMPILER_BUILD_TABLES_LEX_CONFLICT_MANAGER_H_
|
||||
#define COMPILER_BUILD_TABLES_LEX_CONFLICT_MANAGER_H_
|
||||
|
||||
#include "tree_sitter/compiler.h"
|
||||
#include "compiler/lex_table.h"
|
||||
#include "compiler/prepared_grammar.h"
|
||||
|
||||
namespace tree_sitter {
|
||||
namespace build_tables {
|
||||
|
||||
class LexConflictManager {
|
||||
const LexicalGrammar grammar;
|
||||
|
||||
public:
|
||||
explicit LexConflictManager(const LexicalGrammar &grammar);
|
||||
bool resolve_lex_action(const LexAction &old_action,
|
||||
const LexAction &new_action);
|
||||
};
|
||||
|
||||
} // namespace build_tables
|
||||
} // namespace tree_sitter
|
||||
|
||||
#endif // COMPILER_BUILD_TABLES_LEX_CONFLICT_MANAGER_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue