Add text pattern handling to property table generation

This commit is contained in:
Max Brunsfeld 2018-10-04 15:03:17 -07:00
parent 9c6f5c9836
commit 277bf2f03d
5 changed files with 52 additions and 5 deletions

View file

@ -107,6 +107,7 @@ struct hash<tree_sitter::PropertyTransition> {
hash_combine(&result, transition.type);
hash_combine(&result, transition.named);
hash_combine(&result, transition.index);
hash_combine(&result, transition.text_pattern);
hash_combine(&result, transition.state_id);
return result;
}
@ -253,6 +254,7 @@ struct PropertyTableBuilder {
unsigned result = selector.size();
for (const PropertySelectorStep &step : selector) {
if (step.index != -1) result++;
if (!step.text_pattern.empty()) result++;
}
return result;
}
@ -262,7 +264,8 @@ struct PropertyTableBuilder {
return
step.type == transition.type &&
step.named == transition.named &&
(step.index == transition.index || step.index == -1);
(step.index == transition.index || step.index == -1) &&
(step.text_pattern == transition.text_pattern || step.text_pattern.empty());
}
void populate_state(const PropertyItemSet &item_set, StateId state_id) {
@ -280,6 +283,7 @@ struct PropertyTableBuilder {
next_step->type,
next_step->named,
next_step->index,
next_step->text_pattern,
0
}] = PropertyItemSet();
}
@ -329,6 +333,9 @@ struct PropertyTableBuilder {
result.states[state_id].transitions.push_back(transition);
}
auto &transition_list = result.states[state_id].transitions;
std::sort(transition_list.begin(), transition_list.end());
// Compute the default successor item set - the item set that
// we should advance to if the next element doesn't match any
// of the next elements in the item set's selectors.

View file

@ -74,14 +74,18 @@ class CodeGenerator {
void add_transition(const PropertyTransition &transition) {
add("{");
add("\"type\":\"");
add(transition.type);
add("\",\"named\":");
add("\"type\":");
add_string(transition.type);
add(",\"named\":");
add(transition.named ? "true" : "false");
if (transition.index != -1) {
add(",\"index\":");
add(to_string(transition.index));
}
if (!transition.text_pattern.empty()) {
add(",\"text\":");
add_string(transition.text_pattern);
}
add(",\"state_id\": ");
add(to_string(transition.state_id));
add("}");
@ -89,13 +93,20 @@ class CodeGenerator {
void add_string(const string &s) {
add("\"");
add(s);
for (const char c : s) {
if (c == '"') add("\\");
add(c);
}
add("\"");
}
void add(string input) {
buffer += input;
}
void add(char c) {
buffer += c;
}
};
string property_table_json(PropertyTable table) {

View file

@ -409,6 +409,11 @@ Result<PropertyRule> parse_property_rule_json(json_value *rule_json) {
step.index = -1;
}
json_value text_pattern_json = selector_step_json->operator[]("text");
if (text_pattern_json.type == json_string) {
step.text_pattern = text_pattern_json.u.string.ptr;
}
selector.push_back(step);
}

View file

@ -12,6 +12,7 @@ struct PropertySelectorStep {
bool named;
bool is_immediate;
int index;
std::string text_pattern;
inline bool operator==(const PropertySelectorStep &other) const {
return

View file

@ -12,6 +12,7 @@ struct PropertyTransition {
std::string type;
bool named;
int index;
std::string text_pattern;
unsigned state_id;
bool operator==(const PropertyTransition &other) const {
@ -19,8 +20,30 @@ struct PropertyTransition {
type == other.type &&
named == other.named &&
index == other.index &&
text_pattern == other.text_pattern &&
state_id == other.state_id;
}
bool operator<(const PropertyTransition &other) const {
if (type < other.type) return true;
if (type > other.type) return false;
if (named && !other.named) return true;
if (!named && other.named) return false;
// The lack of a specific child index is represented as -1.
// It should be sorted *after* transitions with a specific
// child index.
if (index > other.index) return true;
if (index < other.index) return false;
// The lack of a text pattern is represented as the empty string.
// This should be sorted *after* transitions with a specific
// text pattern.
if (text_pattern.size() > other.text_pattern.size()) return true;
if (text_pattern.size() < other.text_pattern.size()) return false;
return state_id < other.state_id;
}
};
struct PropertyState {