From 9017861eb00e1bf7f2784bb111bd1738e38a6357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B5=D0=BB=D0=B8=D0=BF=D0=B5=D0=BD=D0=BA=D0=BE=20?= =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD?= Date: Fri, 9 Feb 2018 21:44:38 +0000 Subject: [PATCH] git-svn-id: svn://db.shs.com.ru/pip@592 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5 --- src_main/code/picodeparser.cpp | 146 +++++++++++++++++++++++----- src_main/code/picodeparser.h | 9 +- src_main/core/pistring.cpp | 37 +++++++ src_main/core/pistring.h | 4 + utils/code_model_generator/main.cpp | 28 +++++- 5 files changed, 194 insertions(+), 30 deletions(-) diff --git a/src_main/code/picodeparser.cpp b/src_main/code/picodeparser.cpp index 8851df26..b8859461 100755 --- a/src_main/code/picodeparser.cpp +++ b/src_main/code/picodeparser.cpp @@ -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 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) diff --git a/src_main/code/picodeparser.h b/src_main/code/picodeparser.h index 252e586f..614c85d8 100755 --- a/src_main/code/picodeparser.h +++ b/src_main/code/picodeparser.h @@ -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 tmp_temp; + PIMap tmp_meta; }; diff --git a/src_main/core/pistring.cpp b/src_main/core/pistring.cpp index 437926cd..564cbab9 100755 --- a/src_main/core/pistring.cpp +++ b/src_main/core/pistring.cpp @@ -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()); diff --git a/src_main/core/pistring.h b/src_main/core/pistring.h index 92c655bd..30a796d0 100755 --- a/src_main/core/pistring.h +++ b/src_main/core/pistring.h @@ -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; diff --git a/utils/code_model_generator/main.cpp b/utils/code_model_generator/main.cpp index 46457298..291c8ef4 100755 --- a/utils/code_model_generator/main.cpp +++ b/utils/code_model_generator/main.cpp @@ -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) {