* runtime - loading and translating * design-time - works with *.ts file (pip_tr utility) * compile-time - CMake macro for compile *.ts
140 lines
3.7 KiB
C++
140 lines
3.7 KiB
C++
#include "parser.h"
|
|
|
|
#include "piliterals_string.h"
|
|
#include "pistringlist.h"
|
|
|
|
|
|
PIString fromCode(const PIString & in) {
|
|
return in.replacedAll("\\n", '\n')
|
|
.replaceAll("\\r", '\r')
|
|
.replaceAll("\\t", '\t')
|
|
.replaceAll("\\\"", '"')
|
|
.replaceAll("\\'", '\'')
|
|
.replaceAll("\\\\", '\\');
|
|
}
|
|
|
|
|
|
void gatherStrings(TSFile::Content & content, const PIString & file, const PIString & file_loc, int & count_all, int & count_new) {
|
|
static const PIStringList methods({"PITranslator::tr", "PITranslator::trNoOp", "piTr", "piTrNoOp"});
|
|
static const PIStringList literals({"_tr", "_trNoOp"});
|
|
PIString source, context;
|
|
int pos = -1, ppos = 0, line = -1;
|
|
int len = 0;
|
|
auto isCLetter = [](const PIChar c) { return c.isAlpha() || c.isDigit() || c == '_'; };
|
|
auto add = [&content, file_loc, &count_all, &count_new](const PIString & source, const PIString & context, int line) {
|
|
if (source.isEmpty()) return;
|
|
++count_all;
|
|
if (content.contexts[context].confirm(fromCode(source), file_loc, line)) ++count_new;
|
|
// piCout << "Context = \"" << context << "\", message = \"" << source << "\" (" << file_loc << ":" << line << ")";
|
|
};
|
|
// piCout << "file" << file_loc;
|
|
for (const auto & kw: methods) {
|
|
// piCout << "method" << kw;
|
|
for (;;) {
|
|
source.clear();
|
|
context.clear();
|
|
|
|
pos = file.find(kw, pos + 1);
|
|
if (pos < 0) break;
|
|
if (pos > 0) {
|
|
auto pc = file[pos - 1];
|
|
if (isCLetter(pc) || pc == ':') {
|
|
pos += kw.size_s();
|
|
continue;
|
|
}
|
|
}
|
|
pos += kw.size_s();
|
|
if (pos < file.size_s() - 1) {
|
|
auto pc = file[pos];
|
|
if (isCLetter(pc) || pc == ':') {
|
|
pos += kw.size_s();
|
|
continue;
|
|
}
|
|
}
|
|
// piCout << "PITranslator" << pos;
|
|
|
|
pos = file.find('(', pos);
|
|
if (pos < 0) break;
|
|
// piCout << "(" << pos;
|
|
pos += 1;
|
|
|
|
pos = file.findRange('"', '"', '\\', pos, &len);
|
|
if (pos < 0) break;
|
|
// piCout << "\"" << pos;
|
|
source = file.mid(pos, len);
|
|
pos += len + 1;
|
|
line = file.lineNumber(pos);
|
|
ppos = pos;
|
|
|
|
while (pos < file.size_s()) {
|
|
if (!file[pos].isSpace() && file[pos] != '\n' && file[pos] != '\r') break;
|
|
++pos;
|
|
}
|
|
if (pos < file.size_s()) {
|
|
// piCout << "check comma" << file[pos];
|
|
if (file[pos] == ',') {
|
|
pos += 1;
|
|
pos = file.findRange('"', '"', '\\', pos, &len);
|
|
// piCout << "check range" << file.mid(pos, len);
|
|
if (pos >= 0) {
|
|
context = file.mid(pos, len);
|
|
pos += len + 1;
|
|
ppos = pos;
|
|
}
|
|
}
|
|
}
|
|
|
|
pos = ppos;
|
|
add(source, context, line);
|
|
}
|
|
}
|
|
for (const auto & kw: literals) {
|
|
// piCout << "literal" << kw;
|
|
pos = -1;
|
|
for (;;) {
|
|
source.clear();
|
|
context.clear();
|
|
|
|
pos = file.find('"', pos + 1);
|
|
if (pos < 0) break;
|
|
pos = file.findRange('"', '"', '\\', pos, &len);
|
|
if (pos < 0) break;
|
|
// piCout << "\"" << pos;
|
|
source = file.mid(pos, len);
|
|
pos += len + 1;
|
|
if (file.mid(pos, kw.size_s()) == kw) {
|
|
// piCout << "line" << file.lineNumber(pos);
|
|
pos += kw.size_s();
|
|
if (pos < file.size_s() - 1) {
|
|
auto pc = file[pos];
|
|
if (isCLetter(pc) || pc == ':') {
|
|
continue;
|
|
}
|
|
}
|
|
ppos = pos;
|
|
while (pos < file.size_s()) {
|
|
if (!file[pos].isSpace() && file[pos] != '\n' && file[pos] != '\r') break;
|
|
++pos;
|
|
}
|
|
if (pos < file.size_s()) {
|
|
// piCout << "check comma" << file[pos];
|
|
if (file[pos] == '(') {
|
|
pos += 1;
|
|
pos = file.findRange('"', '"', '\\', pos, &len);
|
|
// piCout << "check range" << file.mid(pos, len);
|
|
if (pos >= 0) {
|
|
context = file.mid(pos, len);
|
|
pos += len + 1;
|
|
ppos = pos;
|
|
}
|
|
}
|
|
}
|
|
pos = ppos;
|
|
if (source.isEmpty()) continue;
|
|
line = file.lineNumber(pos);
|
|
add(source, context, line);
|
|
}
|
|
}
|
|
}
|
|
}
|