🔥 get_metadata function
This commit is contained in:
parent
73b3280fbb
commit
c8be143f65
9 changed files with 26 additions and 214 deletions
|
|
@ -15,7 +15,6 @@
|
|||
'src/compiler/build_tables/build_tables.cc',
|
||||
'src/compiler/build_tables/does_match_any_line.cc',
|
||||
'src/compiler/build_tables/get_completion_status.cc',
|
||||
'src/compiler/build_tables/get_metadata.cc',
|
||||
'src/compiler/build_tables/item_set_closure.cc',
|
||||
'src/compiler/build_tables/lex_item.cc',
|
||||
'src/compiler/build_tables/lex_item_transitions.cc',
|
||||
|
|
|
|||
|
|
@ -1,107 +0,0 @@
|
|||
#include "compiler/compiler_spec_helper.h"
|
||||
#include "compiler/rules/metadata.h"
|
||||
#include "compiler/build_tables/get_metadata.h"
|
||||
|
||||
using namespace rules;
|
||||
using namespace build_tables;
|
||||
|
||||
START_TEST
|
||||
|
||||
describe("get_metadata(rule, key)", []() {
|
||||
MetadataKey key1 = MetadataKey(100);
|
||||
MetadataKey key2 = MetadataKey(101);
|
||||
rule_ptr rule;
|
||||
|
||||
describe("with a rule without the metadata key", [&]() {
|
||||
it("returns the zero range", [&]() {
|
||||
rule = sym("x");
|
||||
AssertThat(get_metadata(rule, key1), Equals(MetadataRange(0, 0)));
|
||||
|
||||
rule = seq({ sym("x"), sym("y") });
|
||||
AssertThat(get_metadata(rule, key1), Equals(MetadataRange(0, 0)));
|
||||
|
||||
rule = metadata(seq({ sym("x"), sym("y") }), {{key2, 5}});
|
||||
AssertThat(get_metadata(rule, key1), Equals(MetadataRange(0, 0)));
|
||||
});
|
||||
});
|
||||
|
||||
describe("when given a metadata rule", [&]() {
|
||||
before_each([&]() {
|
||||
rule = make_shared<Metadata>(sym("x"), map<MetadataKey, int>({
|
||||
{ key1, 1 },
|
||||
{ key2, 2 },
|
||||
}));
|
||||
});
|
||||
|
||||
it("returns the value for the given key", [&]() {
|
||||
AssertThat(get_metadata(rule, key1), Equals(MetadataRange(1, 1)));
|
||||
AssertThat(get_metadata(rule, key2), Equals(MetadataRange(2, 2)));
|
||||
});
|
||||
|
||||
it("returns 0 if the rule does not have the key", [&]() {
|
||||
AssertThat(get_metadata(rule, MetadataKey(0)), Equals(MetadataRange(0, 0)));
|
||||
});
|
||||
|
||||
describe("when the rule contains another metadata rule", [&]() {
|
||||
it("also gets metadata from the inner metadata rule", [&]() {
|
||||
rule = make_shared<Metadata>(make_shared<Metadata>(sym("x"), map<MetadataKey, int>({
|
||||
{ key1, 1 }
|
||||
})), map<MetadataKey, int>());
|
||||
|
||||
AssertThat(get_metadata(rule, key1), Equals(MetadataRange(1, 1)));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("with a sequence starting with a metadata rule", [&]() {
|
||||
it("returns the metadata rule's value for the key", [&]() {
|
||||
rule = seq({
|
||||
metadata(sym("x"), {{key1, 5}}),
|
||||
sym("y")
|
||||
});
|
||||
|
||||
AssertThat(get_metadata(rule, key1), Equals(MetadataRange(5, 5)));
|
||||
});
|
||||
});
|
||||
|
||||
describe("with a sequence whose starting value can be blank", [&]() {
|
||||
it("includes later elements of the sequence in the returned range", [&]() {
|
||||
rule = seq({
|
||||
repeat(metadata(sym("x"), {{key1, 3}})),
|
||||
choice({ metadata(sym("x"), {{key1, 5}}), blank() }),
|
||||
metadata(sym("x"), {{key1, 7}}),
|
||||
metadata(sym("x"), {{key1, 9}}),
|
||||
});
|
||||
|
||||
AssertThat(get_metadata(rule, key1), Equals(MetadataRange(3, 7)));
|
||||
});
|
||||
});
|
||||
|
||||
describe("with a sequence whose starting value can be blank", [&]() {
|
||||
it("includes later elements of the sequence in the returned range", [&]() {
|
||||
rule = seq({
|
||||
repeat(metadata(sym("x"), {{key1, 3}})),
|
||||
choice({ metadata(sym("x"), {{key1, 5}}), blank() }),
|
||||
metadata(sym("x"), {{key1, 7}}),
|
||||
metadata(sym("x"), {{key1, 9}}),
|
||||
});
|
||||
|
||||
AssertThat(get_metadata(rule, key1), Equals(MetadataRange(3, 7)));
|
||||
});
|
||||
});
|
||||
|
||||
describe("with a choice rule", [&]() {
|
||||
it("merges the ranges for the choices elements", [&]() {
|
||||
rule = choice({
|
||||
metadata(sym("a"), {{key1, 5}}),
|
||||
metadata(sym("b"), {{key1, 3}}),
|
||||
sym("c"),
|
||||
metadata(sym("d"), {{key1, 1}}),
|
||||
});
|
||||
|
||||
AssertThat(get_metadata(rule, key1), Equals(MetadataRange(1, 5)));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
END_TEST
|
||||
|
|
@ -5,7 +5,6 @@
|
|||
#include "compiler/syntax_grammar.h"
|
||||
#include "compiler/build_tables/parse_item.h"
|
||||
#include "compiler/build_tables/lex_item.h"
|
||||
#include "compiler/build_tables/get_metadata.h"
|
||||
|
||||
namespace tree_sitter {
|
||||
|
||||
|
|
@ -138,11 +137,6 @@ std::ostream &operator<<(std::ostream &stream, const ParseItemSet &item_set) {
|
|||
return stream << item_set.entries;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &stream, const MetadataRange &range) {
|
||||
return stream << string("{") << to_string(range.min) << string(", ")
|
||||
<< to_string(range.max) << string("}");
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &stream, const LookaheadSet &set) {
|
||||
return stream << *set.entries;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,14 +111,12 @@ ostream &operator<<(ostream &, const PrecedenceRange &);
|
|||
|
||||
namespace build_tables {
|
||||
|
||||
struct MetadataRange;
|
||||
class LexItem;
|
||||
class LexItemSet;
|
||||
class ParseItem;
|
||||
class ParseItemSet;
|
||||
class LookaheadSet;
|
||||
|
||||
ostream &operator<<(ostream &, const MetadataRange &);
|
||||
ostream &operator<<(ostream &, const LexItem &);
|
||||
ostream &operator<<(ostream &, const LexItemSet &);
|
||||
ostream &operator<<(ostream &, const ParseItem &);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
#include "compiler/parse_table.h"
|
||||
#include "compiler/build_tables/parse_conflict_manager.h"
|
||||
#include "compiler/build_tables/parse_item.h"
|
||||
#include "compiler/build_tables/get_metadata.h"
|
||||
#include "compiler/build_tables/item_set_closure.h"
|
||||
#include "compiler/lexical_grammar.h"
|
||||
#include "compiler/syntax_grammar.h"
|
||||
|
|
|
|||
|
|
@ -1,67 +0,0 @@
|
|||
#include "compiler/build_tables/get_metadata.h"
|
||||
#include <utility>
|
||||
#include "compiler/rules/visitor.h"
|
||||
#include "compiler/rules/seq.h"
|
||||
#include "compiler/rules/repeat.h"
|
||||
#include "compiler/rules/choice.h"
|
||||
#include "compiler/build_tables/rule_can_be_blank.h"
|
||||
|
||||
namespace tree_sitter {
|
||||
namespace build_tables {
|
||||
|
||||
using std::pair;
|
||||
|
||||
MetadataRange get_metadata(const rule_ptr &rule, rules::MetadataKey key) {
|
||||
class GetMetadata : public rules::RuleFn<pair<MetadataRange, bool>> {
|
||||
rules::MetadataKey metadata_key;
|
||||
|
||||
public:
|
||||
explicit GetMetadata(rules::MetadataKey key) : metadata_key(key) {}
|
||||
|
||||
protected:
|
||||
pair<MetadataRange, bool> apply_to(const rules::Metadata *rule) {
|
||||
pair<MetadataRange, bool> result = apply(rule->rule);
|
||||
if (result.second) {
|
||||
return result;
|
||||
} else {
|
||||
int value = rule->value_for(metadata_key);
|
||||
return { { value, value }, value != 0 };
|
||||
}
|
||||
}
|
||||
|
||||
pair<MetadataRange, bool> apply_to(const rules::Choice *rule) {
|
||||
pair<MetadataRange, bool> result(MetadataRange(0, 0), false);
|
||||
for (const auto &element : rule->elements)
|
||||
merge_result(&result, apply(element));
|
||||
return result;
|
||||
}
|
||||
|
||||
pair<MetadataRange, bool> apply_to(const rules::Seq *rule) {
|
||||
pair<MetadataRange, bool> result = apply(rule->left);
|
||||
if (rule_can_be_blank(rule->left))
|
||||
merge_result(&result, apply(rule->right));
|
||||
return result;
|
||||
}
|
||||
|
||||
pair<MetadataRange, bool> apply_to(const rules::Repeat *rule) {
|
||||
return apply(rule->content);
|
||||
}
|
||||
|
||||
private:
|
||||
void merge_result(pair<MetadataRange, bool> *left,
|
||||
const pair<MetadataRange, bool> &right) {
|
||||
if (right.second) {
|
||||
if (!left->second || right.first.min < left->first.min)
|
||||
left->first.min = right.first.min;
|
||||
if (!left->second || right.first.max > left->first.max)
|
||||
left->first.max = right.first.max;
|
||||
left->second = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return GetMetadata(key).apply(rule).first;
|
||||
}
|
||||
|
||||
} // namespace build_tables
|
||||
} // namespace tree_sitter
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
#ifndef COMPILER_BUILD_TABLES_GET_METADATA_H_
|
||||
#define COMPILER_BUILD_TABLES_GET_METADATA_H_
|
||||
|
||||
#include "compiler/rules/metadata.h"
|
||||
#include "tree_sitter/compiler.h"
|
||||
|
||||
namespace tree_sitter {
|
||||
namespace build_tables {
|
||||
|
||||
struct MetadataRange {
|
||||
MetadataRange() : min(0), max(0) {}
|
||||
MetadataRange(int min, int max) : min(min), max(max) {}
|
||||
|
||||
bool operator==(const MetadataRange &other) const {
|
||||
return min == other.min && max == other.max;
|
||||
}
|
||||
|
||||
int min;
|
||||
int max;
|
||||
};
|
||||
|
||||
MetadataRange get_metadata(const rule_ptr &, rules::MetadataKey);
|
||||
|
||||
} // namespace build_tables
|
||||
} // namespace tree_sitter
|
||||
|
||||
#endif // COMPILER_BUILD_TABLES_GET_METADATA_H_
|
||||
|
|
@ -1,8 +1,12 @@
|
|||
#include "compiler/build_tables/lex_item.h"
|
||||
#include <unordered_set>
|
||||
#include "compiler/build_tables/get_metadata.h"
|
||||
#include "compiler/build_tables/lex_item_transitions.h"
|
||||
#include "compiler/build_tables/rule_can_be_blank.h"
|
||||
#include "compiler/rules/choice.h"
|
||||
#include "compiler/rules/metadata.h"
|
||||
#include "compiler/rules/seq.h"
|
||||
#include "compiler/rules/symbol.h"
|
||||
#include "compiler/rules/visitor.h"
|
||||
|
||||
namespace tree_sitter {
|
||||
namespace build_tables {
|
||||
|
|
@ -22,7 +26,25 @@ bool LexItem::operator==(const LexItem &other) const {
|
|||
}
|
||||
|
||||
bool LexItem::is_token_start() const {
|
||||
return get_metadata(rule, rules::START_TOKEN).max > 0;
|
||||
class IsTokenStart : public rules::RuleFn<bool> {
|
||||
bool apply_to(const rules::Seq *rule) {
|
||||
return apply(rule->left) ||
|
||||
(rule_can_be_blank(rule->left) && apply(rule->right));
|
||||
}
|
||||
|
||||
bool apply_to(const rules::Metadata *rule) {
|
||||
return (rule->value_for(rules::START_TOKEN) > 0) || apply(rule->rule);
|
||||
}
|
||||
|
||||
bool apply_to(const rules::Choice *rule) {
|
||||
for (const rule_ptr &element : rule->elements)
|
||||
if (apply(element))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return IsTokenStart().apply(rule);
|
||||
}
|
||||
|
||||
size_t LexItem::Hash::operator()(const LexItem &item) const {
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ class LexItemTransitions : public rules::RuleFn<void> {
|
|||
merge_transition(transitions, *rule,
|
||||
LexItemSet({
|
||||
LexItem(item_lhs, rules::Blank::build()),
|
||||
}), PrecedenceRange());
|
||||
}),
|
||||
PrecedenceRange());
|
||||
}
|
||||
|
||||
void apply_to(const rules::Choice *rule) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue