summaryrefslogtreecommitdiffstats
path: root/tools/linguist/lupdate/qscript.g
diff options
context:
space:
mode:
Diffstat (limited to 'tools/linguist/lupdate/qscript.g')
-rw-r--r--tools/linguist/lupdate/qscript.g282
1 files changed, 240 insertions, 42 deletions
diff --git a/tools/linguist/lupdate/qscript.g b/tools/linguist/lupdate/qscript.g
index 5445a64..3655f2e 100644
--- a/tools/linguist/lupdate/qscript.g
+++ b/tools/linguist/lupdate/qscript.g
@@ -84,12 +84,15 @@
/.
#include <translator.h>
+#include <QtCore/QCoreApplication>
#include <QtCore/qdebug.h>
#include <QtCore/qnumeric.h>
#include <QtCore/qstring.h>
#include <QtCore/qtextcodec.h>
#include <QtCore/qvariant.h>
+#include <iostream>
+
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
@@ -97,15 +100,22 @@
QT_BEGIN_NAMESPACE
+class LU {
+ Q_DECLARE_TR_FUNCTIONS(LUpdate)
+};
+
static void recordMessage(
Translator *tor, const QString &context, const QString &text, const QString &comment,
- const QString &extracomment, bool plural, const QString &fileName, int lineNo)
+ const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra,
+ bool plural, const QString &fileName, int lineNo)
{
TranslatorMessage msg(
context, text, comment, QString(),
fileName, lineNo, QStringList(),
TranslatorMessage::Unfinished, plural);
msg.setExtraComment(extracomment.simplified());
+ msg.setId(msgid);
+ msg.setExtras(extra);
tor->extend(msg);
}
@@ -113,15 +123,23 @@ static void recordMessage(
namespace QScript
{
+class CommentProcessor
+{
+public:
+ virtual ~CommentProcessor() {}
+ virtual void processComment(const QChar *chars, int length) = 0;
+};
+
class Lexer
{
public:
- Lexer();
+ Lexer(CommentProcessor *);
~Lexer();
- void setCode(const QString &c, int lineno);
+ void setCode(const QString &c, const QString &fileName, int lineno);
int lex();
+ QString fileName() const { return yyfilename; }
int currentLineNo() const { return yylineno; }
int currentColumnNo() const { return yycolumn; }
@@ -201,6 +219,7 @@ public:
{ err = NoError; }
private:
+ QString yyfilename;
int yylineno;
bool done;
char *buffer8;
@@ -254,6 +273,8 @@ private:
void syncProhibitAutomaticSemicolon();
+ void processComment(const QChar *, int);
+
const QChar *code;
uint length;
int yycolumn;
@@ -280,6 +301,8 @@ private:
ParenthesesState parenthesesState;
int parenthesesCount;
bool prohibitAutomaticSemicolon;
+
+ CommentProcessor *commentProcessor;
};
} // namespace QScript
@@ -356,7 +379,7 @@ double integerFromString(const char *buf, int size, int radix)
} // namespace QScript
-QScript::Lexer::Lexer()
+QScript::Lexer::Lexer(QScript::CommentProcessor *proc)
:
yylineno(0),
size8(128), size16(128), restrKeyword(false),
@@ -367,7 +390,8 @@ QScript::Lexer::Lexer()
err(NoError),
check_reserved(true),
parenthesesState(IgnoreParentheses),
- prohibitAutomaticSemicolon(false)
+ prohibitAutomaticSemicolon(false),
+ commentProcessor(proc)
{
// allocate space for read buffers
buffer8 = new char[size8];
@@ -382,9 +406,10 @@ QScript::Lexer::~Lexer()
delete [] buffer16;
}
-void QScript::Lexer::setCode(const QString &c, int lineno)
+void QScript::Lexer::setCode(const QString &c, const QString &fileName, int lineno)
{
errmsg = QString();
+ yyfilename = fileName;
yylineno = lineno;
yycolumn = 1;
restrKeyword = false;
@@ -733,10 +758,12 @@ int QScript::Lexer::lex()
} else if (current == '/' && next1 == '/') {
recordStartPos();
shift(1);
+ Q_ASSERT(pos16 == 0);
state = InSingleLineComment;
} else if (current == '/' && next1 == '*') {
recordStartPos();
shift(1);
+ Q_ASSERT(pos16 == 0);
state = InMultiLineComment;
} else if (current == 0) {
syncProhibitAutomaticSemicolon();
@@ -795,7 +822,7 @@ int QScript::Lexer::lex()
else {
setDone(Bad);
err = IllegalCharacter;
- errmsg = QLatin1String("Illegal character");
+ errmsg = LU::tr("Illegal character");
}
}
break;
@@ -806,7 +833,7 @@ int QScript::Lexer::lex()
} else if (current == 0 || isLineTerminator()) {
setDone(Bad);
err = UnclosedStringLiteral;
- errmsg = QLatin1String("Unclosed string at end of line");
+ errmsg = LU::tr("Unclosed string at end of line");
} else if (current == '\\') {
state = InEscapeSequence;
} else {
@@ -832,7 +859,7 @@ int QScript::Lexer::lex()
} else {
setDone(Bad);
err = IllegalEscapeSequence;
- errmsg = QLatin1String("Illegal escape squence");
+ errmsg = LU::tr("Illegal escape squence");
}
} else if (current == 'x')
state = InHexEscape;
@@ -871,14 +898,17 @@ int QScript::Lexer::lex()
} else {
setDone(Bad);
err = IllegalUnicodeEscapeSequence;
- errmsg = QLatin1String("Illegal unicode escape sequence");
+ errmsg = LU::tr("Illegal unicode escape sequence");
}
break;
case InSingleLineComment:
if (isLineTerminator()) {
+ record16(current); // include newline
+ processComment(buffer16, pos16);
shiftWindowsLineBreak();
yylineno++;
yycolumn = 0;
+ pos16 = 0;
terminator = true;
bol = true;
if (restrKeyword) {
@@ -888,19 +918,25 @@ int QScript::Lexer::lex()
state = Start;
} else if (current == 0) {
setDone(Eof);
+ } else {
+ record16(current);
}
break;
case InMultiLineComment:
if (current == 0) {
setDone(Bad);
err = UnclosedComment;
- errmsg = QLatin1String("Unclosed comment at end of file");
+ errmsg = LU::tr("Unclosed comment at end of file");
} else if (isLineTerminator()) {
shiftWindowsLineBreak();
yylineno++;
} else if (current == '*' && next1 == '/') {
+ processComment(buffer16, pos16);
+ pos16 = 0;
state = Start;
shift(1);
+ } else {
+ record16(current);
}
break;
case InIdentifier:
@@ -978,7 +1014,7 @@ int QScript::Lexer::lex()
} else {
setDone(Bad);
err = IllegalExponentIndicator;
- errmsg = QLatin1String("Illegal syntax for exponential number");
+ errmsg = LU::tr("Illegal syntax for exponential number");
}
break;
case InExponent:
@@ -1004,7 +1040,7 @@ int QScript::Lexer::lex()
&& isIdentLetter(current)) {
state = Bad;
err = IllegalIdentifier;
- errmsg = QLatin1String("Identifier cannot start with numeric literal");
+ errmsg = LU::tr("Identifier cannot start with numeric literal");
}
// terminate string
@@ -1323,7 +1359,7 @@ bool QScript::Lexer::scanRegExp(RegExpBodyPrefix prefix)
while (1) {
if (isLineTerminator() || current == 0) {
- errmsg = QLatin1String("Unterminated regular expression literal");
+ errmsg = LU::tr("Unterminated regular expression literal");
return false;
}
else if (current != '/' || lastWasEscape == true)
@@ -1362,10 +1398,15 @@ void QScript::Lexer::syncProhibitAutomaticSemicolon()
}
}
+void QScript::Lexer::processComment(const QChar *chars, int length)
+{
+ commentProcessor->processComment(chars, length);
+}
+
class Translator;
-class QScriptParser: protected $table
+class QScriptParser: protected $table, public QScript::CommentProcessor
{
public:
QVariant val;
@@ -1381,10 +1422,12 @@ public:
QScriptParser();
~QScriptParser();
- bool parse(QScript::Lexer *lexer,
- const QString &fileName,
- Translator *translator);
+ void setLexer(QScript::Lexer *);
+
+ bool parse(Translator *translator);
+ QString fileName() const
+ { return lexer->fileName(); }
inline QString errorMessage() const
{ return error_message; }
inline int errorLineNumber() const
@@ -1401,6 +1444,10 @@ protected:
inline Location &loc(int index)
{ return location_stack [tos + index - 2]; }
+ std::ostream &yyMsg(int line = 0);
+
+ virtual void processComment(const QChar *, int);
+
protected:
int tos;
int stack_size;
@@ -1410,6 +1457,13 @@ protected:
QString error_message;
int error_lineno;
int error_column;
+
+private:
+ QScript::Lexer *lexer;
+ QString extracomment;
+ QString msgid;
+ QString sourcetext;
+ TranslatorMessage::ExtraData extra;
};
inline void QScriptParser::reallocateStack()
@@ -1436,7 +1490,8 @@ QScriptParser::QScriptParser():
stack_size(0),
sym_stack(0),
state_stack(0),
- location_stack(0)
+ location_stack(0),
+ lexer(0)
{
}
@@ -1458,10 +1513,14 @@ static inline QScriptParser::Location location(QScript::Lexer *lexer)
return loc;
}
-bool QScriptParser::parse(QScript::Lexer *lexer,
- const QString &fileName,
- Translator *translator)
+void QScriptParser::setLexer(QScript::Lexer *lex)
{
+ lexer = lex;
+}
+
+bool QScriptParser::parse(Translator *translator)
+{
+ Q_ASSERT(lexer != 0);
const int INITIAL_STATE = 0;
int yytoken = -1;
@@ -1628,44 +1687,70 @@ CallExpression: MemberExpression Arguments ;
case $rule_number: {
QString name = sym(1).toString();
if ((name == QLatin1String("qsTranslate")) || (name == QLatin1String("QT_TRANSLATE_NOOP"))) {
+ if (!sourcetext.isEmpty())
+ yyMsg(identLineNo) << qPrintable(LU::tr("//% cannot be used with %1(). Ignoring\n").arg(name));
QVariantList args = sym(2).toList();
if (args.size() < 2) {
- qWarning("%s:%d: %s() requires at least two arguments",
- qPrintable(fileName), identLineNo, qPrintable(name));
+ yyMsg(identLineNo) << qPrintable(LU::tr("%1() requires at least two arguments.\n").arg(name));
} else {
if ((args.at(0).type() != QVariant::String)
|| (args.at(1).type() != QVariant::String)) {
- qWarning("%s:%d: %s(): both arguments must be literal strings",
- qPrintable(fileName), identLineNo, qPrintable(name));
+ yyMsg(identLineNo) << qPrintable(LU::tr("%1(): both arguments must be literal strings.\n").arg(name));
} else {
QString context = args.at(0).toString();
QString text = args.at(1).toString();
QString comment = args.value(2).toString();
- QString extracomment;
bool plural = (args.size() > 4);
recordMessage(translator, context, text, comment, extracomment,
- plural, fileName, identLineNo);
+ msgid, extra, plural, fileName(), identLineNo);
}
}
+ sourcetext.clear();
+ extracomment.clear();
+ msgid.clear();
+ extra.clear();
} else if ((name == QLatin1String("qsTr")) || (name == QLatin1String("QT_TR_NOOP"))) {
+ if (!sourcetext.isEmpty())
+ yyMsg(identLineNo) << qPrintable(LU::tr("//% cannot be used with %1(). Ignoring\n").arg(name));
QVariantList args = sym(2).toList();
if (args.size() < 1) {
- qWarning("%s:%d: %s() requires at least one argument",
- qPrintable(fileName), identLineNo, qPrintable(name));
+ yyMsg(identLineNo) << qPrintable(LU::tr("%1() requires at least one argument.\n").arg(name));
} else {
if (args.at(0).type() != QVariant::String) {
- qWarning("%s:%d: %s(): text to translate must be a literal string",
- qPrintable(fileName), identLineNo, qPrintable(name));
+ yyMsg(identLineNo) << qPrintable(LU::tr("%1(): text to translate must be a literal string.\n").arg(name));
} else {
- QString context = QFileInfo(fileName).baseName();
+ QString context = QFileInfo(fileName()).baseName();
QString text = args.at(0).toString();
QString comment = args.value(1).toString();
- QString extracomment;
bool plural = (args.size() > 2);
recordMessage(translator, context, text, comment, extracomment,
- plural, fileName, identLineNo);
+ msgid, extra, plural, fileName(), identLineNo);
}
}
+ sourcetext.clear();
+ extracomment.clear();
+ msgid.clear();
+ extra.clear();
+ } else if ((name == QLatin1String("qsTrId")) || (name == QLatin1String("QT_TRID_NOOP"))) {
+ if (!msgid.isEmpty())
+ yyMsg(identLineNo) << qPrintable(LU::tr("//= cannot be used with %1(). Ignoring\n").arg(name));
+ QVariantList args = sym(2).toList();
+ if (args.size() < 1) {
+ yyMsg(identLineNo) << qPrintable(LU::tr("%1() requires at least one argument.\n").arg(name));
+ } else {
+ if (args.at(0).type() != QVariant::String) {
+ yyMsg(identLineNo) << qPrintable(LU::tr("%1(): identifier must be a literal string.\n").arg(name));
+ } else {
+ msgid = args.at(0).toString();
+ bool plural = (args.size() > 1);
+ recordMessage(translator, QString(), sourcetext, QString(), extracomment,
+ msgid, extra, plural, fileName(), identLineNo);
+ }
+ }
+ sourcetext.clear();
+ extracomment.clear();
+ msgid.clear();
+ extra.clear();
}
} break;
./
@@ -1811,20 +1896,73 @@ ExpressionNotInOpt: ;
ExpressionNotInOpt: ExpressionNotIn ;
Statement: Block ;
+/.
+ case $rule_number:
+./
Statement: VariableStatement ;
+/.
+ case $rule_number:
+./
Statement: EmptyStatement ;
+/.
+ case $rule_number:
+./
Statement: ExpressionStatement ;
+/.
+ case $rule_number:
+./
Statement: IfStatement ;
+/.
+ case $rule_number:
+./
Statement: IterationStatement ;
+/.
+ case $rule_number:
+./
Statement: ContinueStatement ;
+/.
+ case $rule_number:
+./
Statement: BreakStatement ;
+/.
+ case $rule_number:
+./
Statement: ReturnStatement ;
+/.
+ case $rule_number:
+./
Statement: WithStatement ;
+/.
+ case $rule_number:
+./
Statement: LabelledStatement ;
+/.
+ case $rule_number:
+./
Statement: SwitchStatement ;
+/.
+ case $rule_number:
+./
Statement: ThrowStatement ;
+/.
+ case $rule_number:
+./
Statement: TryStatement ;
+/.
+ case $rule_number:
+./
Statement: DebuggerStatement ;
+/.
+ case $rule_number:
+ if (!sourcetext.isEmpty() || !extracomment.isEmpty() || !msgid.isEmpty() || !extra.isEmpty()) {
+ yyMsg() << qPrintable(LU::tr("Discarding unconsumed meta data\n"));
+ sourcetext.clear();
+ extracomment.clear();
+ msgid.clear();
+ extra.clear();
+ }
+ break;
+./
Block: T_LBRACE StatementListOpt T_RBRACE ;
StatementList: Statement ;
@@ -1963,6 +2101,9 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ;
{
if (first)
error_message += QLatin1String ("Expected ");
+ //: Beginning of the string that contains
+ //: comma-separated list of expected tokens
+ error_message += LU::tr("Expected ");
else
error_message += QLatin1String (", ");
@@ -1986,13 +2127,69 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ;
return false;
}
+std::ostream &QScriptParser::yyMsg(int line)
+{
+ return std::cerr << qPrintable(fileName()) << ':' << (line ? line : lexer->startLineNo()) << ": ";
+}
+
+void QScriptParser::processComment(const QChar *chars, int length)
+{
+ if (!length)
+ return;
+ // Try to match the logic of the C++ parser.
+ if (*chars == QLatin1Char(':') && chars[1].isSpace()) {
+ extracomment += QString(chars+2, length-2);
+ } else if (*chars == QLatin1Char('=') && chars[1].isSpace()) {
+ msgid = QString(chars+2, length-2).simplified();
+ } else if (*chars == QLatin1Char('~') && chars[1].isSpace()) {
+ QString text = QString(chars+2, length-2).trimmed();
+ int k = text.indexOf(QLatin1Char(' '));
+ if (k > -1)
+ extra.insert(text.left(k), text.mid(k + 1).trimmed());
+ } else if (*chars == QLatin1Char('%') && chars[1].isSpace()) {
+ sourcetext.reserve(sourcetext.length() + length-2);
+ ushort *ptr = (ushort *)sourcetext.data() + sourcetext.length();
+ int p = 2, c;
+ forever {
+ if (p >= length)
+ break;
+ c = chars[p++].unicode();
+ if (isspace(c))
+ continue;
+ if (c != '"') {
+ yyMsg() << qPrintable(LU::tr("Unexpected character in meta string\n"));
+ break;
+ }
+ forever {
+ if (p >= length) {
+ whoops:
+ yyMsg() << qPrintable(LU::tr("Unterminated meta string\n"));
+ break;
+ }
+ c = chars[p++].unicode();
+ if (c == '"')
+ break;
+ if (c == '\\') {
+ if (p >= length)
+ goto whoops;
+ c = chars[p++].unicode();
+ if (c == '\n')
+ goto whoops;
+ *ptr++ = '\\';
+ }
+ *ptr++ = c;
+ }
+ }
+ sourcetext.resize(ptr - (ushort *)sourcetext.data());
+ }
+}
+
bool loadQScript(Translator &translator, const QString &filename, ConversionData &cd)
{
QFile file(filename);
if (!file.open(QIODevice::ReadOnly)) {
- cd.appendError(QString::fromLatin1("Cannot open %1: %2")
- .arg(filename, file.errorString()));
+ cd.appendError(LU::tr("Cannot open %1: %2").arg(filename, file.errorString()));
return false;
}
QTextStream ts(&file);
@@ -2005,12 +2202,13 @@ bool loadQScript(Translator &translator, const QString &filename, ConversionData
ts.setAutoDetectUnicode(true);
QString code = ts.readAll();
- QScript::Lexer lexer;
- lexer.setCode(code, /*lineNumber=*/1);
QScriptParser parser;
- if (!parser.parse(&lexer, filename, &translator)) {
- qWarning("%s:%d: %s", qPrintable(filename), parser.errorLineNumber(),
- qPrintable(parser.errorMessage()));
+ QScript::Lexer lexer(&parser);
+ lexer.setCode(code, filename, /*lineNumber=*/1);
+ parser.setLexer(&lexer);
+ if (!parser.parse(&translator)) {
+ std::cerr << qPrintable(filename) << ':' << parser.errorLineNumber() << ": "
+ << qPrintable(parser.errorMessage()) << std::endl;
return false;
}