Store parse actions' precedences as ranges, not sets

This commit is contained in:
Max Brunsfeld 2015-10-05 16:05:19 -07:00
parent ef2acf9496
commit 6d748a6714
8 changed files with 105 additions and 50 deletions

View file

@ -233,17 +233,17 @@ class ParseTableBuilder {
return false;
}
set<int> precedence_values_for_item_set(const ParseItemSet &item_set) {
set<int> result;
PrecedenceRange precedence_values_for_item_set(const ParseItemSet &item_set) {
PrecedenceRange result;
for (const auto &pair : item_set.entries) {
const ParseItem &item = pair.first;
const Production &production =
grammar.productions(item.lhs())[item.production_index];
if (item.step_index > 0) {
if (item.step_index < production.size())
result.insert(production[item.step_index].precedence);
result.add(production[item.step_index].precedence);
else
result.insert(production[item.step_index - 1].precedence);
result.add(production[item.step_index - 1].precedence);
}
}
return result;
@ -305,20 +305,10 @@ class ParseTableBuilder {
string action_description(const ParseAction &action,
const set<Symbol> &goal_symbols) const {
string symbols_string;
bool started = false;
for (const auto &symbol : goal_symbols) {
if (started)
symbols_string += ", ";
symbols_string += symbol_name(symbol);
started = true;
}
string result;
switch (action.type) {
case ParseActionTypeReduce: {
result = "Reduce";
result += "Reduce";
for (const ProductionStep &step :
grammar.productions(action.symbol)[action.production_id])
result += " " + symbol_name(step.symbol);
@ -327,21 +317,25 @@ class ParseTableBuilder {
}
case ParseActionTypeShift: {
result = "Shift";
result += "Shift ";
bool started = false;
for (const auto &symbol : goal_symbols) {
if (started)
result += ", ";
started = true;
result += symbol_name(symbol);
}
break;
}
default:
return "";
break;
}
if (action.precedence_values.size() > 1) {
result += " (Precedences " + to_string(*action.precedence_values.begin()) +
", " + to_string(*action.precedence_values.rbegin()) + ")";
} else {
result +=
" (Precedence " + to_string(*action.precedence_values.begin()) + ")";
}
result += (action.precedence_range.min == action.precedence_range.max)
? " (Precedence " + to_string(action.precedence_range.min) + ")"
: " (Precedences " + to_string(action.precedence_range.min) +
", " + to_string(action.precedence_range.max) + ")";
return result;
}

View file

@ -28,9 +28,9 @@ pair<bool, ConflictType> ParseConflictManager::resolve(
case ParseActionTypeShift:
if (new_action.type == ParseActionTypeReduce) {
int min_precedence = *old_action.precedence_values.begin();
int max_precedence = *old_action.precedence_values.rbegin();
int new_precedence = *new_action.precedence_values.rbegin();
int min_precedence = old_action.precedence_range.min;
int max_precedence = old_action.precedence_range.max;
int new_precedence = new_action.precedence_range.max;
if (new_precedence < min_precedence ||
(new_precedence == min_precedence &&
min_precedence < max_precedence)) {
@ -55,8 +55,8 @@ pair<bool, ConflictType> ParseConflictManager::resolve(
case ParseActionTypeReduce:
if (new_action.type == ParseActionTypeReduce) {
int old_precedence = *old_action.precedence_values.begin();
int new_precedence = *new_action.precedence_values.begin();
int old_precedence = old_action.precedence_range.min;
int new_precedence = new_action.precedence_range.min;
if (new_precedence > old_precedence) {
return { true, ConflictTypeResolved };
} else if (new_precedence < old_precedence) {

View file

@ -1,4 +1,5 @@
#include "compiler/parse_table.h"
#include "compiler/precedence_range.h"
#include <string>
namespace tree_sitter {
@ -12,13 +13,13 @@ using rules::Symbol;
ParseAction::ParseAction(ParseActionType type, ParseStateId state_index,
Symbol symbol, size_t consumed_symbol_count,
set<int> precedence_values,
PrecedenceRange precedence_range,
Associativity associativity, int production_id)
: type(type),
symbol(symbol),
state_index(state_index),
consumed_symbol_count(consumed_symbol_count),
precedence_values(precedence_values),
precedence_range(precedence_range),
associativity(associativity),
production_id(production_id) {}
@ -40,9 +41,9 @@ ParseAction ParseAction::Accept() {
}
ParseAction ParseAction::Shift(ParseStateId state_index,
set<int> precedence_values) {
PrecedenceRange precedence_range) {
return ParseAction(ParseActionTypeShift, state_index, Symbol(-1), 0,
precedence_values, AssociativityNone, -1);
precedence_range, AssociativityNone, -1);
}
ParseAction ParseAction::ShiftExtra() {
@ -62,7 +63,7 @@ ParseAction ParseAction::Reduce(Symbol symbol, size_t consumed_symbol_count,
int precedence, Associativity associativity,
unsigned int production_id) {
return ParseAction(ParseActionTypeReduce, 0, symbol, consumed_symbol_count,
{ precedence }, associativity, production_id);
{ precedence, precedence }, associativity, production_id);
}
bool ParseAction::operator==(const ParseAction &other) const {
@ -71,7 +72,9 @@ bool ParseAction::operator==(const ParseAction &other) const {
bool state_indices_eq = state_index == other.state_index;
bool consumed_symbol_counts_eq =
consumed_symbol_count == other.consumed_symbol_count;
return types_eq && symbols_eq && state_indices_eq && consumed_symbol_counts_eq;
bool precedences_eq = precedence_range == other.precedence_range;
return types_eq && symbols_eq && state_indices_eq &&
consumed_symbol_counts_eq && precedences_eq;
}
bool ParseAction::operator<(const ParseAction &other) const {

View file

@ -8,6 +8,7 @@
#include "compiler/lex_table.h"
#include "compiler/rules/symbol.h"
#include "compiler/rules/metadata.h"
#include "compiler/precedence_range.h"
namespace tree_sitter {
@ -26,14 +27,13 @@ typedef enum {
class ParseAction {
ParseAction(ParseActionType type, ParseStateId state_index,
rules::Symbol symbol, size_t consumed_symbol_count,
std::set<int> precedence_values, Associativity, int production_id);
PrecedenceRange range, Associativity, int production_id);
public:
ParseAction();
static ParseAction Accept();
static ParseAction Error();
static ParseAction Shift(ParseStateId state_index,
std::set<int> precedence_values);
static ParseAction Shift(ParseStateId state_index, PrecedenceRange precedence);
static ParseAction Reduce(rules::Symbol symbol, size_t consumed_symbol_count,
int precedence, Associativity,
unsigned int production_id);
@ -46,7 +46,7 @@ class ParseAction {
rules::Symbol symbol;
ParseStateId state_index;
size_t consumed_symbol_count;
std::set<int> precedence_values;
PrecedenceRange precedence_range;
Associativity associativity;
int production_id;
};
@ -62,6 +62,9 @@ struct hash<tree_sitter::ParseAction> {
hash<tree_sitter::rules::Symbol>()(action.symbol) ^
hash<size_t>()(action.state_index) ^
hash<size_t>()(action.consumed_symbol_count) ^
hash<int>()(action.associativity) ^
hash<int>()(action.precedence_range.min) ^
hash<int>()(action.precedence_range.max) ^
hash<size_t>()(action.production_id));
}
};

View file

@ -0,0 +1,35 @@
#include "compiler/precedence_range.h"
namespace tree_sitter {
PrecedenceRange::PrecedenceRange() : min(0), max(0), empty(true) {}
PrecedenceRange::PrecedenceRange(int min, int max)
: min(min), max(max), empty(false) {}
void PrecedenceRange::add(int new_value) {
if (empty) {
min = new_value;
max = new_value;
empty = false;
} else {
if (new_value < min)
min = new_value;
else if (new_value > max)
max = new_value;
}
}
bool PrecedenceRange::operator<(const PrecedenceRange &other) const {
if (empty)
return !other.empty;
else
return (min < other.min && max <= other.min) ||
(min == other.min && max < other.max);
}
bool PrecedenceRange::operator==(const PrecedenceRange &other) const {
return (empty == other.empty) && (min == other.min) && (max == other.max);
}
} // namespace tree_sitter

View file

@ -0,0 +1,21 @@
#ifndef COMPILER_PRECEDENCE_RANGE_H_
#define COMPILER_PRECEDENCE_RANGE_H_
namespace tree_sitter {
struct PrecedenceRange {
PrecedenceRange();
PrecedenceRange(int min, int max);
void add(int);
bool operator==(const PrecedenceRange &other) const;
bool operator<(const PrecedenceRange &other) const;
int min;
int max;
bool empty;
};
} // namespace tree_sitter
#endif // COMPILER_PRECEDENCE_RANGE_H_