Use PrecedenceRange in build_lex_table

This commit is contained in:
Max Brunsfeld 2015-10-05 18:02:59 -07:00
parent 11a1ea8dfe
commit 5455fb977f
5 changed files with 37 additions and 40 deletions

View file

@ -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());
});
});

View file

@ -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;
}

View file

@ -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)

View file

@ -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 {

View file

@ -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