git-svn-id: svn://db.shs.com.ru/pip@592 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5

This commit is contained in:
2018-02-09 21:44:38 +00:00
parent 9a1c5deadd
commit 9017861eb0
5 changed files with 194 additions and 30 deletions

View File

@@ -84,14 +84,18 @@ PICodeParser::PICodeParser() {
void PICodeParser::parseFile(const PIString & file, bool follow_includes) {
clear();
parseFileInternal(file, follow_includes);
/*piForeachC (Entity * c, entities) {
/*piCout << "\n\n";
piForeachC (Entity * c, entities) {
piCout << "";
piCout << c->type << c->name << c->parent_scope << c->parents << c->children;
piCout << c->type << c->name << c->parent_scope << c->parents << c->children << c->meta;
if (c->parent_scope)
piCout << "parent" << c->parent_scope->name;
piForeachC (Member & m, c->members) {
piCout << m.type << m.name;
}
piCout << "Functions:";
piForeachC (Member & m, c->functions)
piCout << m.type << m.name << m.meta;
piCout << "Members:";
piForeachC (Member & m, c->members)
piCout << m.type << m.name << m.meta;
}
piCout << "\n\nDefines:";
piForeachC (Define & m, defines)
@@ -100,11 +104,12 @@ void PICodeParser::parseFile(const PIString & file, bool follow_includes) {
piForeachC (Macro & m, macros)
piCout << "Macro:" << m.name << m.args << m.value;
piCout << "\n\nClasses:";
piForeachC (Entity * c, entities)
piCout << "class" << c->name << c->parents;
piCout << "\n\nEnums:";
piForeachC (Enum & c, enums)
piCout << "enum" << c.name << c.members;
piForeachC (Enum & c, enums) {
piCout << "enum" << c.name << c.meta;
piForeachC (EnumeratorInfo & e, c.members)
piCout << " " << e.name << "=" << e.value << e.meta;
}
piCout << "\n\nTypedefs:";
piForeachC (Typedef & c, typedefs)
piCout << "typedef" << c;*/
@@ -223,6 +228,8 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
}
//piCout << fc;
pfc = procMacros(fc);
replaceMeta(pfc);
if (main) return true;
@@ -299,7 +306,9 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
if (pfc.left(4) == "enum") {
pfc.cutLeft(4);
tmp = pfc.takeCWord();
parseEnum(0, cur_namespace + tmp, pfc.takeRange("{", "}"));
pfc.trim();
MetaMap meta = maybeMeta(pfc);
parseEnum(0, cur_namespace + tmp, pfc.takeRange("{", "}"), meta);
pfc.takeSymbol();
continue;
}
@@ -332,8 +341,14 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc) {
PIString cd = fc.trimmed().removeAll('\n').replaceAll("\t", " ").replaceAll(" ", " "), pn;
MetaMap meta;
int ind = cd.find("$M");
if (ind >= 0) {
meta = tmp_meta.value(cd.takeMid(ind, 5));
cd.replaceAll(" ", " ");
}
//piCout << "found class <****\n" << cd << "\n****>";
int ind = cd.find(":");
ind = cd.find(":");
PIVector<Entity * > parents;
if (ind > 0) {
PIStringList pl = cd.takeMid(ind + 1).trim().split(",");
@@ -356,6 +371,7 @@ PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc)
//piCout << "found " << typename_ << cn;
if (cn.isEmpty()) return 0;
Entity * e = new Entity();
e->meta = meta;
e->name = cur_namespace + cn;
e->type = typename_;//(is_class ? "class" : "struct");
e->has_name = has_name;
@@ -403,7 +419,14 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
parseClass(ce, stmp);
continue;
}
if (cw == "enum") {tmp = fc.takeCWord(); parseEnum(ce, cur_namespace + tmp, fc.takeRange("{", "}")); fc.takeSymbol(); continue;}
if (cw == "enum") {
tmp = fc.takeCWord();
fc.trim();
MetaMap meta = maybeMeta(fc);
parseEnum(ce, cur_namespace + tmp, fc.takeRange("{", "}"), meta);
fc.takeSymbol();
continue;
}
if (cw == "friend") {fc.cutLeft(fc.find(";") + 1); continue;}
if (cw == "typedef") {ce->typedefs << parseTypedef(fc.takeLeft(fc.find(";"))); typedefs << ce->typedefs.back(); typedefs.back().first.insert(0, cur_namespace); if (ce->typedefs.back().first.isEmpty()) ce->typedefs.pop_back(); fc.takeSymbol(); continue;}
if (cw == "template") {
@@ -429,17 +452,41 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
}
bool PICodeParser::parseEnum(Entity * parent, const PIString & name, PIString fc) {
PICodeParser::MetaMap PICodeParser::parseMeta(PIString & fc) {
PICodeParser::MetaMap ret;
if (fc.isEmpty()) return ret;
PIStringList ml = fc.split(",");
piForeachC (PIString & m, ml) {
int i = m.find("=");
if (i < 0) continue;
PIString mv = m.mid(i + 1).trim();
if (mv.startsWith("\"")) mv.cutLeft(1);
if (mv.endsWith("\"")) mv.cutRight(1);
ret[m.left(i).trim()] = mv;
}
//piCout << ms << ret;
return ret;
}
bool PICodeParser::parseEnum(Entity * parent, const PIString & name, PIString fc, const MetaMap & meta) {
//piCout << "enum" << name << fc;
Enum e(name);
e.meta = meta;
PIStringList vl(fc.split(","));
PIString vn;
int cv = -1, ind = 0;
piForeachC (PIString & v, vl) {
piForeach (PIString & v, vl) {
MetaMap meta;
int mi = v.find("$M");
if (mi >= 0) {
meta = tmp_meta.value(v.takeMid(mi, 5));
v.replaceAll(" ", " ");
}
vn = v; ind = v.find("=");
if (ind > 0) {cv = v.right(v.size_s() - ind - 1).toInt(); vn = v.left(ind);}
if (ind < 0) ++cv;
e.members << EnumeratorInfo(vn.trim(), cv);
e.members << EnumeratorInfo(vn.trim(), cv, meta);
}
if (!e.members.isEmpty())
if (e.members.back().name.isEmpty())
@@ -478,22 +525,30 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
while (ts >= 0) {
ctemp = fc.mid(ts).takeRange("<", ">");
if (ctemp.isEmpty()) {te = ts + 1; ts = fc.find("<", te); continue;}
crepl = "$" + PIString::fromNumber(tmp_temp.size_s()).expandLeftTo(3, "0");
crepl = "$T" + PIString::fromNumber(tmp_temp.size_s()).expandLeftTo(3, "0");
fc.replace(ts, ctemp.size_s() + 2, crepl);
tmp_temp[crepl] = "<" + ctemp + ">";
ts = fc.find("<", te);
}
fc.replaceAll("\n", " ").replaceAll("\t", " ").replaceAll(" ", " ").replaceAll(", ", ",");
fc.replaceAll("\n", " ").replaceAll("\t", " ").replaceAll(" ", " ").replaceAll(", ", ",").replaceAll(" $M", "$M");
//piCout << "parse member" << fc;
PIStringList tl, al;
Member me;
//piCout << fc;
if (fc.contains("(")) {
MetaMap meta;
int ind = fc.find("$M");
if (ind >= 0) {
meta = tmp_meta.value(fc.takeMid(ind, 5));
fc.replaceAll(" ", " ");
}
fc.cutRight(fc.size_s() - fc.findLast(")") - 1);
te = fc.find("(");
//piCout << fc;
for (ts = te - 1; ts >= 0; --ts)
if (!_isCChar(fc[ts]) && !(fc[ts].isDigit())) break;
//piCout << "takeMid" << ts + 1 << te - ts - 1;
me.meta = meta;
me.name = fc.takeMid(ts + 1, te - ts - 1);
if (me.name == parent->name) return true;
me.arguments_full = fc.takeMid(ts + 2).cutRight(1).split(",");
@@ -542,17 +597,21 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
if (fc.startsWith("using") || !(fc.contains(' ') || fc.contains('\t') || fc.contains('\n'))) return true;
int bits = extractMemberBits(fc);
tl = fc.split(",");
//piCout << "member" << fc;
//piCout << "member" << fc << tl;
//piCout << "member after eb" << fc << ", bits =" << bits;
if (tl.isEmpty()) return true;
bool vn = true;
ctemp = tl.front();
ctemp = tl.front().trim();
PIString meta_t;
if (ctemp.contains("$M"))
meta_t = ctemp.takeMid(ctemp.find("$M"));
for (ts = ctemp.size_s() - 1; ts > 0; --ts) {
if (vn) {if (!_isCChar(ctemp[ts]) && !ctemp[ts].isDigit() && ctemp[ts] != '[' && ctemp[ts] != ']') vn = false;}
else {if (_isCChar(ctemp[ts]) || ctemp[ts].isDigit()) break;}
}
me.type = ctemp.takeLeft(ts + 1);
me.visibility = cur_def_vis;
ctemp += meta_t;
restoreTmpTemp(&me);
PIString type = " " + me.type;
if (type.find(" const ") >= 0) {
@@ -580,8 +639,10 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
tl[0] = ctemp.trim();
piForeachC (PIString & v, tl) {
crepl.clear();
me.name = v.trimmed();
me.type = type;
restoreTmpMeta(&me);
if (me.name.isEmpty()) continue;
if (me.name.contains("["))
crepl = me.name.takeMid(me.name.find("["), me.name.findLast("]") - me.name.find("[") + 1);
@@ -669,15 +730,32 @@ void PICodeParser::normalizeEntityNamespace(PIString & n) {
void PICodeParser::restoreTmpTemp(Member * e) {
int i = 0;
piForeach (PIString & a, e->arguments_full) {
while ((i = a.find("$")) >= 0)
a.replace(i, 4, tmp_temp[a.mid(i, 4)]);
while ((i = a.find("$T")) >= 0)
a.replace(i, 5, tmp_temp[a.mid(i, 5)]);
}
piForeach (PIString & a, e->arguments_type) {
while ((i = a.find("$")) >= 0)
a.replace(i, 4, tmp_temp[a.mid(i, 4)]);
while ((i = a.find("$T")) >= 0)
a.replace(i, 5, tmp_temp[a.mid(i, 5)]);
}
while ((i = e->type.find("$")) >= 0)
e->type.replace(i, 4, tmp_temp[e->type.mid(i, 4)]);
while ((i = e->type.find("$T")) >= 0)
e->type.replace(i, 5, tmp_temp[e->type.mid(i, 5)]);
}
void PICodeParser::restoreTmpMeta(PICodeParser::Member * e) {
int i = e->name.find("$M");
if (i < 0) return;
e->meta = tmp_meta[e->name.takeMid(i, 5)];
}
PICodeParser::MetaMap PICodeParser::maybeMeta(PIString & fc) {
PICodeParser::MetaMap ret;
if (fc.left(2) == "$M") {
ret = tmp_meta.value(fc.takeLeft(5));
fc.trim();
}
return ret;
}
@@ -751,6 +829,24 @@ double PICodeParser::defineValue(const PIString & dn) {
}
void PICodeParser::replaceMeta(PIString & dn) {
tmp_meta.clear();
if (dn.isEmpty()) return;
int s = dn.find("PIMETA");
while (s >= 0) {
int ms = 0, ml = 0;
ms = dn.findRange('(', ')', '\\', s + 6, &ml);
if (ms < 0) return;
PIString meta = dn.mid(ms, ml).trim();
PIString rm = "$M" + PIString::fromNumber(tmp_meta.size_s()).expandLeftTo(3, "0");
dn.replace(s, ms + ml + 1 - s, rm);
//piCout << "FOUND META \"" << meta << "\"";
tmp_meta[rm] = parseMeta(meta);
s = dn.find("PIMETA");
}
}
PICodeParser::Entity * PICodeParser::findEntityByName(const PIString & en) {
piForeach (Entity * e, entities)
if (e->name == en)

View File

@@ -107,7 +107,7 @@ public:
};
struct PIP_EXPORT EnumeratorInfo {
EnumeratorInfo(const PIString & n = PIString(), int v = 0) {name = n; value = v;}
EnumeratorInfo(const PIString & n = PIString(), int v = 0, const MetaMap & m = MetaMap()) {name = n; value = v; meta = m;}
MetaMap meta;
PIString name;
int value;
@@ -149,14 +149,18 @@ private:
bool parseDirective(PIString d);
Entity * parseClassDeclaration(const PIString & fc);
PIString parseClass(Entity * parent, PIString & fc);
bool parseEnum(Entity * parent, const PIString & name, PIString fc);
MetaMap parseMeta(PIString & fc);
bool parseEnum(Entity * parent, const PIString & name, PIString fc, const MetaMap & meta);
Typedef parseTypedef(PIString fc);
bool parseMember(Entity * parent, PIString & fc);
int extractMemberBits(PIString & fc);
void restoreTmpTemp(Member * e);
void restoreTmpMeta(Member * e);
MetaMap maybeMeta(PIString & fc);
bool macroCondition(const PIString & mif, PIString mifcond);
bool isDefineExists(const PIString & dn);
double defineValue(const PIString & dn);
void replaceMeta(PIString & dn);
PIString procMacros(PIString fc);
double procMacrosCond(PIString fc);
bool isDeclaration(const PIString & fc, int start, int * end);
@@ -174,6 +178,7 @@ private:
Visibility cur_def_vis;
PIString cur_namespace;
PIMap<PIString, PIString> tmp_temp;
PIMap<PIString, MetaMap> tmp_meta;
};

View File

@@ -697,6 +697,43 @@ int PIString::findCWord(const PIString & word, const int start) const {
}
int PIString::findRange(const PIChar & start, const PIChar & end, const PIChar & shield, const int start_index, int * len) const {
if (len) *len = 0;
bool trim_ = (start != ' ' && start != '\t' && start != '\n' && start != '\r'), eq = (start == end);
int sz = size_s(), ls = -1, le = -1, cnt = 0;
for (int i = start_index; i < sz; ++i) {
PIChar c = at(i);
if (c == shield) {++i; continue;}
if (trim_) {
if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
continue;
trim_ = false;
}
if (eq) {
if (c == start) {
if (cnt == 0) ls = i;
else {le = i; cnt = 0; break;}
cnt++;
}
} else {
if (c == start) {
if (cnt == 0) ls = i;
cnt++;
}
if (c == end) {
cnt--;
if (cnt == 0) le = i;
}
}
if (cnt <= 0) break;
}
//piCout << ls << le << cnt;
if (le < ls || ls < 0 || le < 0 || cnt != 0) return -1;
if (len) *len = le - ls - 1;
return ls + 1;
}
bool PIString::startsWith(const PIString & str) const {
if (size() < str.size()) return false;
return str == left(str.size());

View File

@@ -516,6 +516,10 @@ public:
//! \brief Search C-style word "word" from symbol at index "start" and return first occur position.
//! \details Example: \snippet pistring.cpp PIString::findCWord
int findCWord(const PIString & word, const int start = 0) const;
//! \brief Search range between "start" and "end" symbols at index "start_index" and return first occur position.
//! \details Example: \snippet pistring.cpp PIString::findRange
int findRange(const PIChar & start, const PIChar & end, const PIChar & shield = '\\', const int start_index = 0, int * len = 0) const;
//! \brief Return if string starts with "str"
bool startsWith(const PIString & str) const;

View File

@@ -58,6 +58,10 @@ void makeClassInfo(PIFile & f, const PICodeParser::Entity * e) {
f << "\tci->type = \"" << e->type << "\";\n";
f << "\tci->name = \"" << e->name << "\";\n";
f << "\tci->has_name = " << (e->has_name ? "true" : "false") << ";\n";
if (!e->meta.isEmpty()) {
for (PICodeParser::MetaMap::const_iterator i = e->meta.begin(); i != e->meta.end(); ++i)
f << "\tci->meta[\"" << i.key() << "\"] = \"" << i.value() << "\";\n";
}
f << "\t(*classesInfo)[ci->name] = ci;\n";
if (e->parent_scope) {
f << "\tpci = " << "classesInfo->value(\"" << e->parent_scope->name << "\", 0);\n";
@@ -66,7 +70,7 @@ void makeClassInfo(PIFile & f, const PICodeParser::Entity * e) {
piForeachC (PICodeParser::Entity * p, e->parents)
f << "\tci->parents << \"" << p->name << "\";\n";
piForeachC (PICodeParser::Member & m, e->members) {
f << "\tci->variables << TypeInfo(\"" << m.name << "\", \"" << m.type << "\"";
f << "\tti = TypeInfo(\"" << m.name << "\", \"" << m.type << "\"";
if (m.attributes != 0) {
bool fir = true;
f << ", ";
@@ -83,6 +87,11 @@ void makeClassInfo(PIFile & f, const PICodeParser::Entity * e) {
if (m.isBitfield())
f << ", " << m.bits;
f << ");\n";
if (!m.meta.isEmpty()) {
for (PICodeParser::MetaMap::const_iterator i = m.meta.begin(); i != m.meta.end(); ++i)
f << "\tti.meta[\"" << i.key() << "\"] = \"" << i.value() << "\";\n";
}
f << "\tci->variables << ti;\n";
}
PIString arg;
piForeachC (PICodeParser::Member & m, e->functions) {
@@ -117,6 +126,10 @@ void makeClassInfo(PIFile & f, const PICodeParser::Entity * e) {
if (con) f << ", Const";
f << ");\n";
}
if (!m.meta.isEmpty()) {
for (PICodeParser::MetaMap::const_iterator i = m.meta.begin(); i != m.meta.end(); ++i)
f << "\tfi->meta[\"" << i.key() << "\"] = \"" << i.value() << "\";\n";
}
}
}
@@ -128,9 +141,18 @@ void makeEnumInfo(PIFile & f, const PICodeParser::Enum * e) {
f << "\n\tei = new EnumInfo();\n";
f << "\t(*enumsInfo)[\"" << e->name << "\"] = ei;\n";
f << "\tei->name = \"" << e->name << "\";\n";
if (!e->meta.isEmpty()) {
for (PICodeParser::MetaMap::const_iterator i = e->meta.begin(); i != e->meta.end(); ++i)
f << "\tei->meta[\"" << i.key() << "\"] = \"" << i.value() << "\";\n";
}
}
piForeachC (PICodeParser::EnumeratorInfo & m, e->members)
piForeachC (PICodeParser::EnumeratorInfo & m, e->members) {
f << "\tei->members << PICodeInfo::EnumeratorInfo(\"" << m.name << "\", " << m.value << ");\n";
if (!e->meta.isEmpty()) {
for (PICodeParser::MetaMap::const_iterator i = e->meta.begin(); i != e->meta.end(); ++i)
f << "\tei->members.back().meta[\"" << i.key() << "\"] = \"" << i.value() << "\";\n";
}
}
}
@@ -310,7 +332,7 @@ void writeModel(PICodeParser & parser, PICLI & cli, const PIString out, bool met
f << "\n\n// Metainformation\n\n__ClassInfo_" << defname << "_Initializer__::__ClassInfo_" << defname << "_Initializer__() {\n";
f << "\tif (_inited_) return;\n\t_inited_ = true;\n\n";
if (meta) {
f << "\tClassInfo * ci, * pci = new ClassInfo();\n\tTypeInfo * ni;\n\tFunctionInfo * fi;\n";
f << "\tClassInfo * ci, * pci = new ClassInfo();\n\tTypeInfo * ni;\n\tFunctionInfo * fi;\n\tTypeInfo ti;\n";
f << "\t(*classesInfo)[\"\"] = pci;\n";
}
if (enums) {