C++ Tools: apply clang-format on cplusplus-keywordgen.cpp

There is no history for this file after it was moved, so there's no harm
of beautifying it to be able to read and change.

Change-Id: Iec2ad5bc9d8553589b2d2512f69991f772808d89
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
Volodymyr Zibarov
2020-05-26 13:05:07 +03:00
parent 078ca0cdff
commit fcf364d61a

View File

@@ -19,16 +19,16 @@
// ### TODO: Rewrite me. // ### TODO: Rewrite me.
#include <string>
#include <iostream>
#include <map>
#include <list>
#include <vector>
#include <set>
#include <cstdlib>
#include <cctype>
#include <functional>
#include <algorithm> #include <algorithm>
#include <cctype>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
class State; class State;
class DottedItem; class DottedItem;
@@ -40,102 +40,108 @@ typedef StateList::iterator StatePtr;
typedef std::string::iterator Dot; typedef std::string::iterator Dot;
typedef std::vector<DottedItem>::iterator DottedItemPtr; typedef std::vector<DottedItem>::iterator DottedItemPtr;
class DottedItem { class DottedItem
{
public: public:
RulePtr rule; RulePtr rule;
Dot dot; Dot dot;
DottedItem() {} DottedItem() {}
DottedItem(RulePtr rule, Dot dot): DottedItem(RulePtr rule, Dot dot)
rule(rule), dot(dot) {} : rule(rule)
, dot(dot)
{}
bool operator == (const DottedItem &other) const { bool operator==(const DottedItem &other) const
return rule == other.rule && dot == other.dot; {
} return rule == other.rule && dot == other.dot;
}
bool operator != (const DottedItem &other) const { bool operator!=(const DottedItem &other) const { return !operator==(other); }
return ! operator == (other);
}
bool terminal() const { bool terminal() const { return dot == rule->end(); }
return dot == rule->end();
}
DottedItem next() const { DottedItem next() const
DottedItem item; {
item.rule = rule; DottedItem item;
item.dot = dot; item.rule = rule;
++item.dot; item.dot = dot;
return item; ++item.dot;
} return item;
}
}; };
class State { class State
{
public: public:
State() {} State() {}
template <typename _ForwardIterator> template<typename _ForwardIterator>
State(_ForwardIterator first, _ForwardIterator last) { State(_ForwardIterator first, _ForwardIterator last)
_items.insert(_items.end(), first, last); {
} _items.insert(_items.end(), first, last);
static State &intern(const State &state) {
StatePtr ptr = std::find(first_state(), last_state(), state);
if (ptr == last_state())
ptr = states().insert(last_state(), state);
return *ptr;
}
State &next(char ch) {
std::vector<DottedItem> n;
for (DottedItemPtr it = first_item(); it != last_item(); ++it) {
if (! it->terminal() && *it->dot == ch)
n.push_back(it->next());
} }
return intern(State(n.begin(), n.end()));
}
std::set<char> firsts() { static State &intern(const State &state)
std::set<char> s; {
for (DottedItemPtr it = first_item(); it != last_item(); ++it) { StatePtr ptr = std::find(first_state(), last_state(), state);
if (! it->terminal()) if (ptr == last_state())
s.insert(*it->dot); ptr = states().insert(last_state(), state);
return *ptr;
} }
return s;
}
size_t item_count() const { return _items.size(); } State &next(char ch)
{
std::vector<DottedItem> n;
for (DottedItemPtr it = first_item(); it != last_item(); ++it) {
if (!it->terminal() && *it->dot == ch)
n.push_back(it->next());
}
return intern(State(n.begin(), n.end()));
}
DottedItemPtr first_item() { return _items.begin(); } std::set<char> firsts()
DottedItemPtr last_item() { return _items.end(); } {
std::set<char> s;
for (DottedItemPtr it = first_item(); it != last_item(); ++it) {
if (!it->terminal())
s.insert(*it->dot);
}
return s;
}
static StatePtr first_state() { return states().begin(); } size_t item_count() const { return _items.size(); }
static StatePtr last_state() { return states().end(); }
bool operator == (const State &other) const { return _items == other._items; } DottedItemPtr first_item() { return _items.begin(); }
bool operator != (const State &other) const { return _items != other._items; } DottedItemPtr last_item() { return _items.end(); }
template <typename _Iterator> static StatePtr first_state() { return states().begin(); }
static State &start(_Iterator first, _Iterator last) { static StatePtr last_state() { return states().end(); }
std::vector<DottedItem> items;
for (; first != last; ++first)
items.push_back(DottedItem(first, first->begin()));
return intern(State(items.begin(), items.end()));
}
static void reset() { bool operator==(const State &other) const { return _items == other._items; }
states().clear(); bool operator!=(const State &other) const { return _items != other._items; }
}
template<typename _Iterator>
static State &start(_Iterator first, _Iterator last)
{
std::vector<DottedItem> items;
for (; first != last; ++first)
items.push_back(DottedItem(first, first->begin()));
return intern(State(items.begin(), items.end()));
}
static void reset() { states().clear(); }
private: private:
static StateList &states() { static StateList &states()
static StateList _states; {
return _states; static StateList _states;
} return _states;
}
private: private:
std::vector<DottedItem> _items; std::vector<DottedItem> _items;
}; };
static bool option_no_enums = false; static bool option_no_enums = false;
@@ -147,186 +153,201 @@ static std::string option_unicode_function = "";
std::string token_id(const std::string &id) std::string token_id(const std::string &id)
{ {
std::string token = option_token_prefix; std::string token = option_token_prefix;
if (! option_toupper) if (!option_toupper)
token += id; token += id;
else { else {
for (size_t i = 0; i < id.size(); ++i) for (size_t i = 0; i < id.size(); ++i)
token += toupper(id[i]); token += toupper(id[i]);
} }
return token; return token;
} }
bool starts_with(const std::string &line, const std::string &text) { bool starts_with(const std::string &line, const std::string &text)
if (text.length() < line.length()) { {
return std::equal(line.begin(), line.begin() + text.size(), text.begin()); if (text.length() < line.length()) {
} return std::equal(line.begin(), line.begin() + text.size(), text.begin());
return false; }
return false;
} }
void doit(State &state) void doit(State &state)
{ {
static int depth{0}; static int depth{0};
++depth; ++depth;
std::string indent(depth * 2, ' '); std::string indent(depth * 2, ' ');
std::set<char> firsts = state.firsts(); std::set<char> firsts = state.firsts();
for (std::set<char>::iterator it = firsts.begin(); it != firsts.end(); ++it) { for (std::set<char>::iterator it = firsts.begin(); it != firsts.end(); ++it) {
std::string _else = it == firsts.begin() ? "" : "else "; std::string _else = it == firsts.begin() ? "" : "else ";
std::cout << indent << _else << "if (s[" << (depth - 1) << "]" << option_unicode_function << " == '" << *it << "') {" << std::endl; std::cout << indent << _else << "if (s[" << (depth - 1) << "]" << option_unicode_function
State &next_state = state.next(*it); << " == '" << *it << "') {" << std::endl;
State &next_state = state.next(*it);
bool found = false; bool found = false;
for (DottedItemPtr item = next_state.first_item(); item != next_state.last_item(); ++item) { for (DottedItemPtr item = next_state.first_item(); item != next_state.last_item(); ++item) {
if (item->terminal()) { if (item->terminal()) {
if (found) { if (found) {
std::cerr << "*** Error. Too many accepting states" << std::endl; std::cerr << "*** Error. Too many accepting states" << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
found = true; found = true;
std::cout << indent << " return " << option_namespace_name << token_id(*item->rule) << ";" << std::endl; std::cout << indent << " return " << option_namespace_name << token_id(*item->rule)
} << ";" << std::endl;
}
}
if (!found)
doit(next_state);
std::cout << indent << "}" << std::endl;
} }
if (! found) --depth;
doit(next_state);
std::cout << indent << "}" << std::endl;
}
--depth;
} }
void gen_classify_n(State &start_state, int N) void gen_classify_n(State &start_state, int N)
{ {
std::cout << "static inline int classify" << N << "(const " << option_char_type << " *s) {" << std::endl; std::cout << "static inline int classify" << N << "(const " << option_char_type << " *s) {"
doit(start_state); << std::endl;
std::cout << " return " << option_namespace_name << token_id("identifier") << ";" << std::endl doit(start_state);
<< "}" << std::endl << std::endl; std::cout << " return " << option_namespace_name << token_id("identifier") << ";" << std::endl
<< "}" << std::endl
<< std::endl;
} }
void gen_classify(const std::multimap<size_t, std::string> &keywords) void gen_classify(const std::multimap<size_t, std::string> &keywords)
{ {
std::cout << "int " << option_namespace_name << "classify(const " << option_char_type << " *s, int n) {" << std::endl std::cout << "int " << option_namespace_name << "classify(const " << option_char_type
<< " switch (n) {" << std::endl; << " *s, int n) {" << std::endl
std::multimap<size_t, std::string>::const_iterator it = keywords.begin(); << " switch (n) {" << std::endl;
while (it != keywords.end()) { std::multimap<size_t, std::string>::const_iterator it = keywords.begin();
size_t size = it->first; while (it != keywords.end()) {
std::cout << " case " << size << ": return classify" << size << "(s);" << std::endl; size_t size = it->first;
do { ++it; } while (it != keywords.end() && it->first == size); std::cout << " case " << size << ": return classify" << size << "(s);" << std::endl;
} do {
std::cout << " default: return " << option_namespace_name << token_id("identifier") << ";" << std::endl ++it;
<< " } // switch" << std::endl } while (it != keywords.end() && it->first == size);
<< "}" << std::endl << std::endl; }
std::cout << " default: return " << option_namespace_name << token_id("identifier") << ";"
<< std::endl
<< " } // switch" << std::endl
<< "}" << std::endl
<< std::endl;
} }
void gen_enums(const std::multimap<size_t, std::string> &keywords) void gen_enums(const std::multimap<size_t, std::string> &keywords)
{ {
std::cout << "enum {" << std::endl; std::cout << "enum {" << std::endl;
std::multimap<size_t, std::string>::const_iterator it = keywords.begin(); std::multimap<size_t, std::string>::const_iterator it = keywords.begin();
for (; it != keywords.end(); ++it) { for (; it != keywords.end(); ++it) {
std::cout << " " << token_id(it->second) << "," << std::endl; std::cout << " " << token_id(it->second) << "," << std::endl;
}
std::cout << " " << token_id("identifier") << std::endl
<< "};" << std::endl << std::endl;
}
inline bool not_whitespace_p(char ch) {
return ! std::isspace(ch);
}
int main(int argc, char *argv[]) {
const std::string ns = "--namespace=";
for (int i = 0; i < argc; ++i) {
const std::string arg(argv[i]);
if (arg == "--no-enums")
option_no_enums = true;
else if (starts_with(arg, ns)) {
option_namespace_name.assign(arg.begin() + ns.size(), arg.end());
option_namespace_name += "::";
} }
} std::cout << " " << token_id("identifier") << std::endl << "};" << std::endl << std::endl;
}
std::multimap<size_t, std::string> keywords;
std::string textline; inline bool not_whitespace_p(char ch)
{
bool readKeywords = false; return !std::isspace(ch);
}
const std::string opt_no_enums = "%no-enums";
const std::string opt_toupper = "%toupper"; int main(int argc, char *argv[])
const std::string opt_ns = "%namespace="; {
const std::string opt_tok_prefix = "%token-prefix="; const std::string ns = "--namespace=";
const std::string opt_char_type = "%char-type=";
const std::string opt_unicode_function = "%unicode-function="; for (int i = 0; i < argc; ++i) {
const std::string arg(argv[i]);
while (getline(std::cin, textline)) { if (arg == "--no-enums")
option_no_enums = true;
// remove trailing spaces else if (starts_with(arg, ns)) {
textline.assign(textline.begin(), std::find_if(textline.rbegin(), textline.rend(), not_whitespace_p).base()); option_namespace_name.assign(arg.begin() + ns.size(), arg.end());
option_namespace_name += "::";
if (! readKeywords) { }
if (textline.size() >= 2 && textline[0] == '%') { }
if (textline[1] == '%') {
readKeywords = true; std::multimap<size_t, std::string> keywords;
} else if (textline == opt_no_enums) { std::string textline;
option_no_enums = true;
} else if (textline == opt_toupper) { bool readKeywords = false;
option_toupper = true;
} else if (starts_with(textline, opt_tok_prefix)) { const std::string opt_no_enums = "%no-enums";
option_token_prefix.assign(textline.begin() + opt_tok_prefix.size(), textline.end()); const std::string opt_toupper = "%toupper";
} else if (starts_with(textline, opt_char_type)) { const std::string opt_ns = "%namespace=";
option_char_type.assign(textline.begin() + opt_char_type.size(), textline.end()); const std::string opt_tok_prefix = "%token-prefix=";
} else if (starts_with(textline, opt_unicode_function)) { const std::string opt_char_type = "%char-type=";
option_unicode_function.assign(textline.begin() + opt_unicode_function.size(), textline.end()); const std::string opt_unicode_function = "%unicode-function=";
} else if (starts_with(textline, opt_ns)) {
option_namespace_name.assign(textline.begin() + opt_ns.size(), textline.end()); while (getline(std::cin, textline)) {
option_namespace_name += "::"; // remove trailing spaces
} textline.assign(textline.begin(),
std::find_if(textline.rbegin(), textline.rend(), not_whitespace_p).base());
continue;
} if (!readKeywords) {
std::cout << textline << std::endl; if (textline.size() >= 2 && textline[0] == '%') {
} else { if (textline[1] == '%') {
if (textline.empty()) readKeywords = true;
continue; } else if (textline == opt_no_enums) {
option_no_enums = true;
std::string::iterator start = textline.begin(); } else if (textline == opt_toupper) {
while (start != textline.end() && std::isspace(*start)) option_toupper = true;
++start; } else if (starts_with(textline, opt_tok_prefix)) {
option_token_prefix.assign(textline.begin() + opt_tok_prefix.size(),
std::string::iterator stop = start; textline.end());
while (stop != textline.end() && (std::isalnum(*stop) || *stop == '_')) } else if (starts_with(textline, opt_char_type)) {
++stop; option_char_type.assign(textline.begin() + opt_char_type.size(), textline.end());
} else if (starts_with(textline, opt_unicode_function)) {
if (start != stop) { option_unicode_function.assign(textline.begin() + opt_unicode_function.size(),
std::string keyword(start, stop); textline.end());
if (keyword == "identifier") { } else if (starts_with(textline, opt_ns)) {
std::cerr << "*** Error. `identifier' is reserved" << std::endl; option_namespace_name.assign(textline.begin() + opt_ns.size(), textline.end());
exit(EXIT_FAILURE); option_namespace_name += "::";
} }
keywords.insert(std::make_pair(keyword.size(), keyword)); continue;
} }
} std::cout << textline << std::endl;
} } else {
if (textline.empty())
if (! option_no_enums) continue;
gen_enums(keywords);
std::string::iterator start = textline.begin();
std::multimap<size_t, std::string>::iterator it = keywords.begin(); while (start != textline.end() && std::isspace(*start))
while (it != keywords.end()) { ++start;
size_t size = it->first;
RuleList rules; std::string::iterator stop = start;
do { rules.push_back(it->second); ++it; } while (stop != textline.end() && (std::isalnum(*stop) || *stop == '_'))
while (it != keywords.end() && it->first == size); ++stop;
gen_classify_n(State::start(rules.begin(), rules.end()), size);
State::reset(); if (start != stop) {
} std::string keyword(start, stop);
if (keyword == "identifier") {
gen_classify(keywords); std::cerr << "*** Error. `identifier' is reserved" << std::endl;
exit(EXIT_FAILURE);
}
keywords.insert(std::make_pair(keyword.size(), keyword));
}
}
}
if (!option_no_enums)
gen_enums(keywords);
std::multimap<size_t, std::string>::iterator it = keywords.begin();
while (it != keywords.end()) {
size_t size = it->first;
RuleList rules;
do {
rules.push_back(it->second);
++it;
} while (it != keywords.end() && it->first == size);
gen_classify_n(State::start(rules.begin(), rules.end()), size);
State::reset();
}
gen_classify(keywords);
} }