ether-code 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/ether.js +1 -1
- package/generators/php-generator.js +788 -722
- package/i18n/i18n-php.json +8 -0
- package/lexer/ether-lexer.js +401 -392
- package/package.json +1 -1
- package/parsers/ether-parser-php.js +303 -316
|
@@ -226,12 +226,6 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
226
226
|
this.phpModifiers = ['statique', 'static', 'final', 'finale', 'abstrait', 'abstraite', 'abstract', 'readonly', 'lecture seule']
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
-
safeStr(val) {
|
|
230
|
-
if (typeof val === 'string') return val
|
|
231
|
-
if (val && typeof val === 'object') return String(val.name || val.value || '')
|
|
232
|
-
return String(val || '')
|
|
233
|
-
}
|
|
234
|
-
|
|
235
229
|
translatePHP(word) {
|
|
236
230
|
if (!word) return word
|
|
237
231
|
const lower = this.normalizeAccents(String(word))
|
|
@@ -278,10 +272,6 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
278
272
|
|
|
279
273
|
const value = token.value != null ? this.normalizeAccents(String(token.value).toLowerCase()) : ''
|
|
280
274
|
|
|
281
|
-
if (this.isDeclare(value)) {
|
|
282
|
-
return this.parseDeclare(lang)
|
|
283
|
-
}
|
|
284
|
-
|
|
285
275
|
if (this.isNamespace(value)) {
|
|
286
276
|
return this.parseNamespace(lang)
|
|
287
277
|
}
|
|
@@ -290,6 +280,10 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
290
280
|
return this.parseUseStatement(lang)
|
|
291
281
|
}
|
|
292
282
|
|
|
283
|
+
if (this.isDeclare(value)) {
|
|
284
|
+
return this.parseDeclareStatement(lang)
|
|
285
|
+
}
|
|
286
|
+
|
|
293
287
|
if (this.isClassDeclaration(value)) {
|
|
294
288
|
return this.parseClassDeclaration(lang)
|
|
295
289
|
}
|
|
@@ -326,16 +320,6 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
326
320
|
return this.parseSwitch(lang)
|
|
327
321
|
}
|
|
328
322
|
|
|
329
|
-
if (token.type === TokenType.IDENTIFIER) {
|
|
330
|
-
const multiWordCall = this.tryParseMultiWordCallFromStart(lang)
|
|
331
|
-
if (multiWordCall) {
|
|
332
|
-
return {
|
|
333
|
-
type: 'ExpressionStatement',
|
|
334
|
-
expression: multiWordCall
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
323
|
if (this.isTry(value)) {
|
|
340
324
|
return this.parseTryStatement(lang)
|
|
341
325
|
}
|
|
@@ -385,23 +369,17 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
385
369
|
}
|
|
386
370
|
|
|
387
371
|
isNamespace(value) {
|
|
388
|
-
|
|
389
|
-
if (value === 'espace') {
|
|
390
|
-
const next1 = this.peek(1)
|
|
391
|
-
const next2 = this.peek(2)
|
|
392
|
-
if (next1 && next2) {
|
|
393
|
-
const val1 = this.normalizeAccents(String(next1.value).toLowerCase())
|
|
394
|
-
const val2 = this.normalizeAccents(String(next2.value).toLowerCase())
|
|
395
|
-
if (val1 === 'de' && val2 === 'noms') return true
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
return false
|
|
372
|
+
return ['namespace', 'espace de noms'].includes(value)
|
|
399
373
|
}
|
|
400
374
|
|
|
401
375
|
isUse(value) {
|
|
402
376
|
return ['utiliser', 'use'].includes(value)
|
|
403
377
|
}
|
|
404
378
|
|
|
379
|
+
isDeclare(value) {
|
|
380
|
+
return ['declarer', 'declare'].includes(value)
|
|
381
|
+
}
|
|
382
|
+
|
|
405
383
|
isClassDeclaration(value) {
|
|
406
384
|
const keywords = ['classe', 'class', 'abstrait', 'abstraite', 'abstract', 'final', 'finale', 'readonly']
|
|
407
385
|
if (keywords.includes(value)) {
|
|
@@ -493,54 +471,8 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
493
471
|
return value === 'match'
|
|
494
472
|
}
|
|
495
473
|
|
|
496
|
-
isDeclare(value) {
|
|
497
|
-
return ['declare', 'declarer', 'déclarer'].includes(value)
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
parseDeclare(lang) {
|
|
501
|
-
this.advance()
|
|
502
|
-
|
|
503
|
-
const directives = []
|
|
504
|
-
|
|
505
|
-
if (this.match(TokenType.LPAREN)) {
|
|
506
|
-
do {
|
|
507
|
-
const nameToken = this.current()
|
|
508
|
-
const name = nameToken ? this.safeStr(nameToken.value) : ''
|
|
509
|
-
this.advance()
|
|
510
|
-
|
|
511
|
-
this.match(TokenType.EQUALS)
|
|
512
|
-
|
|
513
|
-
const value = this.parseExpression(lang)
|
|
514
|
-
directives.push({ name, value })
|
|
515
|
-
} while (this.match(TokenType.COMMA))
|
|
516
|
-
|
|
517
|
-
this.match(TokenType.RPAREN)
|
|
518
|
-
} else {
|
|
519
|
-
const nameToken = this.current()
|
|
520
|
-
const name = nameToken ? this.safeStr(nameToken.value) : ''
|
|
521
|
-
this.advance()
|
|
522
|
-
|
|
523
|
-
this.match(TokenType.EQUALS)
|
|
524
|
-
|
|
525
|
-
const value = this.parseExpression(lang)
|
|
526
|
-
directives.push({ name, value })
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
return {
|
|
530
|
-
type: 'DeclareStatement',
|
|
531
|
-
directives: directives
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
474
|
parseNamespace(lang) {
|
|
536
|
-
|
|
537
|
-
const firstVal = this.normalizeAccents(String(first.value).toLowerCase())
|
|
538
|
-
|
|
539
|
-
if (firstVal === 'espace' && firstVal !== 'espace de noms') {
|
|
540
|
-
this.advance()
|
|
541
|
-
this.advance()
|
|
542
|
-
}
|
|
543
|
-
|
|
475
|
+
this.advance()
|
|
544
476
|
const name = this.parseNamespacePath(lang)
|
|
545
477
|
this.skipNewlines()
|
|
546
478
|
|
|
@@ -601,6 +533,16 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
601
533
|
})
|
|
602
534
|
} while (this.match(TokenType.COMMA))
|
|
603
535
|
|
|
536
|
+
if (imports.length === 1) {
|
|
537
|
+
return {
|
|
538
|
+
type: 'UseStatement',
|
|
539
|
+
useType: useType,
|
|
540
|
+
name: imports[0].path,
|
|
541
|
+
alias: imports[0].alias,
|
|
542
|
+
imports: imports
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
604
546
|
return {
|
|
605
547
|
type: 'UseStatement',
|
|
606
548
|
useType: useType,
|
|
@@ -608,6 +550,42 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
608
550
|
}
|
|
609
551
|
}
|
|
610
552
|
|
|
553
|
+
parseDeclareStatement(lang) {
|
|
554
|
+
this.advance()
|
|
555
|
+
|
|
556
|
+
const directives = []
|
|
557
|
+
|
|
558
|
+
do {
|
|
559
|
+
const nameToken = this.current()
|
|
560
|
+
if (!nameToken || nameToken.type !== TokenType.IDENTIFIER) break
|
|
561
|
+
|
|
562
|
+
let name = String(nameToken.value)
|
|
563
|
+
this.advance()
|
|
564
|
+
|
|
565
|
+
if (name === 'strict' && this.current()) {
|
|
566
|
+
const next = this.normalizeAccents(String(this.current().value).toLowerCase())
|
|
567
|
+
if (next === 'types' || next === '_types') {
|
|
568
|
+
name = 'strict_types'
|
|
569
|
+
this.advance()
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
this.match(TokenType.EQUALS)
|
|
574
|
+
|
|
575
|
+
const value = this.parseExpression(lang)
|
|
576
|
+
|
|
577
|
+
directives.push({
|
|
578
|
+
name: name,
|
|
579
|
+
value: value
|
|
580
|
+
})
|
|
581
|
+
} while (this.match(TokenType.COMMA))
|
|
582
|
+
|
|
583
|
+
return {
|
|
584
|
+
type: 'DeclareStatement',
|
|
585
|
+
directives: directives
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
611
589
|
parseClassDeclaration(lang) {
|
|
612
590
|
const modifiers = []
|
|
613
591
|
|
|
@@ -743,6 +721,10 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
743
721
|
return this.parseTraitUse(lang)
|
|
744
722
|
}
|
|
745
723
|
|
|
724
|
+
if (val === 'variable' || val === 'var') {
|
|
725
|
+
this.advance()
|
|
726
|
+
}
|
|
727
|
+
|
|
746
728
|
return this.parsePropertyDeclaration(lang, visibility, isStatic, isReadonly)
|
|
747
729
|
}
|
|
748
730
|
|
|
@@ -803,11 +785,6 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
803
785
|
}
|
|
804
786
|
|
|
805
787
|
parsePropertyDeclaration(lang, visibility, isStatic, isReadonly) {
|
|
806
|
-
const val = this.current() ? this.normalizeAccents(String(this.current().value).toLowerCase()) : ''
|
|
807
|
-
if (val === 'variable' || val === 'var') {
|
|
808
|
-
this.advance()
|
|
809
|
-
}
|
|
810
|
-
|
|
811
788
|
let typeHint = null
|
|
812
789
|
|
|
813
790
|
const current = this.current()
|
|
@@ -819,10 +796,12 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
819
796
|
}
|
|
820
797
|
|
|
821
798
|
const nameToken = this.current()
|
|
822
|
-
let name =
|
|
799
|
+
let name = nameToken ? nameToken.value : 'property'
|
|
823
800
|
|
|
824
|
-
if (name.startsWith('$')) {
|
|
801
|
+
if (typeof name === 'string' && name.startsWith('$')) {
|
|
825
802
|
name = name.substring(1)
|
|
803
|
+
} else if (typeof name !== 'string') {
|
|
804
|
+
name = String(name)
|
|
826
805
|
}
|
|
827
806
|
|
|
828
807
|
if (nameToken) this.advance()
|
|
@@ -1091,6 +1070,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1091
1070
|
}
|
|
1092
1071
|
}
|
|
1093
1072
|
|
|
1073
|
+
this.match(TokenType.COLON)
|
|
1094
1074
|
this.skipNewlines()
|
|
1095
1075
|
|
|
1096
1076
|
let body
|
|
@@ -1109,8 +1089,6 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1109
1089
|
}
|
|
1110
1090
|
}
|
|
1111
1091
|
|
|
1112
|
-
this.match(TokenType.COLON)
|
|
1113
|
-
this.skipNewlines()
|
|
1114
1092
|
body = this.parseBlock(lang)
|
|
1115
1093
|
|
|
1116
1094
|
return {
|
|
@@ -1135,7 +1113,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1135
1113
|
}
|
|
1136
1114
|
|
|
1137
1115
|
const varToken = this.current()
|
|
1138
|
-
let varName =
|
|
1116
|
+
let varName = varToken ? String(varToken.value) : ''
|
|
1139
1117
|
if (varName.startsWith('$')) {
|
|
1140
1118
|
varName = varName.substring(1)
|
|
1141
1119
|
}
|
|
@@ -1180,7 +1158,6 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1180
1158
|
let variadic = false
|
|
1181
1159
|
let byReference = false
|
|
1182
1160
|
let defaultValue = null
|
|
1183
|
-
let name = null
|
|
1184
1161
|
|
|
1185
1162
|
const val = this.current() ? this.normalizeAccents(String(this.current().value).toLowerCase()) : ''
|
|
1186
1163
|
if (this.phpVisibility.includes(val)) {
|
|
@@ -1194,6 +1171,19 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1194
1171
|
this.advance()
|
|
1195
1172
|
}
|
|
1196
1173
|
|
|
1174
|
+
const currentType = this.current()
|
|
1175
|
+
if (currentType && currentType.type === TokenType.IDENTIFIER) {
|
|
1176
|
+
const typeLower = this.normalizeAccents(String(currentType.value).toLowerCase())
|
|
1177
|
+
const nextToken = this.peek(1)
|
|
1178
|
+
|
|
1179
|
+
if (nextToken && nextToken.type === TokenType.COLON) {
|
|
1180
|
+
} else if (this.phpTypes[typeLower] || (typeLower[0] && typeLower[0] === typeLower[0].toUpperCase())) {
|
|
1181
|
+
if (!nextToken || nextToken.type !== TokenType.EQUALS) {
|
|
1182
|
+
typeHint = this.parseTypeHint(lang)
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1197
1187
|
if (this.match(TokenType.SPREAD) || this.matchValue('...')) {
|
|
1198
1188
|
variadic = true
|
|
1199
1189
|
}
|
|
@@ -1202,33 +1192,17 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1202
1192
|
byReference = true
|
|
1203
1193
|
}
|
|
1204
1194
|
|
|
1205
|
-
const
|
|
1206
|
-
if (!
|
|
1207
|
-
|
|
1208
|
-
const nextToken = this.peek(1)
|
|
1195
|
+
const nameToken = this.current()
|
|
1196
|
+
if (!nameToken) return null
|
|
1209
1197
|
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
this.advance()
|
|
1214
|
-
this.advance()
|
|
1215
|
-
typeHint = this.parseTypeHint(lang)
|
|
1216
|
-
} else {
|
|
1217
|
-
const typeLower = this.normalizeAccents(String(currentToken.value).toLowerCase())
|
|
1218
|
-
if (this.phpTypes[typeLower] || /^[A-Z]/.test(currentToken.value)) {
|
|
1219
|
-
typeHint = this.parseTypeHint(lang)
|
|
1220
|
-
}
|
|
1221
|
-
|
|
1222
|
-
const nameToken = this.current()
|
|
1223
|
-
if (nameToken && nameToken.type === TokenType.IDENTIFIER) {
|
|
1224
|
-
name = this.safeStr(nameToken.value)
|
|
1225
|
-
if (name.startsWith('$')) name = name.substring(1)
|
|
1226
|
-
this.advance()
|
|
1227
|
-
}
|
|
1198
|
+
let name = String(nameToken.value)
|
|
1199
|
+
if (name.startsWith('$')) {
|
|
1200
|
+
name = name.substring(1)
|
|
1228
1201
|
}
|
|
1202
|
+
this.advance()
|
|
1229
1203
|
|
|
1230
|
-
if (
|
|
1231
|
-
|
|
1204
|
+
if (this.match(TokenType.COLON)) {
|
|
1205
|
+
typeHint = this.parseTypeHint(lang)
|
|
1232
1206
|
}
|
|
1233
1207
|
|
|
1234
1208
|
if (this.match(TokenType.EQUALS)) {
|
|
@@ -1317,7 +1291,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1317
1291
|
}
|
|
1318
1292
|
|
|
1319
1293
|
const nameToken = this.current()
|
|
1320
|
-
let name =
|
|
1294
|
+
let name = nameToken ? String(nameToken.value) : 'variable'
|
|
1321
1295
|
if (name.startsWith('$')) {
|
|
1322
1296
|
name = name.substring(1)
|
|
1323
1297
|
}
|
|
@@ -1357,25 +1331,47 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1357
1331
|
|
|
1358
1332
|
const elseVal = this.current() ? this.normalizeAccents(String(this.current().value).toLowerCase()) : ''
|
|
1359
1333
|
if (elseVal === 'sinon si' || elseVal === 'elseif') {
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1334
|
+
this.advance()
|
|
1335
|
+
|
|
1336
|
+
let elseCondition
|
|
1337
|
+
if (this.match(TokenType.LPAREN)) {
|
|
1338
|
+
elseCondition = this.parseExpression(lang)
|
|
1339
|
+
this.match(TokenType.RPAREN)
|
|
1340
|
+
} else {
|
|
1341
|
+
elseCondition = this.parseConditionUntilColon(lang)
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
this.match(TokenType.COLON)
|
|
1345
|
+
this.skipNewlines()
|
|
1346
|
+
const elseConsequent = this.parseBlock(lang)
|
|
1347
|
+
|
|
1348
|
+
alternate = {
|
|
1349
|
+
type: 'IfStatement',
|
|
1350
|
+
test: elseCondition,
|
|
1351
|
+
consequent: elseConsequent,
|
|
1352
|
+
alternate: null
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
this.skipNewlines()
|
|
1356
|
+
const nextElse = this.current() ? this.normalizeAccents(String(this.current().value).toLowerCase()) : ''
|
|
1357
|
+
if (nextElse === 'sinon' || nextElse === 'else') {
|
|
1358
|
+
this.advance()
|
|
1359
|
+
this.match(TokenType.COLON)
|
|
1360
|
+
this.skipNewlines()
|
|
1361
|
+
alternate.alternate = this.parseBlock(lang)
|
|
1362
|
+
}
|
|
1363
|
+
} else if (elseVal === 'sinon' || elseVal === 'else') {
|
|
1363
1364
|
this.advance()
|
|
1364
1365
|
|
|
1365
1366
|
const nextVal = this.current() ? this.normalizeAccents(String(this.current().value).toLowerCase()) : ''
|
|
1366
1367
|
if (nextVal === 'si' || nextVal === 'if') {
|
|
1367
1368
|
alternate = this.parseConditional(lang)
|
|
1368
|
-
alternate.type = '
|
|
1369
|
+
alternate.type = 'ElseIfStatement'
|
|
1369
1370
|
} else {
|
|
1370
1371
|
this.match(TokenType.COLON)
|
|
1371
1372
|
this.skipNewlines()
|
|
1372
1373
|
alternate = this.parseBlock(lang)
|
|
1373
1374
|
}
|
|
1374
|
-
} else if (elseVal === 'else') {
|
|
1375
|
-
this.advance()
|
|
1376
|
-
this.match(TokenType.COLON)
|
|
1377
|
-
this.skipNewlines()
|
|
1378
|
-
alternate = this.parseBlock(lang)
|
|
1379
1375
|
}
|
|
1380
1376
|
|
|
1381
1377
|
return {
|
|
@@ -1387,7 +1383,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1387
1383
|
}
|
|
1388
1384
|
|
|
1389
1385
|
parseConditionUntilColon(lang) {
|
|
1390
|
-
const
|
|
1386
|
+
const tokens = []
|
|
1391
1387
|
let depth = 0
|
|
1392
1388
|
|
|
1393
1389
|
while (!this.isAtEnd()) {
|
|
@@ -1404,23 +1400,36 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1404
1400
|
break
|
|
1405
1401
|
}
|
|
1406
1402
|
|
|
1403
|
+
tokens.push(token)
|
|
1407
1404
|
this.advance()
|
|
1408
1405
|
}
|
|
1409
1406
|
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
if (endPos > startPos) {
|
|
1414
|
-
return this.parseExpression(lang)
|
|
1407
|
+
if (tokens.length === 0) {
|
|
1408
|
+
return { type: 'Literal', value: true }
|
|
1415
1409
|
}
|
|
1416
1410
|
|
|
1417
|
-
|
|
1411
|
+
const savedPos = this.pos
|
|
1412
|
+
const savedTokens = this.tokens
|
|
1413
|
+
this.tokens = tokens
|
|
1414
|
+
this.pos = 0
|
|
1415
|
+
|
|
1416
|
+
const expr = this.parseExpression(lang)
|
|
1417
|
+
|
|
1418
|
+
this.tokens = savedTokens
|
|
1419
|
+
this.pos = savedPos
|
|
1420
|
+
|
|
1421
|
+
return expr
|
|
1418
1422
|
}
|
|
1419
1423
|
|
|
1420
1424
|
parseLoop(lang) {
|
|
1421
1425
|
const token = this.current()
|
|
1422
1426
|
const value = this.normalizeAccents(String(token.value).toLowerCase())
|
|
1423
1427
|
|
|
1428
|
+
if (value === 'pour chaque' || value === 'foreach') {
|
|
1429
|
+
this.advance()
|
|
1430
|
+
return this.parseForeach(lang)
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1424
1433
|
if (value === 'pour') {
|
|
1425
1434
|
const next = this.peek(1)
|
|
1426
1435
|
if (next && this.normalizeAccents(String(next.value).toLowerCase()) === 'chaque') {
|
|
@@ -1431,16 +1440,14 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1431
1440
|
return this.parseFor(lang)
|
|
1432
1441
|
}
|
|
1433
1442
|
|
|
1434
|
-
if (value === '
|
|
1443
|
+
if (value === 'tant que' || value === 'while') {
|
|
1435
1444
|
this.advance()
|
|
1436
|
-
return this.
|
|
1445
|
+
return this.parseWhile(lang)
|
|
1437
1446
|
}
|
|
1438
1447
|
|
|
1439
|
-
if (value === '
|
|
1448
|
+
if (value === 'tant') {
|
|
1440
1449
|
this.advance()
|
|
1441
|
-
|
|
1442
|
-
this.matchValue('que')
|
|
1443
|
-
}
|
|
1450
|
+
this.matchValue('que')
|
|
1444
1451
|
return this.parseWhile(lang)
|
|
1445
1452
|
}
|
|
1446
1453
|
|
|
@@ -1454,7 +1461,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1454
1461
|
|
|
1455
1462
|
parseFor(lang) {
|
|
1456
1463
|
this.advance()
|
|
1457
|
-
|
|
1464
|
+
|
|
1458
1465
|
let init = null
|
|
1459
1466
|
let test = null
|
|
1460
1467
|
let update = null
|
|
@@ -1475,19 +1482,13 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1475
1482
|
}
|
|
1476
1483
|
this.match(TokenType.RPAREN)
|
|
1477
1484
|
} else {
|
|
1478
|
-
|
|
1479
|
-
init = this.parseExpression(lang)
|
|
1480
|
-
}
|
|
1485
|
+
init = this.parseForInitUntilSemicolon(lang)
|
|
1481
1486
|
this.match(TokenType.SEMICOLON)
|
|
1482
1487
|
|
|
1483
|
-
|
|
1484
|
-
test = this.parseExpression(lang)
|
|
1485
|
-
}
|
|
1488
|
+
test = this.parseForConditionUntilSemicolon(lang)
|
|
1486
1489
|
this.match(TokenType.SEMICOLON)
|
|
1487
1490
|
|
|
1488
|
-
|
|
1489
|
-
update = this.parseExpression(lang)
|
|
1490
|
-
}
|
|
1491
|
+
update = this.parseForUpdateUntilColon(lang)
|
|
1491
1492
|
}
|
|
1492
1493
|
|
|
1493
1494
|
this.match(TokenType.COLON)
|
|
@@ -1503,6 +1504,82 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1503
1504
|
}
|
|
1504
1505
|
}
|
|
1505
1506
|
|
|
1507
|
+
parseForInitUntilSemicolon(lang) {
|
|
1508
|
+
const tokens = []
|
|
1509
|
+
while (!this.isAtEnd()) {
|
|
1510
|
+
const token = this.current()
|
|
1511
|
+
if (!token) break
|
|
1512
|
+
if (token.type === TokenType.SEMICOLON) break
|
|
1513
|
+
tokens.push(token)
|
|
1514
|
+
this.advance()
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
if (tokens.length === 0) return null
|
|
1518
|
+
|
|
1519
|
+
const savedPos = this.pos
|
|
1520
|
+
const savedTokens = this.tokens
|
|
1521
|
+
this.tokens = tokens
|
|
1522
|
+
this.pos = 0
|
|
1523
|
+
|
|
1524
|
+
const expr = this.parseExpression(lang)
|
|
1525
|
+
|
|
1526
|
+
this.tokens = savedTokens
|
|
1527
|
+
this.pos = savedPos
|
|
1528
|
+
|
|
1529
|
+
return expr
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
parseForConditionUntilSemicolon(lang) {
|
|
1533
|
+
const tokens = []
|
|
1534
|
+
while (!this.isAtEnd()) {
|
|
1535
|
+
const token = this.current()
|
|
1536
|
+
if (!token) break
|
|
1537
|
+
if (token.type === TokenType.SEMICOLON) break
|
|
1538
|
+
tokens.push(token)
|
|
1539
|
+
this.advance()
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
if (tokens.length === 0) return null
|
|
1543
|
+
|
|
1544
|
+
const savedPos = this.pos
|
|
1545
|
+
const savedTokens = this.tokens
|
|
1546
|
+
this.tokens = tokens
|
|
1547
|
+
this.pos = 0
|
|
1548
|
+
|
|
1549
|
+
const expr = this.parseExpression(lang)
|
|
1550
|
+
|
|
1551
|
+
this.tokens = savedTokens
|
|
1552
|
+
this.pos = savedPos
|
|
1553
|
+
|
|
1554
|
+
return expr
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
parseForUpdateUntilColon(lang) {
|
|
1558
|
+
const tokens = []
|
|
1559
|
+
while (!this.isAtEnd()) {
|
|
1560
|
+
const token = this.current()
|
|
1561
|
+
if (!token) break
|
|
1562
|
+
if (token.type === TokenType.COLON) break
|
|
1563
|
+
if (token.type === TokenType.NEWLINE) break
|
|
1564
|
+
tokens.push(token)
|
|
1565
|
+
this.advance()
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
if (tokens.length === 0) return null
|
|
1569
|
+
|
|
1570
|
+
const savedPos = this.pos
|
|
1571
|
+
const savedTokens = this.tokens
|
|
1572
|
+
this.tokens = tokens
|
|
1573
|
+
this.pos = 0
|
|
1574
|
+
|
|
1575
|
+
const expr = this.parseExpression(lang)
|
|
1576
|
+
|
|
1577
|
+
this.tokens = savedTokens
|
|
1578
|
+
this.pos = savedPos
|
|
1579
|
+
|
|
1580
|
+
return expr
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1506
1583
|
parseForeach(lang) {
|
|
1507
1584
|
let array = null
|
|
1508
1585
|
let key = null
|
|
@@ -1522,7 +1599,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1522
1599
|
}
|
|
1523
1600
|
|
|
1524
1601
|
const firstVar = this.current()
|
|
1525
|
-
let firstName =
|
|
1602
|
+
let firstName = firstVar ? String(firstVar.value) : 'item'
|
|
1526
1603
|
if (firstName.startsWith('$')) firstName = firstName.substring(1)
|
|
1527
1604
|
this.advance()
|
|
1528
1605
|
|
|
@@ -1534,7 +1611,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1534
1611
|
}
|
|
1535
1612
|
|
|
1536
1613
|
const valueVar = this.current()
|
|
1537
|
-
value =
|
|
1614
|
+
value = valueVar ? String(valueVar.value) : 'value'
|
|
1538
1615
|
if (value.startsWith('$')) value = value.substring(1)
|
|
1539
1616
|
this.advance()
|
|
1540
1617
|
} else {
|
|
@@ -1543,12 +1620,28 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1543
1620
|
|
|
1544
1621
|
this.match(TokenType.RPAREN)
|
|
1545
1622
|
} else {
|
|
1546
|
-
const
|
|
1547
|
-
|
|
1548
|
-
|
|
1623
|
+
const tokens = []
|
|
1624
|
+
while (!this.isAtEnd()) {
|
|
1625
|
+
const token = this.current()
|
|
1626
|
+
if (!token) break
|
|
1627
|
+
const tokenVal = this.normalizeAccents(String(token.value).toLowerCase())
|
|
1628
|
+
if (tokenVal === 'comme' || tokenVal === 'as') break
|
|
1629
|
+
if (token.type === TokenType.COLON) break
|
|
1630
|
+
if (token.type === TokenType.NEWLINE) break
|
|
1631
|
+
tokens.push(token)
|
|
1549
1632
|
this.advance()
|
|
1550
1633
|
}
|
|
1551
1634
|
|
|
1635
|
+
if (tokens.length > 0) {
|
|
1636
|
+
const savedPos = this.pos
|
|
1637
|
+
const savedTokens = this.tokens
|
|
1638
|
+
this.tokens = tokens
|
|
1639
|
+
this.pos = 0
|
|
1640
|
+
array = this.parseExpression(lang)
|
|
1641
|
+
this.tokens = savedTokens
|
|
1642
|
+
this.pos = savedPos
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1552
1645
|
const asVal = this.current() ? this.normalizeAccents(String(this.current().value).toLowerCase()) : ''
|
|
1553
1646
|
if (asVal === 'comme' || asVal === 'as') {
|
|
1554
1647
|
this.advance()
|
|
@@ -1559,23 +1652,27 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1559
1652
|
}
|
|
1560
1653
|
|
|
1561
1654
|
const firstVar = this.current()
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1655
|
+
if (firstVar && firstVar.type === TokenType.IDENTIFIER) {
|
|
1656
|
+
let firstName = String(firstVar.value)
|
|
1657
|
+
if (firstName.startsWith('$')) firstName = firstName.substring(1)
|
|
1658
|
+
this.advance()
|
|
1565
1659
|
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1660
|
+
if (this.match(TokenType.DOUBLE_ARROW) || this.matchValue('=>')) {
|
|
1661
|
+
key = firstName
|
|
1662
|
+
|
|
1663
|
+
if (this.match(TokenType.AMPERSAND)) {
|
|
1664
|
+
byRef = true
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
const valueVar = this.current()
|
|
1668
|
+
if (valueVar && valueVar.type === TokenType.IDENTIFIER) {
|
|
1669
|
+
value = String(valueVar.value)
|
|
1670
|
+
if (value.startsWith('$')) value = value.substring(1)
|
|
1671
|
+
this.advance()
|
|
1672
|
+
}
|
|
1673
|
+
} else {
|
|
1674
|
+
value = firstName
|
|
1571
1675
|
}
|
|
1572
|
-
|
|
1573
|
-
const valueVar = this.current()
|
|
1574
|
-
value = this.safeStr(valueVar ? valueVar.value : 'value')
|
|
1575
|
-
if (value.startsWith('$')) value = value.substring(1)
|
|
1576
|
-
this.advance()
|
|
1577
|
-
} else {
|
|
1578
|
-
value = firstName
|
|
1579
1676
|
}
|
|
1580
1677
|
}
|
|
1581
1678
|
|
|
@@ -1639,7 +1736,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1639
1736
|
return {
|
|
1640
1737
|
type: 'DoWhileStatement',
|
|
1641
1738
|
body: body,
|
|
1642
|
-
|
|
1739
|
+
test: condition
|
|
1643
1740
|
}
|
|
1644
1741
|
}
|
|
1645
1742
|
|
|
@@ -1686,25 +1783,29 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1686
1783
|
|
|
1687
1784
|
if (val === 'cas' || val === 'case') {
|
|
1688
1785
|
this.advance()
|
|
1689
|
-
const test = this.
|
|
1786
|
+
const test = this.parseConditionUntilColon(lang)
|
|
1690
1787
|
this.match(TokenType.COLON)
|
|
1691
1788
|
this.skipNewlines()
|
|
1692
|
-
this.match(TokenType.INDENT)
|
|
1693
1789
|
|
|
1790
|
+
const hasInnerIndent = this.match(TokenType.INDENT)
|
|
1694
1791
|
const consequent = []
|
|
1792
|
+
|
|
1695
1793
|
while (!this.isAtEnd()) {
|
|
1696
1794
|
this.skipNewlines()
|
|
1697
|
-
const
|
|
1698
|
-
if (!
|
|
1795
|
+
const nextToken = this.current()
|
|
1796
|
+
if (!nextToken) break
|
|
1699
1797
|
|
|
1700
|
-
const nextVal = this.normalizeAccents(String(
|
|
1701
|
-
if (['cas', 'case', 'defaut', 'default'].includes(nextVal)) {
|
|
1798
|
+
const nextVal = this.normalizeAccents(String(nextToken.value).toLowerCase())
|
|
1799
|
+
if (['cas', 'case', 'defaut', 'default', 'défaut'].includes(nextVal)) {
|
|
1702
1800
|
break
|
|
1703
1801
|
}
|
|
1704
|
-
if (
|
|
1705
|
-
|
|
1802
|
+
if (nextToken.type === TokenType.RBRACE || nextToken.type === TokenType.DEDENT) {
|
|
1803
|
+
if (hasInnerIndent) {
|
|
1804
|
+
this.advance()
|
|
1805
|
+
}
|
|
1706
1806
|
break
|
|
1707
1807
|
}
|
|
1808
|
+
|
|
1708
1809
|
const stmt = this.parseStatement(lang)
|
|
1709
1810
|
if (stmt) consequent.push(stmt)
|
|
1710
1811
|
this.skipNewlines()
|
|
@@ -1715,21 +1816,26 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1715
1816
|
test: test,
|
|
1716
1817
|
consequent: consequent
|
|
1717
1818
|
})
|
|
1718
|
-
} else if (val === 'defaut' || val === 'default') {
|
|
1819
|
+
} else if (val === 'defaut' || val === 'default' || val === 'défaut') {
|
|
1719
1820
|
this.advance()
|
|
1720
1821
|
this.match(TokenType.COLON)
|
|
1721
1822
|
this.skipNewlines()
|
|
1722
|
-
this.match(TokenType.INDENT)
|
|
1723
1823
|
|
|
1824
|
+
const hasInnerIndent = this.match(TokenType.INDENT)
|
|
1724
1825
|
const consequent = []
|
|
1826
|
+
|
|
1725
1827
|
while (!this.isAtEnd()) {
|
|
1726
1828
|
this.skipNewlines()
|
|
1727
|
-
const
|
|
1728
|
-
if (!
|
|
1729
|
-
|
|
1730
|
-
|
|
1829
|
+
const nextToken = this.current()
|
|
1830
|
+
if (!nextToken) break
|
|
1831
|
+
|
|
1832
|
+
if (nextToken.type === TokenType.RBRACE || nextToken.type === TokenType.DEDENT) {
|
|
1833
|
+
if (hasInnerIndent) {
|
|
1834
|
+
this.advance()
|
|
1835
|
+
}
|
|
1731
1836
|
break
|
|
1732
1837
|
}
|
|
1838
|
+
|
|
1733
1839
|
const stmt = this.parseStatement(lang)
|
|
1734
1840
|
if (stmt) consequent.push(stmt)
|
|
1735
1841
|
this.skipNewlines()
|
|
@@ -1833,7 +1939,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1833
1939
|
do {
|
|
1834
1940
|
const typeToken = this.current()
|
|
1835
1941
|
if (typeToken && typeToken.type === TokenType.IDENTIFIER) {
|
|
1836
|
-
const typeName =
|
|
1942
|
+
const typeName = String(typeToken.value)
|
|
1837
1943
|
if (typeName.startsWith('$')) {
|
|
1838
1944
|
param = typeName.substring(1)
|
|
1839
1945
|
} else {
|
|
@@ -1846,7 +1952,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1846
1952
|
if (!param) {
|
|
1847
1953
|
const paramToken = this.current()
|
|
1848
1954
|
if (paramToken && paramToken.type === TokenType.IDENTIFIER) {
|
|
1849
|
-
param =
|
|
1955
|
+
param = String(paramToken.value)
|
|
1850
1956
|
if (param.startsWith('$')) param = param.substring(1)
|
|
1851
1957
|
this.advance()
|
|
1852
1958
|
}
|
|
@@ -1855,7 +1961,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1855
1961
|
} else {
|
|
1856
1962
|
const typeToken = this.current()
|
|
1857
1963
|
if (typeToken && typeToken.type === TokenType.IDENTIFIER) {
|
|
1858
|
-
types.push(
|
|
1964
|
+
types.push(String(typeToken.value))
|
|
1859
1965
|
this.advance()
|
|
1860
1966
|
}
|
|
1861
1967
|
|
|
@@ -1864,7 +1970,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1864
1970
|
this.advance()
|
|
1865
1971
|
const paramToken = this.current()
|
|
1866
1972
|
if (paramToken && paramToken.type === TokenType.IDENTIFIER) {
|
|
1867
|
-
param =
|
|
1973
|
+
param = String(paramToken.value)
|
|
1868
1974
|
if (param.startsWith('$')) param = param.substring(1)
|
|
1869
1975
|
this.advance()
|
|
1870
1976
|
}
|
|
@@ -1979,7 +2085,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1979
2085
|
const variables = []
|
|
1980
2086
|
do {
|
|
1981
2087
|
const varToken = this.current()
|
|
1982
|
-
let varName =
|
|
2088
|
+
let varName = varToken ? String(varToken.value) : ''
|
|
1983
2089
|
if (varName.startsWith('$')) varName = varName.substring(1)
|
|
1984
2090
|
this.advance()
|
|
1985
2091
|
variables.push(varName)
|
|
@@ -2196,12 +2302,12 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
2196
2302
|
return { type: 'UnaryExpression', operator: '!', operand }
|
|
2197
2303
|
}
|
|
2198
2304
|
|
|
2199
|
-
if (this.match(TokenType.MINUS)
|
|
2305
|
+
if (this.match(TokenType.MINUS)) {
|
|
2200
2306
|
const operand = this.parseUnary(lang)
|
|
2201
2307
|
return { type: 'UnaryExpression', operator: '-', operand }
|
|
2202
2308
|
}
|
|
2203
2309
|
|
|
2204
|
-
if (this.match(TokenType.PLUS)
|
|
2310
|
+
if (this.match(TokenType.PLUS)) {
|
|
2205
2311
|
const operand = this.parseUnary(lang)
|
|
2206
2312
|
return { type: 'UnaryExpression', operator: '+', operand }
|
|
2207
2313
|
}
|
|
@@ -2216,15 +2322,12 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
2216
2322
|
return { type: 'UnaryExpression', operator: '~', operand }
|
|
2217
2323
|
}
|
|
2218
2324
|
|
|
2219
|
-
|
|
2220
|
-
if (current && current.type === TokenType.PLUS && current.value === '++') {
|
|
2221
|
-
this.advance()
|
|
2325
|
+
if (this.match(TokenType.DOUBLE_PLUS)) {
|
|
2222
2326
|
const operand = this.parseUnary(lang)
|
|
2223
2327
|
return { type: 'UpdateExpression', operator: '++', prefix: true, operand }
|
|
2224
2328
|
}
|
|
2225
2329
|
|
|
2226
|
-
if (
|
|
2227
|
-
this.advance()
|
|
2330
|
+
if (this.match(TokenType.DOUBLE_MINUS)) {
|
|
2228
2331
|
const operand = this.parseUnary(lang)
|
|
2229
2332
|
return { type: 'UpdateExpression', operator: '--', prefix: true, operand }
|
|
2230
2333
|
}
|
|
@@ -2333,123 +2436,14 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
2333
2436
|
}
|
|
2334
2437
|
}
|
|
2335
2438
|
|
|
2336
|
-
tryParseMultiWordCall(firstName, lang) {
|
|
2337
|
-
const words = [firstName]
|
|
2338
|
-
let lookAhead = 0
|
|
2339
|
-
|
|
2340
|
-
while (true) {
|
|
2341
|
-
const nextToken = this.peek(lookAhead)
|
|
2342
|
-
if (!nextToken) break
|
|
2343
|
-
|
|
2344
|
-
if (nextToken.type === TokenType.LPAREN) {
|
|
2345
|
-
if (words.length > 1) {
|
|
2346
|
-
for (let i = 0; i < lookAhead; i++) {
|
|
2347
|
-
this.advance()
|
|
2348
|
-
}
|
|
2349
|
-
this.advance()
|
|
2350
|
-
|
|
2351
|
-
const args = []
|
|
2352
|
-
while (!this.isAtEnd() && !this.check(TokenType.RPAREN)) {
|
|
2353
|
-
this.skipNewlines()
|
|
2354
|
-
if (this.check(TokenType.RPAREN)) break
|
|
2355
|
-
|
|
2356
|
-
if (this.match(TokenType.SPREAD) || this.matchValue('...')) {
|
|
2357
|
-
const arg = this.parseExpression(lang)
|
|
2358
|
-
args.push({ type: 'SpreadElement', argument: arg })
|
|
2359
|
-
} else {
|
|
2360
|
-
const arg = this.parseExpression(lang)
|
|
2361
|
-
args.push(arg)
|
|
2362
|
-
}
|
|
2363
|
-
this.match(TokenType.COMMA)
|
|
2364
|
-
this.skipNewlines()
|
|
2365
|
-
}
|
|
2366
|
-
this.match(TokenType.RPAREN)
|
|
2367
|
-
|
|
2368
|
-
const funcName = words.join(' ')
|
|
2369
|
-
return {
|
|
2370
|
-
type: 'CallExpression',
|
|
2371
|
-
callee: { type: 'Identifier', name: funcName },
|
|
2372
|
-
arguments: args
|
|
2373
|
-
}
|
|
2374
|
-
}
|
|
2375
|
-
break
|
|
2376
|
-
}
|
|
2377
|
-
|
|
2378
|
-
if (nextToken.type === TokenType.IDENTIFIER) {
|
|
2379
|
-
words.push(this.safeStr(nextToken.value))
|
|
2380
|
-
lookAhead++
|
|
2381
|
-
} else {
|
|
2382
|
-
break
|
|
2383
|
-
}
|
|
2384
|
-
}
|
|
2385
|
-
|
|
2386
|
-
return null
|
|
2387
|
-
}
|
|
2388
|
-
|
|
2389
|
-
tryParseMultiWordCallFromStart(lang) {
|
|
2390
|
-
const words = []
|
|
2391
|
-
let lookAhead = 0
|
|
2392
|
-
|
|
2393
|
-
while (true) {
|
|
2394
|
-
const token = this.peek(lookAhead)
|
|
2395
|
-
if (!token) break
|
|
2396
|
-
|
|
2397
|
-
if (token.type === TokenType.LPAREN) {
|
|
2398
|
-
if (words.length >= 2) {
|
|
2399
|
-
for (let i = 0; i < lookAhead; i++) {
|
|
2400
|
-
this.advance()
|
|
2401
|
-
}
|
|
2402
|
-
this.advance()
|
|
2403
|
-
|
|
2404
|
-
const args = []
|
|
2405
|
-
while (!this.isAtEnd() && !this.check(TokenType.RPAREN)) {
|
|
2406
|
-
this.skipNewlines()
|
|
2407
|
-
if (this.check(TokenType.RPAREN)) break
|
|
2408
|
-
|
|
2409
|
-
if (this.match(TokenType.SPREAD) || this.matchValue('...')) {
|
|
2410
|
-
const arg = this.parseExpression(lang)
|
|
2411
|
-
args.push({ type: 'SpreadElement', argument: arg })
|
|
2412
|
-
} else {
|
|
2413
|
-
const arg = this.parseExpression(lang)
|
|
2414
|
-
args.push(arg)
|
|
2415
|
-
}
|
|
2416
|
-
this.match(TokenType.COMMA)
|
|
2417
|
-
this.skipNewlines()
|
|
2418
|
-
}
|
|
2419
|
-
this.match(TokenType.RPAREN)
|
|
2420
|
-
|
|
2421
|
-
const funcName = words.join(' ')
|
|
2422
|
-
return {
|
|
2423
|
-
type: 'CallExpression',
|
|
2424
|
-
callee: { type: 'Identifier', name: funcName },
|
|
2425
|
-
arguments: args
|
|
2426
|
-
}
|
|
2427
|
-
}
|
|
2428
|
-
break
|
|
2429
|
-
}
|
|
2430
|
-
|
|
2431
|
-
if (token.type === TokenType.IDENTIFIER) {
|
|
2432
|
-
words.push(this.safeStr(token.value))
|
|
2433
|
-
lookAhead++
|
|
2434
|
-
} else {
|
|
2435
|
-
break
|
|
2436
|
-
}
|
|
2437
|
-
}
|
|
2438
|
-
|
|
2439
|
-
return null
|
|
2440
|
-
}
|
|
2441
|
-
|
|
2442
2439
|
parsePostfix(lang) {
|
|
2443
2440
|
let expr = this.parseCall(lang)
|
|
2444
2441
|
|
|
2445
|
-
|
|
2446
|
-
if (current && current.type === TokenType.PLUS && current.value === '++') {
|
|
2447
|
-
this.advance()
|
|
2442
|
+
if (this.match(TokenType.DOUBLE_PLUS) || this.matchValue('++')) {
|
|
2448
2443
|
return { type: 'UpdateExpression', operator: '++', prefix: false, operand: expr }
|
|
2449
2444
|
}
|
|
2450
2445
|
|
|
2451
|
-
if (
|
|
2452
|
-
this.advance()
|
|
2446
|
+
if (this.match(TokenType.DOUBLE_MINUS) || this.matchValue('--')) {
|
|
2453
2447
|
return { type: 'UpdateExpression', operator: '--', prefix: false, operand: expr }
|
|
2454
2448
|
}
|
|
2455
2449
|
|
|
@@ -2459,13 +2453,6 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
2459
2453
|
parseCall(lang) {
|
|
2460
2454
|
let expr = this.parsePrimary(lang)
|
|
2461
2455
|
|
|
2462
|
-
if (expr && expr.type === 'Identifier') {
|
|
2463
|
-
const multiWordResult = this.tryParseMultiWordCall(expr.name, lang)
|
|
2464
|
-
if (multiWordResult) {
|
|
2465
|
-
return multiWordResult
|
|
2466
|
-
}
|
|
2467
|
-
}
|
|
2468
|
-
|
|
2469
2456
|
while (true) {
|
|
2470
2457
|
if (this.match(TokenType.LPAREN)) {
|
|
2471
2458
|
const args = []
|
|
@@ -2548,11 +2535,11 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
2548
2535
|
|
|
2549
2536
|
if (token.type === TokenType.STRING) {
|
|
2550
2537
|
this.advance()
|
|
2551
|
-
let value =
|
|
2538
|
+
let value = token.value
|
|
2552
2539
|
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|
|
2553
2540
|
value = value.slice(1, -1)
|
|
2554
2541
|
}
|
|
2555
|
-
const isDouble =
|
|
2542
|
+
const isDouble = token.value.startsWith('"')
|
|
2556
2543
|
return { type: 'StringLiteral', value, doubleQuoted: isDouble }
|
|
2557
2544
|
}
|
|
2558
2545
|
|
|
@@ -2562,7 +2549,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
2562
2549
|
}
|
|
2563
2550
|
|
|
2564
2551
|
if (token.type === TokenType.IDENTIFIER) {
|
|
2565
|
-
const value =
|
|
2552
|
+
const value = token.value
|
|
2566
2553
|
const valueLower = this.normalizeAccents(value.toLowerCase())
|
|
2567
2554
|
|
|
2568
2555
|
if (valueLower === 'vrai' || valueLower === 'true') {
|
|
@@ -2612,7 +2599,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
2612
2599
|
return this.parseMatchExpression(lang)
|
|
2613
2600
|
}
|
|
2614
2601
|
|
|
2615
|
-
if (value.startsWith('$')) {
|
|
2602
|
+
if (typeof value === 'string' && value.startsWith('$')) {
|
|
2616
2603
|
this.advance()
|
|
2617
2604
|
return { type: 'Variable', name: value.substring(1) }
|
|
2618
2605
|
}
|
|
@@ -2623,7 +2610,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
2623
2610
|
|
|
2624
2611
|
if (token.type === TokenType.VARIABLE) {
|
|
2625
2612
|
this.advance()
|
|
2626
|
-
let name =
|
|
2613
|
+
let name = String(token.value)
|
|
2627
2614
|
if (name.startsWith('$')) name = name.substring(1)
|
|
2628
2615
|
return { type: 'Variable', name }
|
|
2629
2616
|
}
|