From 4850384b78b2b3022fb47d690af20a5b34dbc9f6 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 30 Oct 2015 13:54:11 -0700 Subject: [PATCH] Include precedence calculation in ParseItemSet::transitions --- spec/compiler/build_tables/parse_item_spec.cc | 83 +++++++++++++------ .../build_tables/build_parse_table.cc | 15 +--- src/compiler/build_tables/parse_item.cc | 8 +- src/compiler/build_tables/parse_item.h | 5 +- 4 files changed, 70 insertions(+), 41 deletions(-) diff --git a/spec/compiler/build_tables/parse_item_spec.cc b/spec/compiler/build_tables/parse_item_spec.cc index b9dbfd3b..f189d98f 100644 --- a/spec/compiler/build_tables/parse_item_spec.cc +++ b/spec/compiler/build_tables/parse_item_spec.cc @@ -9,25 +9,30 @@ using namespace build_tables; START_TEST describe("ParseItemSet::transitions())", [&]() { - it("returns a map of symbols to ParseItemSets that would result from consuming those symbols", [&]() { + it("computes the ParseItemSet that would occur after consuming each lookahead symbol, along with its precedence", [&]() { SyntaxGrammar grammar{{ SyntaxVariable("rule_0", VariableTypeNamed, { Production({ {Symbol(11, true), 0, AssociativityNone, 101}, {Symbol(12, true), 0, AssociativityNone, 102}, - {Symbol(1), 0, AssociativityNone, 103}, - {Symbol(13, true), 0, AssociativityNone, 104}, + {Symbol(13), 5, AssociativityNone, 103}, + {Symbol(14, true), 0, AssociativityNone, 104}, + }), + Production({ + {Symbol(11, true), 0, AssociativityNone, 105}, + {Symbol(12, true), 0, AssociativityNone, 106}, + {Symbol(15), 6, AssociativityNone, 107}, }) }), SyntaxVariable("rule_1", VariableTypeNamed, { Production({ - {Symbol(2), 0, AssociativityNone, 105}, - {Symbol(14, true), 0, AssociativityNone, 106}, + {Symbol(15), 7, AssociativityNone, 109}, + {Symbol(16, true), 0, AssociativityNone, 110}, }) }), SyntaxVariable("rule_2", VariableTypeNamed, { Production({ - {Symbol(15, true), 0, AssociativityNone, 105}, + {Symbol(18, true), 0, AssociativityNone, 111}, }) }) }, {}, {}}; @@ -36,41 +41,69 @@ describe("ParseItemSet::transitions())", [&]() { return grammar.variables[variable_index].productions[production_index]; }; - ParseItemSet set1({ + ParseItemSet item_set({ + + // Two symbols into the first production for rule_0 { ParseItem(Symbol(0), production(0, 0), 2), - LookaheadSet({ Symbol(16, true) }) + LookaheadSet({ Symbol(21, true) }) }, + + // Two symbols into the second production for rule_0 + { + ParseItem(Symbol(0), production(0, 1), 2), + LookaheadSet({ Symbol(21, true) }) + }, + + // At the beginning of the first production for rule_1 { ParseItem(Symbol(1), production(1, 0), 0), - LookaheadSet({ Symbol(17, true) }) + LookaheadSet({ Symbol(22, true) }) }, + + // At the end of the first production for rule_2 { ParseItem(Symbol(2), production(2, 0), 1), - LookaheadSet({ Symbol(17, true) }) + LookaheadSet({ Symbol(22, true) }) } }); - AssertThat(set1.transitions(), Equals(map({ + AssertThat(item_set.transitions(), Equals(ParseItemSet::TransitionMap({ + + // For the first item, symbol 13 is next, with precedence 5. { - Symbol(1), - ParseItemSet({ - { - ParseItem(Symbol(0), production(0, 0), 3), - LookaheadSet({ Symbol(16, true) }) - } - }) + Symbol(13), + { + ParseItemSet({ + { + ParseItem(Symbol(0), production(0, 0), 3), + LookaheadSet({ Symbol(21, true) }) + } + }), + PrecedenceRange(5, 5) + } }, + // For the second and third item, symbol 15 is next, with two different + // precedence values. { - Symbol(2), - ParseItemSet({ - { - ParseItem(Symbol(1), production(1, 0), 1), - LookaheadSet({ Symbol(17, true) }) - }, - }) + Symbol(15), + { + ParseItemSet({ + { + ParseItem(Symbol(0), production(0, 1), 3), + LookaheadSet({ Symbol(21, true) }) + }, + { + ParseItem(Symbol(1), production(1, 0), 1), + LookaheadSet({ Symbol(22, true) }) + }, + }), + PrecedenceRange(6, 7) + } }, + + // The third item is at the end of its production: no transitions. }))); }); }); diff --git a/src/compiler/build_tables/build_parse_table.cc b/src/compiler/build_tables/build_parse_table.cc index 2a5738a9..7ae65e95 100644 --- a/src/compiler/build_tables/build_parse_table.cc +++ b/src/compiler/build_tables/build_parse_table.cc @@ -99,11 +99,12 @@ class ParseTableBuilder { void add_shift_actions(const ParseItemSet &item_set, ParseStateId state_id) { for (const auto &transition : item_set.transitions()) { const Symbol &symbol = transition.first; - const ParseItemSet &next_item_set = transition.second; + const ParseItemSet &next_item_set = transition.second.first; + const PrecedenceRange &precedence = transition.second.second; ParseAction *new_action = add_action( state_id, symbol, - ParseAction::Shift(0, precedence_values_for_item_set(next_item_set)), + ParseAction::Shift(0, precedence), item_set); if (new_action) new_action->state_index = add_parse_state(next_item_set); @@ -319,16 +320,6 @@ class ParseTableBuilder { return 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; - if (item.step_index > 0) - result.add(item.production->at(item.step_index - 1).precedence); - } - return result; - } - string symbol_name(const rules::Symbol &symbol) const { if (symbol.is_built_in()) { if (symbol == rules::ERROR()) diff --git a/src/compiler/build_tables/parse_item.cc b/src/compiler/build_tables/parse_item.cc index 1209d808..1a285a10 100644 --- a/src/compiler/build_tables/parse_item.cc +++ b/src/compiler/build_tables/parse_item.cc @@ -104,8 +104,8 @@ size_t ParseItemSet::Hash::operator()(const ParseItemSet &item_set) const { return result; } -map ParseItemSet::transitions() const { - map result; +ParseItemSet::TransitionMap ParseItemSet::transitions() const { + ParseItemSet::TransitionMap result; for (const auto &pair : entries) { const ParseItem &item = pair.first; const LookaheadSet &lookahead_symbols = pair.second; @@ -114,9 +114,11 @@ map ParseItemSet::transitions() const { size_t step = item.step_index + 1; Symbol symbol = item.production->at(item.step_index).symbol; + int precedence = item.production->at(item.step_index).precedence; ParseItem new_item(item.lhs(), *item.production, step); - result[symbol].entries[new_item] = lookahead_symbols; + result[symbol].first.entries[new_item] = lookahead_symbols; + result[symbol].second.add(precedence); } return result; diff --git a/src/compiler/build_tables/parse_item.h b/src/compiler/build_tables/parse_item.h index ba4d747b..b7f1cea8 100644 --- a/src/compiler/build_tables/parse_item.h +++ b/src/compiler/build_tables/parse_item.h @@ -7,6 +7,7 @@ #include "compiler/rules/symbol.h" #include "compiler/rules/metadata.h" #include "compiler/syntax_grammar.h" +#include "compiler/precedence_range.h" namespace tree_sitter { namespace build_tables { @@ -37,7 +38,9 @@ class ParseItemSet { ParseItemSet(); explicit ParseItemSet(const std::map &); - std::map transitions() const; + typedef std::map> TransitionMap; + + TransitionMap transitions() const; bool operator==(const ParseItemSet &) const; std::map entries;