Use PrecedenceRange in build_lex_table
This commit is contained in:
parent
11a1ea8dfe
commit
5455fb977f
5 changed files with 37 additions and 40 deletions
|
|
@ -22,19 +22,19 @@ describe("LexConflictManager", []() {
|
|||
Symbol sym3(2, true);
|
||||
|
||||
it("favors non-errors over lexical errors", [&]() {
|
||||
update = conflict_manager.resolve(LexAction::Advance(2, {0}), LexAction::Error());
|
||||
update = conflict_manager.resolve(LexAction::Advance(2, {0, 0}), LexAction::Error());
|
||||
AssertThat(update, IsTrue());
|
||||
|
||||
update = conflict_manager.resolve(LexAction::Error(), LexAction::Advance(2, {0}));
|
||||
update = conflict_manager.resolve(LexAction::Error(), LexAction::Advance(2, {0, 0}));
|
||||
AssertThat(update, IsFalse());
|
||||
});
|
||||
|
||||
describe("accept-token/advance conflicts", [&]() {
|
||||
it("prefers the advance", [&]() {
|
||||
update = conflict_manager.resolve(LexAction::Advance(1, { 0 }), LexAction::Accept(sym3, 3));
|
||||
update = conflict_manager.resolve(LexAction::Advance(1, { 0, 0 }), LexAction::Accept(sym3, 3));
|
||||
AssertThat(update, IsTrue());
|
||||
|
||||
update = conflict_manager.resolve(LexAction::Accept(sym3, 3), LexAction::Advance(1, { 0 }));
|
||||
update = conflict_manager.resolve(LexAction::Accept(sym3, 3), LexAction::Advance(1, { 0, 0 }));
|
||||
AssertThat(update, IsFalse());
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -43,31 +43,32 @@ class LexTableBuilder {
|
|||
conflict_manager(lex_grammar),
|
||||
parse_table(parse_table) {
|
||||
vector<rule_ptr> separators;
|
||||
for (const auto &rule : lex_grammar.separators)
|
||||
for (const rule_ptr &rule : lex_grammar.separators)
|
||||
separators.push_back(rules::Repeat::build(rule));
|
||||
separator_rule = rules::Choice::build(separators);
|
||||
}
|
||||
|
||||
LexTable build() {
|
||||
for (auto &parse_state : parse_table->states) {
|
||||
for (ParseState &parse_state : parse_table->states) {
|
||||
LexItemSet item_set = build_lex_item_set(parse_state.expected_inputs());
|
||||
parse_state.lex_state_id = add_lex_state(item_set);
|
||||
}
|
||||
add_error_lex_state();
|
||||
|
||||
LexItemSet error_item_set = build_lex_item_set(parse_table->symbols);
|
||||
populate_lex_state(error_item_set, LexTable::ERROR_STATE_ID);
|
||||
|
||||
return lex_table;
|
||||
}
|
||||
|
||||
private:
|
||||
LexItemSet build_lex_item_set(const set<Symbol> &symbols) {
|
||||
LexItemSet result;
|
||||
for (const auto &symbol : symbols) {
|
||||
for (const Symbol &symbol : symbols) {
|
||||
if (symbol == rules::ERROR())
|
||||
continue;
|
||||
|
||||
if (symbol == rules::END_OF_INPUT())
|
||||
else if (symbol == rules::END_OF_INPUT())
|
||||
result.entries.insert(
|
||||
LexItem(symbol, after_separators(CharacterSet().include(0).copy())));
|
||||
|
||||
else if (symbol.is_token)
|
||||
result.entries.insert(LexItem(
|
||||
symbol, after_separators(lex_grammar.variables[symbol.index].rule)));
|
||||
|
|
@ -80,31 +81,26 @@ class LexTableBuilder {
|
|||
if (pair == lex_state_ids.end()) {
|
||||
LexStateId state_id = lex_table.add_state();
|
||||
lex_state_ids[item_set] = state_id;
|
||||
|
||||
add_accept_token_actions(item_set, state_id);
|
||||
add_advance_actions(item_set, state_id);
|
||||
add_token_start(item_set, state_id);
|
||||
|
||||
populate_lex_state(item_set, state_id);
|
||||
return state_id;
|
||||
} else {
|
||||
return pair->second;
|
||||
}
|
||||
}
|
||||
|
||||
void add_error_lex_state() {
|
||||
LexItemSet item_set = build_lex_item_set(parse_table->symbols);
|
||||
add_accept_token_actions(item_set, LexTable::ERROR_STATE_ID);
|
||||
add_advance_actions(item_set, LexTable::ERROR_STATE_ID);
|
||||
add_token_start(item_set, LexTable::ERROR_STATE_ID);
|
||||
void populate_lex_state(const LexItemSet &item_set, LexStateId state_id) {
|
||||
add_accept_token_actions(item_set, state_id);
|
||||
add_advance_actions(item_set, state_id);
|
||||
add_token_start(item_set, state_id);
|
||||
}
|
||||
|
||||
void add_advance_actions(const LexItemSet &item_set, LexStateId state_id) {
|
||||
for (const auto &transition : item_set.transitions()) {
|
||||
CharacterSet rule = transition.first;
|
||||
LexItemSet new_item_set = transition.second;
|
||||
const CharacterSet &rule = transition.first;
|
||||
const LexItemSet &new_item_set = transition.second;
|
||||
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));
|
||||
new_state_id, precedence_range_for_item_set(new_item_set));
|
||||
if (conflict_manager.resolve(action,
|
||||
lex_table.state(state_id).default_action))
|
||||
lex_table.state(state_id).actions[rule] = action;
|
||||
|
|
@ -140,12 +136,12 @@ class LexTableBuilder {
|
|||
});
|
||||
}
|
||||
|
||||
set<int> precedence_values_for_item_set(const LexItemSet &item_set) const {
|
||||
set<int> result;
|
||||
PrecedenceRange precedence_range_for_item_set(const LexItemSet &item_set) const {
|
||||
PrecedenceRange result;
|
||||
for (const auto &item : item_set.entries) {
|
||||
auto precedence_range = get_metadata(item.rule, rules::PRECEDENCE);
|
||||
result.insert(precedence_range.min);
|
||||
result.insert(precedence_range.max);
|
||||
result.add(precedence_range.min);
|
||||
result.add(precedence_range.max);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ bool LexConflictManager::resolve(const LexAction &new_action,
|
|||
return true;
|
||||
|
||||
case LexActionTypeAccept: {
|
||||
int old_precedence = *old_action.precedence_values.begin();
|
||||
int old_precedence = old_action.precedence_range.min;
|
||||
|
||||
switch (new_action.type) {
|
||||
case LexActionTypeAccept: {
|
||||
int new_precedence = *new_action.precedence_values.begin();
|
||||
int new_precedence = new_action.precedence_range.min;
|
||||
if (new_precedence > old_precedence)
|
||||
return true;
|
||||
else if (new_precedence < old_precedence)
|
||||
|
|
|
|||
|
|
@ -14,26 +14,26 @@ LexAction::LexAction()
|
|||
: type(LexActionTypeError),
|
||||
symbol(Symbol(-1)),
|
||||
state_index(-1),
|
||||
precedence_values({ 0 }) {}
|
||||
precedence_range({ 0, 0 }) {}
|
||||
|
||||
LexAction::LexAction(LexActionType type, size_t state_index, Symbol symbol,
|
||||
set<int> precedence_values)
|
||||
PrecedenceRange precedence_range)
|
||||
: type(type),
|
||||
symbol(symbol),
|
||||
state_index(state_index),
|
||||
precedence_values(precedence_values) {}
|
||||
precedence_range(precedence_range) {}
|
||||
|
||||
LexAction LexAction::Error() {
|
||||
return LexAction(LexActionTypeError, -1, Symbol(-1), { 0 });
|
||||
return LexAction(LexActionTypeError, -1, Symbol(-1), { 0, 0 });
|
||||
}
|
||||
|
||||
LexAction LexAction::Advance(size_t state_index, set<int> precedence_values) {
|
||||
LexAction LexAction::Advance(size_t state_index, PrecedenceRange precedence_range) {
|
||||
return LexAction(LexActionTypeAdvance, state_index, Symbol(-1),
|
||||
precedence_values);
|
||||
precedence_range);
|
||||
}
|
||||
|
||||
LexAction LexAction::Accept(Symbol symbol, int precedence) {
|
||||
return LexAction(LexActionTypeAccept, -1, symbol, { precedence });
|
||||
return LexAction(LexActionTypeAccept, -1, symbol, { precedence, precedence });
|
||||
}
|
||||
|
||||
bool LexAction::operator==(const LexAction &other) const {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <vector>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include "compiler/precedence_range.h"
|
||||
#include "compiler/rules/symbol.h"
|
||||
#include "compiler/rules/character_set.h"
|
||||
|
||||
|
|
@ -18,19 +19,19 @@ typedef enum {
|
|||
|
||||
class LexAction {
|
||||
LexAction(LexActionType type, size_t state_index, rules::Symbol symbol,
|
||||
std::set<int> precedence_values);
|
||||
PrecedenceRange precedence_range);
|
||||
|
||||
public:
|
||||
LexAction();
|
||||
static LexAction Accept(rules::Symbol symbol, int precedence);
|
||||
static LexAction Error();
|
||||
static LexAction Advance(size_t state_index, std::set<int> precedence_values);
|
||||
static LexAction Advance(size_t state_index, PrecedenceRange precedence_range);
|
||||
bool operator==(const LexAction &action) const;
|
||||
|
||||
LexActionType type;
|
||||
rules::Symbol symbol;
|
||||
size_t state_index;
|
||||
std::set<int> precedence_values;
|
||||
PrecedenceRange precedence_range;
|
||||
};
|
||||
|
||||
} // namespace tree_sitter
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue