forked from qt-creator/qt-creator
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:
@@ -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);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user