Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
java.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4
#
include
<
translator
.
h
>
5
6
#
include
<
QtCore
/
QDebug
>
7
#
include
<
QtCore
/
QFile
>
8
#
include
<
QtCore
/
QStack
>
9
#
include
<
QtCore
/
QStack
>
10
#
include
<
QtCore
/
QString
>
11
#
include
<
QtCore
/
QCoreApplication
>
12
#
include
<
QtCore
/
QStringConverter
>
13
#
include
<
QtCore
/
QTextStream
>
14
15
#
include
<
iostream
>
16
17
#
include
<
ctype
.
h
>
18
19
QT_BEGIN_NAMESPACE
20
21
using
namespace
Qt::Literals::StringLiterals;
22
23
enum
{
Tok_Eof
,
Tok_class
,
Tok_return
,
Tok_tr
,
24
Tok_translate
,
Tok_Ident
,
Tok_Package
,
25
Tok_Comment
,
Tok_String
,
Tok_Colon
,
Tok_Dot
,
26
Tok_LeftBrace
,
Tok_RightBrace
,
Tok_LeftParen
,
27
Tok_RightParen
,
Tok_Comma
,
Tok_Semicolon
,
28
Tok_Integer
,
Tok_Plus
,
Tok_PlusPlus
,
Tok_PlusEq
,
Tok_null
};
29
30
class
Scope
31
{
32
public
:
33
QString
name
;
34
enum
Type
{
Clazz
,
Function
,
Other
} type;
35
int
line
;
36
37
Scope
(
const
QString & name,
Type
type,
int
line) :
38
name
(
name
),
39
type(type),
40
line
(line)
41
{}
42
43
~
Scope
()
44
{}
45
};
46
47
/*
48
The tokenizer maintains the following global variables. The names
49
should be self-explanatory.
50
*/
51
52
static
QString
yyFileName
;
53
static
QChar
yyCh
;
54
static
QString
yyIdent
;
55
static
QString
yyComment
;
56
static
QString
yyString
;
57
static
bool
yyEOF
=
false
;
58
59
static
qlonglong
yyInteger
;
60
static
int
yyParenDepth
;
61
static
int
yyLineNo
;
62
static
int
yyCurLineNo
;
63
static
int
yyParenLineNo
;
64
static
int
yyTok
;
65
66
// the string to read from and current position in the string
67
static
QString
yyInStr
;
68
static
int
yyInPos
;
69
70
// The parser maintains the following global variables.
71
static
QString
yyPackage
;
72
static
QStack
<
Scope
*>
yyScope
;
73
74
std
::ostream &
yyMsg
(
int
line = 0)
75
{
76
return
std
::cerr << qPrintable(yyFileName) <<
':'
<< (line ? line :
yyLineNo
) <<
": "
;
77
}
78
79
static
QChar
getChar
()
80
{
81
if
(
yyInPos
>= yyInStr.size()) {
82
yyEOF
=
true
;
83
return
QChar();
84
}
85
QChar c = yyInStr[
yyInPos
++];
86
if
(c == u'\n')
87
++
yyCurLineNo
;
88
return
c;
89
}
90
91
static
int
getToken
()
92
{
93
const
char
tab[] =
"bfnrt\"\'\\"
;
94
const
char
backTab[] =
"\b\f\n\r\t\"\'\\"
;
95
96
yyIdent
.clear();
97
yyComment
.clear();
98
yyString
.clear();
99
100
while
(!
yyEOF
) {
101
yyLineNo
=
yyCurLineNo
;
102
103
if
(
yyCh
.isLetter() || yyCh.toLatin1() ==
'_'
) {
104
do
{
105
yyIdent
.append(yyCh);
106
yyCh
= getChar();
107
}
while
( yyCh.isLetterOrNumber() || yyCh.toLatin1() ==
'_'
);
108
109
if
(
yyTok
!=
Tok_Dot
) {
110
switch
(
yyIdent
.at(0).toLatin1() ) {
111
case
'r'
:
112
if
(yyIdent ==
"return"_L1
)
113
return
Tok_return
;
114
break
;
115
case
'c'
:
116
if
(yyIdent ==
"class"_L1
)
117
return
Tok_class
;
118
break
;
119
case
'n'
:
120
if
(yyIdent ==
"null"_L1
)
121
return
Tok_null
;
122
break
;
123
}
124
}
125
switch
(
yyIdent
.at(0).toLatin1() ) {
126
case
'p'
:
127
if
(yyIdent ==
"package"_L1
)
128
return
Tok_Package
;
129
break
;
130
case
't'
:
131
if
(yyIdent ==
"tr"_L1
)
132
return
Tok_tr
;
133
if
(yyIdent ==
"translate"_L1
)
134
return
Tok_translate
;
135
}
136
return
Tok_Ident
;
137
}
else
{
138
switch
(
yyCh
.toLatin1() ) {
139
140
case
'/'
:
141
yyCh
= getChar();
142
if
(
yyCh
== u'/') {
143
do
{
144
yyCh
= getChar();
145
if
(
yyEOF
)
146
break
;
147
yyComment
.append(yyCh);
148
}
while
(yyCh != u'\n');
149
return
Tok_Comment
;
150
151
}
else
if
(
yyCh
== u'*') {
152
bool
metAster =
false
;
153
bool
metAsterSlash =
false
;
154
155
while
( !metAsterSlash ) {
156
yyCh
= getChar();
157
if
(
yyEOF
) {
158
yyMsg
(
)
<<
"Unterminated Java comment.\n"
;
159
return
Tok_Comment
;
160
}
161
162
yyComment
.append( yyCh );
163
164
if
(
yyCh
== u'*')
165
metAster =
true
;
166
else
if
(metAster && yyCh == u'/')
167
metAsterSlash =
true
;
168
else
169
metAster =
false
;
170
}
171
yyComment
.chop(2);
172
yyCh
= getChar();
173
174
return
Tok_Comment
;
175
}
176
break
;
177
case
'"'
:
178
yyCh
= getChar();
179
180
while
(!
yyEOF
&& yyCh != u'\n' && yyCh != u'"') {
181
182
if
(
yyCh
== u'\\') {
183
yyCh
= getChar();
184
if
(
yyCh
== u'u') {
185
yyCh
= getChar();
186
uint unicode(0);
187
for
(
int
i = 4; i > 0; --i) {
188
unicode = unicode << 4;
189
if
(
yyCh
.isDigit() ) {
190
unicode += yyCh.digitValue();
191
}
192
else
{
193
int
sub(
yyCh
.toLower().toLatin1() - 87);
194
if
( sub > 15 || sub < 10) {
195
yyMsg
(
)
<<
"Invalid Unicode value.\n"
;
196
break
;
197
}
198
unicode += sub;
199
}
200
yyCh
= getChar();
201
}
202
yyString
.append(QChar(unicode));
203
}
else
if
(
yyCh
== u'\n') {
204
yyCh
= getChar();
205
}
else
if
(
const
char
*p = strchr(tab, yyCh.toLatin1()); p) {
206
yyString
.append(QLatin1Char(backTab[p - tab]));
207
yyCh
= getChar();
208
}
else
{
209
yyMsg
(
)
<<
"Invalid escaped character \'\\"
<< qPrintable(yyCh)
210
<<
"\'\n"
;
211
yyCh
= getChar();
212
}
213
}
else
{
214
yyString
.append(yyCh);
215
yyCh
= getChar();
216
}
217
}
218
219
if
(
yyCh
!= u'"')
220
yyMsg
(
)
<<
"Unterminated string.\n"
;
221
222
yyCh
= getChar();
223
224
return
Tok_String
;
225
226
case
':'
:
227
yyCh
= getChar();
228
return
Tok_Colon
;
229
case
'\''
:
230
yyCh
= getChar();
231
232
if
(
yyCh
== u'\\')
233
yyCh
= getChar();
234
do
{
235
yyCh
= getChar();
236
}
while
(!
yyEOF
&& yyCh != u'\'');
237
yyCh
= getChar();
238
break
;
239
case
'{'
:
240
yyCh
= getChar();
241
return
Tok_LeftBrace
;
242
case
'}'
:
243
yyCh
= getChar();
244
return
Tok_RightBrace
;
245
case
'('
:
246
if
(
yyParenDepth
== 0)
247
yyParenLineNo
=
yyCurLineNo
;
248
yyParenDepth
++;
249
yyCh
= getChar();
250
return
Tok_LeftParen
;
251
case
')'
:
252
if
(
yyParenDepth
== 0)
253
yyParenLineNo
=
yyCurLineNo
;
254
yyParenDepth
--;
255
yyCh
= getChar();
256
return
Tok_RightParen
;
257
case
','
:
258
yyCh
= getChar();
259
return
Tok_Comma
;
260
case
'.'
:
261
yyCh
= getChar();
262
return
Tok_Dot
;
263
case
';'
:
264
yyCh
= getChar();
265
return
Tok_Semicolon
;
266
case
'+'
:
267
yyCh
= getChar();
268
if
(
yyCh
== u'+') {
269
yyCh
= getChar();
270
return
Tok_PlusPlus
;
271
}
272
if
(
yyCh
== u'=') {
273
yyCh
= getChar();
274
return
Tok_PlusEq
;
275
}
276
return
Tok_Plus
;
277
case
'0'
:
278
case
'1'
:
279
case
'2'
:
280
case
'3'
:
281
case
'4'
:
282
case
'5'
:
283
case
'6'
:
284
case
'7'
:
285
case
'8'
:
286
case
'9'
:
287
{
288
QByteArray ba;
289
ba += yyCh.toLatin1();
290
yyCh
= getChar();
291
bool
hex = yyCh == u'x';
292
if
( hex ) {
293
ba += yyCh.toLatin1();
294
yyCh
= getChar();
295
}
296
while
( hex ? isxdigit(yyCh.toLatin1()) : yyCh.isDigit() ) {
297
ba += yyCh.toLatin1();
298
yyCh
= getChar();
299
}
300
bool
ok;
301
yyInteger
= ba.toLongLong(&ok);
302
if
(ok)
return
Tok_Integer
;
303
break
;
304
}
305
default
:
306
yyCh
= getChar();
307
}
308
}
309
}
310
return
Tok_Eof
;
311
}
312
313
static
bool
match
(
int
t )
314
{
315
bool
matches = (
yyTok
== t );
316
if
( matches )
317
yyTok
=
getToken
(
)
;
318
return
matches;
319
}
320
321
static
bool
matchString
( QString &s )
322
{
323
if
(
yyTok
!=
Tok_String
)
324
return
false
;
325
326
s = yyString;
327
yyTok
=
getToken
(
)
;
328
while
(
yyTok
==
Tok_Plus
) {
329
yyTok
=
getToken
(
)
;
330
if
(
yyTok
==
Tok_String
)
331
s += yyString;
332
else
{
333
yyMsg
(
)
<<
334
"String used in translation can contain only literals"
335
" concatenated with other literals, not expressions or numbers.\n"
;
336
return
false
;
337
}
338
yyTok
=
getToken
(
)
;
339
}
340
return
true
;
341
}
342
343
static
bool
matchStringOrNull
(QString &s)
344
{
345
bool
matches = matchString(s);
346
if
(!matches) {
347
matches = (
yyTok
==
Tok_null
);
348
if
(matches)
349
yyTok
=
getToken
(
)
;
350
}
351
return
matches;
352
}
353
354
/*
355
* match any expression that can return a number, which can be
356
* 1. Literal number (e.g. '11')
357
* 2. simple identifier (e.g. 'm_count')
358
* 3. simple function call (e.g. 'size()' )
359
* 4. function call on an object (e.g. 'list.size()')
360
* 5. function call on an object (e.g. 'list->size()')
361
*
362
* Other cases:
363
* size(2,4)
364
* list().size()
365
* list(a,b).size(2,4)
366
* etc...
367
*/
368
static
bool
matchExpression
()
369
{
370
if
(
match
(
Tok_Integer
)
) {
371
return
true
;
372
}
373
374
int
parenlevel = 0;
375
while
(
match
(
Tok_Ident
)
|| parenlevel > 0) {
376
if
(
yyTok
==
Tok_RightParen
) {
377
if
(parenlevel == 0)
break
;
378
--parenlevel;
379
yyTok
=
getToken
(
)
;
380
}
else
if
(
yyTok
==
Tok_LeftParen
) {
381
yyTok
=
getToken
(
)
;
382
if
(
yyTok
==
Tok_RightParen
) {
383
yyTok
=
getToken
(
)
;
384
}
else
{
385
++parenlevel;
386
}
387
}
else
if
(
yyTok
==
Tok_Ident
) {
388
continue
;
389
}
else
if
(parenlevel == 0) {
390
return
false
;
391
}
392
}
393
return
true
;
394
}
395
396
static
const
QString
context
()
397
{
398
QString context(
yyPackage
);
399
bool
innerClass =
false
;
400
for
(
int
i = 0; i <
yyScope
.size(); ++i) {
401
if
(
yyScope
.at(i)->type ==
Scope
::
Clazz
) {
402
if
(innerClass)
403
context.append(
"$"_L1
);
404
else
405
context.append(
"."_L1
);
406
407
context.append(yyScope.at(i)->name);
408
innerClass =
true
;
409
}
410
}
411
return
context;
412
}
413
414
static
void
recordMessage
(
415
Translator
*tor,
const
QString &context,
const
QString &text,
const
QString &comment,
416
const
QString &extracomment,
bool
plural,
ConversionData
&cd)
417
{
418
TranslatorMessage
msg(
419
context, text, comment, QString(),
420
yyFileName,
yyLineNo
, QStringList(),
421
TranslatorMessage
::
Unfinished
, plural);
422
msg.setExtraComment(extracomment.simplified());
423
tor
->
extend
(
msg
,
cd
)
;
424
}
425
426
static
void
parse
(
Translator
*tor,
ConversionData
&cd)
427
{
428
QString text;
429
QString com;
430
QString extracomment;
431
432
yyEOF
=
false
;
433
yyCh
= getChar();
434
435
yyTok
=
getToken
(
)
;
436
while
(
yyTok
!=
Tok_Eof
) {
437
switch
(
yyTok
) {
438
case
Tok_class
:
439
yyTok
=
getToken
(
)
;
440
if
(
yyTok
==
Tok_Ident
) {
441
yyScope
.push(
new
Scope
(yyIdent,
Scope
::
Clazz
,
yyLineNo
));
442
}
443
else
{
444
yyMsg
(
)
<<
"'class' must be followed by a class name.\n"
;
445
break
;
446
}
447
while
(!
match
(
Tok_LeftBrace
)
) {
448
yyTok
=
getToken
(
)
;
449
}
450
break
;
451
452
case
Tok_tr
:
453
yyTok
=
getToken
(
)
;
454
if
( match(Tok_LeftParen) && matchString(text) ) {
455
com.clear();
456
bool
plural =
false
;
457
458
if
(
match
(
Tok_RightParen
)
) {
459
// no comment
460
}
else
if
(match(Tok_Comma) && matchStringOrNull(com)) {
//comment
461
if
(
match
(
Tok_RightParen
)
) {
462
// ok,
463
}
else
if
(
match
(
Tok_Comma
)
) {
464
plural =
true
;
465
}
466
}
467
recordMessage(tor, context(), text, com, extracomment, plural, cd);
468
}
469
break
;
470
case
Tok_translate
:
471
{
472
QString contextOverride;
473
yyTok
=
getToken
(
)
;
474
if
( match(Tok_LeftParen) &&
475
matchString(contextOverride) &&
476
match(Tok_Comma) &&
477
matchString(text) ) {
478
479
com.clear();
480
bool
plural =
false
;
481
if
(!
match
(
Tok_RightParen
)
) {
482
// look for comment
483
if
( match(Tok_Comma) && matchStringOrNull(com)) {
484
if
(!
match
(
Tok_RightParen
)
) {
485
if
(
match
(
Tok_Comma
)
&&
matchExpression
(
)
&&
match
(
Tok_RightParen
)
) {
486
plural =
true
;
487
}
else
{
488
break
;
489
}
490
}
491
}
else
{
492
break
;
493
}
494
}
495
recordMessage(tor, contextOverride, text, com, extracomment, plural, cd);
496
}
497
}
498
break
;
499
500
case
Tok_Ident
:
501
yyTok
=
getToken
(
)
;
502
break
;
503
504
case
Tok_Comment
:
505
if
(
yyComment
.startsWith(u':')) {
506
yyComment
.remove(0, 1);
507
extracomment.append(yyComment);
508
}
509
yyTok
=
getToken
(
)
;
510
break
;
511
512
case
Tok_RightBrace
:
513
if
(
yyScope
.isEmpty() ) {
514
yyMsg
(
)
<<
"Excess closing brace.\n"
;
515
}
516
else
517
delete
(
yyScope
.pop());
518
extracomment.clear();
519
yyTok
=
getToken
(
)
;
520
break
;
521
522
case
Tok_LeftBrace
:
523
yyScope
.push(
new
Scope
(QString(),
Scope
::
Other
,
yyLineNo
));
524
yyTok
=
getToken
(
)
;
525
break
;
526
527
case
Tok_Semicolon
:
528
extracomment.clear();
529
yyTok
=
getToken
(
)
;
530
break
;
531
532
case
Tok_Package
:
533
yyTok
=
getToken
(
)
;
534
while
(!
match
(
Tok_Semicolon
)
) {
535
switch
(
yyTok
) {
536
case
Tok_Ident
:
537
yyPackage
.append(yyIdent);
538
break
;
539
case
Tok_Dot
:
540
yyPackage
.append(
"."_L1
);
541
break
;
542
default
:
543
yyMsg
(
)
<<
"'package' must be followed by package name.\n"
;
544
break
;
545
}
546
yyTok
=
getToken
(
)
;
547
}
548
break
;
549
550
default
:
551
yyTok
=
getToken
(
)
;
552
}
553
}
554
555
if
( !yyScope.isEmpty() )
556
yyMsg(yyScope.top()->line) <<
"Unbalanced opening brace.\n"
;
557
else
if
(
yyParenDepth
!= 0 )
558
yyMsg
(
yyParenLineNo
)
<<
"Unbalanced opening parenthesis.\n"
;
559
}
560
561
562
bool
loadJava
(
Translator
&translator,
const
QString &filename,
ConversionData
&cd)
563
{
564
QFile file(filename);
565
if
(!file.open(QIODevice::ReadOnly)) {
566
cd.appendError(QStringLiteral(
"Cannot open %1: %2"
).arg(filename, file.errorString()));
567
return
false
;
568
}
569
570
yyInPos
= -1;
571
yyFileName
= filename;
572
yyPackage
.clear();
573
yyScope
.clear();
574
yyTok
= -1;
575
yyParenDepth
= 0;
576
yyCurLineNo
= 0;
577
yyParenLineNo
= 1;
578
579
QTextStream ts(&file);
580
ts.setEncoding(cd.m_sourceIsUtf16 ? QStringConverter::Utf16 : QStringConverter::Utf8);
581
ts.setAutoDetectUnicode(
true
);
582
yyInStr
= ts.readAll();
583
yyInPos
= 0;
584
yyFileName
= filename;
585
yyCurLineNo
= 1;
586
yyParenLineNo
= 1;
587
588
parse
(
&translator
,
cd
)
;
589
return
true
;
590
}
591
592
QT_END_NAMESPACE
ConversionData
Definition
translator.h:26
Scope
Definition
java.cpp:31
Scope::line
int line
Definition
java.cpp:35
Scope::name
QString name
Definition
java.cpp:33
Scope::Type
Type
Definition
java.cpp:34
Scope::Clazz
@ Clazz
Definition
java.cpp:34
Scope::Function
@ Function
Definition
java.cpp:34
Scope::Other
@ Other
Definition
java.cpp:34
Scope::Scope
Scope(const QString &name, Type type, int line)
Definition
java.cpp:37
Scope::~Scope
~Scope()
Definition
java.cpp:43
TranslatorMessage
Definition
translatormessage.h:17
TranslatorMessage::Unfinished
@ Unfinished
Definition
translatormessage.h:19
Translator
Definition
translator.h:79
Translator::extend
void extend(const TranslatorMessage &msg, ConversionData &cd)
Definition
translator.cpp:128
yyMsg
std::ostream & yyMsg(int line=0)
Definition
java.cpp:74
yyEOF
static bool yyEOF
Definition
java.cpp:57
yyTok
static int yyTok
Definition
java.cpp:64
yyLineNo
static int yyLineNo
Definition
java.cpp:61
yyCh
static QChar yyCh
Definition
java.cpp:53
match
static bool match(int t)
Definition
java.cpp:313
yyInPos
static int yyInPos
Definition
java.cpp:68
matchString
static bool matchString(QString &s)
Definition
java.cpp:321
yyComment
static QString yyComment
Definition
java.cpp:55
yyCurLineNo
static int yyCurLineNo
Definition
java.cpp:62
getToken
static int getToken()
Definition
java.cpp:91
getChar
static QChar getChar()
Definition
java.cpp:79
matchExpression
static bool matchExpression()
Definition
java.cpp:368
yyString
static QString yyString
Definition
java.cpp:56
yyIdent
static QString yyIdent
Definition
java.cpp:54
yyInStr
static QString yyInStr
Definition
java.cpp:67
Tok_Comment
@ Tok_Comment
Definition
java.cpp:25
Tok_Ident
@ Tok_Ident
Definition
java.cpp:24
Tok_return
@ Tok_return
Definition
java.cpp:23
Tok_Eof
@ Tok_Eof
Definition
java.cpp:23
Tok_PlusEq
@ Tok_PlusEq
Definition
java.cpp:28
Tok_String
@ Tok_String
Definition
java.cpp:25
Tok_LeftBrace
@ Tok_LeftBrace
Definition
java.cpp:26
Tok_PlusPlus
@ Tok_PlusPlus
Definition
java.cpp:28
Tok_Colon
@ Tok_Colon
Definition
java.cpp:25
Tok_Plus
@ Tok_Plus
Definition
java.cpp:28
Tok_Semicolon
@ Tok_Semicolon
Definition
java.cpp:27
Tok_LeftParen
@ Tok_LeftParen
Definition
java.cpp:26
Tok_tr
@ Tok_tr
Definition
java.cpp:23
Tok_translate
@ Tok_translate
Definition
java.cpp:24
Tok_Comma
@ Tok_Comma
Definition
java.cpp:27
Tok_class
@ Tok_class
Definition
java.cpp:23
Tok_Package
@ Tok_Package
Definition
java.cpp:24
Tok_Integer
@ Tok_Integer
Definition
java.cpp:28
Tok_RightParen
@ Tok_RightParen
Definition
java.cpp:27
Tok_null
@ Tok_null
Definition
java.cpp:28
Tok_RightBrace
@ Tok_RightBrace
Definition
java.cpp:26
Tok_Dot
@ Tok_Dot
Definition
java.cpp:25
parse
static void parse(Translator *tor, ConversionData &cd)
Definition
java.cpp:426
yyFileName
static QString yyFileName
Definition
java.cpp:52
yyScope
static QStack< Scope * > yyScope
Definition
java.cpp:72
matchStringOrNull
static bool matchStringOrNull(QString &s)
Definition
java.cpp:343
context
static const QString context()
Definition
java.cpp:396
yyPackage
static QString yyPackage
Definition
java.cpp:71
recordMessage
static void recordMessage(Translator *tor, const QString &context, const QString &text, const QString &comment, const QString &extracomment, bool plural, ConversionData &cd)
Definition
java.cpp:414
yyInteger
static qlonglong yyInteger
Definition
java.cpp:59
yyParenDepth
static int yyParenDepth
Definition
java.cpp:60
yyParenLineNo
static int yyParenLineNo
Definition
java.cpp:63
std
[33]
Definition
src_corelib_tools_qhash.cpp:421
loadJava
bool loadJava(Translator &translator, const QString &filename, ConversionData &cd)
Definition
java.cpp:562
qttools
src
linguist
shared
trlib
java.cpp
Generated on
for Qt by
1.18.0