From 277bf2f03d8a9b7742cf59cc5b0f03ed06cf6338 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 4 Oct 2018 15:03:17 -0700 Subject: [PATCH] Add text pattern handling to property table generation --- .../build_tables/property_table_builder.cc | 9 +++++++- .../generate_code/property_table_json.cc | 19 +++++++++++---- src/compiler/parse_json.cc | 5 ++++ src/compiler/property_sheet.h | 1 + src/compiler/property_table.h | 23 +++++++++++++++++++ 5 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/compiler/build_tables/property_table_builder.cc b/src/compiler/build_tables/property_table_builder.cc index d19b471f..ec9d79db 100644 --- a/src/compiler/build_tables/property_table_builder.cc +++ b/src/compiler/build_tables/property_table_builder.cc @@ -107,6 +107,7 @@ struct hash { 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. diff --git a/src/compiler/generate_code/property_table_json.cc b/src/compiler/generate_code/property_table_json.cc index dabe2b2f..f2ca1061 100644 --- a/src/compiler/generate_code/property_table_json.cc +++ b/src/compiler/generate_code/property_table_json.cc @@ -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) { diff --git a/src/compiler/parse_json.cc b/src/compiler/parse_json.cc index 5ac8ffc4..0b32ad6f 100644 --- a/src/compiler/parse_json.cc +++ b/src/compiler/parse_json.cc @@ -409,6 +409,11 @@ Result 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); } diff --git a/src/compiler/property_sheet.h b/src/compiler/property_sheet.h index c7663175..38427d3d 100644 --- a/src/compiler/property_sheet.h +++ b/src/compiler/property_sheet.h @@ -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 diff --git a/src/compiler/property_table.h b/src/compiler/property_table.h index e7fb4b9f..eb1e0cb5 100644 --- a/src/compiler/property_table.h +++ b/src/compiler/property_table.h @@ -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 {