Add PREC_DYNAMIC rule for resolving runtime ambiguities
This commit is contained in:
parent
cb652239f6
commit
d8e9d04fe7
24 changed files with 316 additions and 83 deletions
|
|
@ -55,7 +55,8 @@ class ParseTableBuilder {
|
|||
Symbol::non_terminal(0);
|
||||
|
||||
Production start_production{
|
||||
ProductionStep{start_symbol, 0, rules::AssociativityNone},
|
||||
{ProductionStep{start_symbol, 0, rules::AssociativityNone}},
|
||||
0
|
||||
};
|
||||
|
||||
// Placeholder for error state
|
||||
|
|
@ -281,9 +282,10 @@ class ParseTableBuilder {
|
|||
|
||||
for (ParseAction &action : actions) {
|
||||
if (action.type == ParseActionTypeReduce) {
|
||||
if (has_fragile_production(action.production))
|
||||
if (has_fragile_production(action.production)) {
|
||||
action.fragile = true;
|
||||
action.production = NULL;
|
||||
}
|
||||
action.production = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -586,7 +588,7 @@ class ParseTableBuilder {
|
|||
}
|
||||
|
||||
description += " (" + symbol_name(action.symbol);
|
||||
for (const ProductionStep &step : *action.production) {
|
||||
for (const ProductionStep &step : action.production->steps) {
|
||||
description += " " + symbol_name(step.symbol);
|
||||
}
|
||||
description += ")";
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@ int ParseItem::precedence() const {
|
|||
}
|
||||
}
|
||||
|
||||
int ParseItem::dynamic_precedence() const {
|
||||
return production->dynamic_precedence;
|
||||
}
|
||||
|
||||
rules::Associativity ParseItem::associativity() const {
|
||||
if (is_done()) {
|
||||
if (production->empty()) {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ struct ParseItem {
|
|||
rules::Symbol lhs() const;
|
||||
rules::Symbol next_symbol() const;
|
||||
int precedence() const;
|
||||
int dynamic_precedence() const;
|
||||
rules::Associativity associativity() const;
|
||||
bool is_done() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -490,12 +490,17 @@ class CCodeGenerator {
|
|||
break;
|
||||
case ParseActionTypeReduce:
|
||||
if (action.fragile) {
|
||||
add("REDUCE_FRAGILE(" + symbol_id(action.symbol) + ", " +
|
||||
to_string(action.consumed_symbol_count) + ")");
|
||||
add("REDUCE_FRAGILE");
|
||||
} else {
|
||||
add("REDUCE(" + symbol_id(action.symbol) + ", " +
|
||||
to_string(action.consumed_symbol_count) + ")");
|
||||
add("REDUCE");
|
||||
}
|
||||
|
||||
add("(");
|
||||
add(symbol_id(action.symbol));
|
||||
add(", ");
|
||||
add(to_string(action.consumed_symbol_count));
|
||||
add(", " + to_string(action.dynamic_precedence));
|
||||
add(")");
|
||||
break;
|
||||
case ParseActionTypeRecover:
|
||||
add("RECOVER(" + to_string(action.state_index) + ")");
|
||||
|
|
|
|||
|
|
@ -184,6 +184,20 @@ ParseRuleResult parse_rule(json_value *rule_json) {
|
|||
return Rule(Metadata::prec_right(precedence_json.u.integer, result.rule));
|
||||
}
|
||||
|
||||
if (type == "PREC_DYNAMIC") {
|
||||
json_value precedence_json = rule_json->operator[]("value");
|
||||
if (precedence_json.type != json_integer) {
|
||||
return "Precedence value must be an integer";
|
||||
}
|
||||
|
||||
json_value content_json = rule_json->operator[]("content");
|
||||
auto result = parse_rule(&content_json);
|
||||
if (!result.error_message.empty()) {
|
||||
return "Invalid precedence content: " + result.error_message;
|
||||
}
|
||||
return Rule(Metadata::prec_dynamic(precedence_json.u.integer, result.rule));
|
||||
}
|
||||
|
||||
return "Unknown rule type: " + type;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,25 +13,14 @@ using std::vector;
|
|||
using std::function;
|
||||
using rules::Symbol;
|
||||
|
||||
ParseAction::ParseAction(ParseActionType type, ParseStateId state_index,
|
||||
Symbol symbol, size_t consumed_symbol_count,
|
||||
const Production *production)
|
||||
: type(type),
|
||||
extra(false),
|
||||
fragile(false),
|
||||
state_index(state_index),
|
||||
symbol(symbol),
|
||||
consumed_symbol_count(consumed_symbol_count),
|
||||
production(production) {}
|
||||
|
||||
ParseAction::ParseAction()
|
||||
: type(ParseActionTypeError),
|
||||
: production(nullptr),
|
||||
consumed_symbol_count(0),
|
||||
symbol(rules::NONE()),
|
||||
type(ParseActionTypeError),
|
||||
extra(false),
|
||||
fragile(false),
|
||||
state_index(-1),
|
||||
symbol(rules::NONE()),
|
||||
consumed_symbol_count(0),
|
||||
production(nullptr) {}
|
||||
state_index(-1) {}
|
||||
|
||||
ParseAction ParseAction::Error() {
|
||||
return ParseAction();
|
||||
|
|
@ -44,12 +33,17 @@ ParseAction ParseAction::Accept() {
|
|||
}
|
||||
|
||||
ParseAction ParseAction::Shift(ParseStateId state_index) {
|
||||
return ParseAction(ParseActionTypeShift, state_index, rules::NONE(), 0, nullptr);
|
||||
ParseAction result;
|
||||
result.type = ParseActionTypeShift;
|
||||
result.state_index = state_index;
|
||||
return result;
|
||||
}
|
||||
|
||||
ParseAction ParseAction::Recover(ParseStateId state_index) {
|
||||
return ParseAction(ParseActionTypeRecover, state_index, rules::NONE(), 0,
|
||||
nullptr);
|
||||
ParseAction result;
|
||||
result.type = ParseActionTypeRecover;
|
||||
result.state_index = state_index;
|
||||
return result;
|
||||
}
|
||||
|
||||
ParseAction ParseAction::ShiftExtra() {
|
||||
|
|
@ -61,8 +55,13 @@ ParseAction ParseAction::ShiftExtra() {
|
|||
|
||||
ParseAction ParseAction::Reduce(Symbol symbol, size_t consumed_symbol_count,
|
||||
const Production &production) {
|
||||
return ParseAction(ParseActionTypeReduce, 0, symbol, consumed_symbol_count,
|
||||
&production);
|
||||
ParseAction result;
|
||||
result.type = ParseActionTypeReduce;
|
||||
result.symbol = symbol;
|
||||
result.consumed_symbol_count = consumed_symbol_count;
|
||||
result.production = &production;
|
||||
result.dynamic_precedence = production.dynamic_precedence;
|
||||
return result;
|
||||
}
|
||||
|
||||
int ParseAction::precedence() const {
|
||||
|
|
|
|||
|
|
@ -24,9 +24,6 @@ enum ParseActionType {
|
|||
|
||||
struct ParseAction {
|
||||
ParseAction();
|
||||
ParseAction(ParseActionType type, ParseStateId state_index,
|
||||
rules::Symbol symbol, size_t consumed_symbol_count,
|
||||
const Production *);
|
||||
static ParseAction Accept();
|
||||
static ParseAction Error();
|
||||
static ParseAction Shift(ParseStateId state_index);
|
||||
|
|
@ -39,13 +36,14 @@ struct ParseAction {
|
|||
rules::Associativity associativity() const;
|
||||
int precedence() const;
|
||||
|
||||
const Production *production;
|
||||
size_t consumed_symbol_count;
|
||||
rules::Symbol symbol;
|
||||
int dynamic_precedence;
|
||||
ParseActionType type;
|
||||
bool extra;
|
||||
bool fragile;
|
||||
ParseStateId state_index;
|
||||
rules::Symbol symbol;
|
||||
size_t consumed_symbol_count;
|
||||
const Production *production;
|
||||
};
|
||||
|
||||
struct ParseTableEntry {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class FlattenRule {
|
|||
void apply(const Rule &rule) {
|
||||
rule.match(
|
||||
[&](const rules::Symbol &symbol) {
|
||||
production.push_back(ProductionStep{
|
||||
production.steps.push_back(ProductionStep{
|
||||
symbol,
|
||||
precedence_stack.back(),
|
||||
associativity_stack.back()
|
||||
|
|
@ -42,6 +42,10 @@ class FlattenRule {
|
|||
associativity_stack.push_back(metadata.params.associativity);
|
||||
}
|
||||
|
||||
if (metadata.params.dynamic_precedence > production.dynamic_precedence) {
|
||||
production.dynamic_precedence = metadata.params.dynamic_precedence;
|
||||
}
|
||||
|
||||
apply(*metadata.rule);
|
||||
|
||||
if (metadata.params.has_precedence) {
|
||||
|
|
|
|||
|
|
@ -51,6 +51,12 @@ Metadata Metadata::prec_right(int precedence, const Rule &rule) {
|
|||
return Metadata{rule, params};
|
||||
}
|
||||
|
||||
Metadata Metadata::prec_dynamic(int dynamic_precedence, const Rule &rule) {
|
||||
MetadataParams params;
|
||||
params.dynamic_precedence = dynamic_precedence;
|
||||
return Metadata{rule, params};
|
||||
}
|
||||
|
||||
Metadata Metadata::separator(const Rule &rule) {
|
||||
MetadataParams params;
|
||||
params.has_precedence = true;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ enum Associativity {
|
|||
|
||||
struct MetadataParams {
|
||||
int precedence;
|
||||
int dynamic_precedence;
|
||||
Associativity associativity;
|
||||
bool has_precedence;
|
||||
bool has_associativity;
|
||||
|
|
@ -23,8 +24,8 @@ struct MetadataParams {
|
|||
bool is_main_token;
|
||||
|
||||
inline MetadataParams() :
|
||||
precedence{0}, associativity{AssociativityNone}, has_precedence{false},
|
||||
has_associativity{false}, is_token{false}, is_string{false},
|
||||
precedence{0}, dynamic_precedence{0}, associativity{AssociativityNone},
|
||||
has_precedence{false}, has_associativity{false}, is_token{false}, is_string{false},
|
||||
is_active{false}, is_main_token{false} {}
|
||||
|
||||
inline bool operator==(const MetadataParams &other) const {
|
||||
|
|
@ -33,6 +34,7 @@ struct MetadataParams {
|
|||
associativity == other.associativity &&
|
||||
has_precedence == other.has_precedence &&
|
||||
has_associativity == other.has_associativity &&
|
||||
dynamic_precedence == other.dynamic_precedence &&
|
||||
is_token == other.is_token &&
|
||||
is_string == other.is_string &&
|
||||
is_active == other.is_active &&
|
||||
|
|
@ -54,6 +56,7 @@ struct Metadata {
|
|||
static Metadata prec(int precedence, const Rule &rule);
|
||||
static Metadata prec_left(int precedence, const Rule &rule);
|
||||
static Metadata prec_right(int precedence, const Rule &rule);
|
||||
static Metadata prec_dynamic(int precedence, const Rule &rule);
|
||||
static Metadata separator(const Rule &rule);
|
||||
static Metadata main_token(const Rule &rule);
|
||||
|
||||
|
|
@ -63,4 +66,4 @@ struct Metadata {
|
|||
} // namespace rules
|
||||
} // namespace tree_sitter
|
||||
|
||||
#endif // COMPILER_RULES_METADATA_H_
|
||||
#endif // COMPILER_RULES_METADATA_H_
|
||||
|
|
|
|||
|
|
@ -11,8 +11,9 @@ namespace tree_sitter {
|
|||
|
||||
struct ProductionStep {
|
||||
inline bool operator==(const ProductionStep &other) const {
|
||||
return symbol == other.symbol && precedence == other.precedence &&
|
||||
associativity == other.associativity;
|
||||
return symbol == other.symbol &&
|
||||
precedence == other.precedence &&
|
||||
associativity == other.associativity;
|
||||
}
|
||||
|
||||
rules::Symbol symbol;
|
||||
|
|
@ -20,7 +21,21 @@ struct ProductionStep {
|
|||
rules::Associativity associativity;
|
||||
};
|
||||
|
||||
typedef std::vector<ProductionStep> Production;
|
||||
struct Production {
|
||||
std::vector<ProductionStep> steps;
|
||||
int dynamic_precedence = 0;
|
||||
|
||||
inline bool operator==(const Production &other) const {
|
||||
return steps == other.steps && dynamic_precedence == other.dynamic_precedence;
|
||||
}
|
||||
|
||||
inline ProductionStep &back() { return steps.back(); }
|
||||
inline const ProductionStep &back() const { return steps.back(); }
|
||||
inline bool empty() const { return steps.empty(); }
|
||||
inline size_t size() const { return steps.size(); }
|
||||
inline const ProductionStep &operator[](int i) const { return steps[i]; }
|
||||
inline const ProductionStep &at(int i) const { return steps[i]; }
|
||||
};
|
||||
|
||||
struct SyntaxVariable {
|
||||
std::string name;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue