ether-code 0.8.3 → 0.8.5
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 +67 -29
- package/package.json +1 -1
- package/parsers/ether-parser-php.js +187 -30
package/cli/ether.js
CHANGED
|
@@ -101,6 +101,8 @@ class PHPGenerator {
|
|
|
101
101
|
|
|
102
102
|
const generators = {
|
|
103
103
|
'Program': () => this.generateProgram(node),
|
|
104
|
+
'DeclareStatement': () => this.generateDeclareStatement(node),
|
|
105
|
+
'NamespaceDeclaration': () => this.generateNamespaceDeclaration(node),
|
|
104
106
|
'FunctionDeclaration': () => this.generateFunctionDeclaration(node),
|
|
105
107
|
'ClassDeclaration': () => this.generateClassDeclaration(node),
|
|
106
108
|
'InterfaceDeclaration': () => this.generateInterfaceDeclaration(node),
|
|
@@ -110,6 +112,7 @@ class PHPGenerator {
|
|
|
110
112
|
'PropertyDeclaration': () => this.generatePropertyDeclaration(node),
|
|
111
113
|
'VariableDeclaration': () => this.generateVariableDeclaration(node),
|
|
112
114
|
'ConstantDeclaration': () => this.generateConstantDeclaration(node),
|
|
115
|
+
'DefineDeclaration': () => this.generateDefineDeclaration(node),
|
|
113
116
|
'IfStatement': () => this.generateIfStatement(node),
|
|
114
117
|
'ForStatement': () => this.generateForStatement(node),
|
|
115
118
|
'ForEachStatement': () => this.generateForEachStatement(node),
|
|
@@ -176,6 +179,33 @@ class PHPGenerator {
|
|
|
176
179
|
}
|
|
177
180
|
}
|
|
178
181
|
|
|
182
|
+
generateDeclareStatement(node) {
|
|
183
|
+
const directives = (node.directives || []).map(d => {
|
|
184
|
+
const name = this.safeString(d.name)
|
|
185
|
+
const value = this.generateNode(d.value)
|
|
186
|
+
return `${name}=${value}`
|
|
187
|
+
}).join(', ')
|
|
188
|
+
|
|
189
|
+
this.writeLine(`declare(${directives});`)
|
|
190
|
+
this.writeLine('')
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
generateNamespaceDeclaration(node) {
|
|
194
|
+
const name = this.safeString(node.name)
|
|
195
|
+
this.writeLine(`namespace ${name};`)
|
|
196
|
+
this.writeLine('')
|
|
197
|
+
|
|
198
|
+
if (node.body) {
|
|
199
|
+
this.generateNode(node.body)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
generateDefineDeclaration(node) {
|
|
204
|
+
const name = this.safeString(node.name)
|
|
205
|
+
const value = this.generateNode(node.value)
|
|
206
|
+
this.writeLine(`define('${name}', ${value});`)
|
|
207
|
+
}
|
|
208
|
+
|
|
179
209
|
generateFunctionDeclaration(node) {
|
|
180
210
|
const name = this.safeString(node.name || node.id?.name || 'anonymous')
|
|
181
211
|
const translatedName = this.translate(name)
|
|
@@ -465,7 +495,7 @@ class PHPGenerator {
|
|
|
465
495
|
generateVariableDeclaration(node) {
|
|
466
496
|
for (const decl of node.declarations || [node]) {
|
|
467
497
|
const name = this.safeString(decl.name || decl.id?.name || decl.id)
|
|
468
|
-
const varName = '$' +
|
|
498
|
+
const varName = '$' + name
|
|
469
499
|
|
|
470
500
|
if (decl.init !== undefined) {
|
|
471
501
|
const value = this.generateNode(decl.init)
|
|
@@ -489,7 +519,7 @@ class PHPGenerator {
|
|
|
489
519
|
}
|
|
490
520
|
|
|
491
521
|
generateIfStatement(node) {
|
|
492
|
-
const test = this.generateNode(node.test)
|
|
522
|
+
const test = this.generateNode(node.test || node.condition)
|
|
493
523
|
this.writeLine(`if (${test}) {`)
|
|
494
524
|
this.indent++
|
|
495
525
|
this.generateNode(node.consequent)
|
|
@@ -497,7 +527,7 @@ class PHPGenerator {
|
|
|
497
527
|
|
|
498
528
|
if (node.alternate) {
|
|
499
529
|
if (node.alternate.type === 'IfStatement') {
|
|
500
|
-
this.write('} else')
|
|
530
|
+
this.write('} else ')
|
|
501
531
|
this.generateIfStatement({ ...node.alternate, isElseIf: true })
|
|
502
532
|
} else {
|
|
503
533
|
this.writeLine('} else {')
|
|
@@ -536,7 +566,7 @@ class PHPGenerator {
|
|
|
536
566
|
}
|
|
537
567
|
|
|
538
568
|
generateWhileStatement(node) {
|
|
539
|
-
const test = this.generateNode(node.test)
|
|
569
|
+
const test = this.generateNode(node.test || node.condition)
|
|
540
570
|
this.writeLine(`while (${test}) {`)
|
|
541
571
|
this.indent++
|
|
542
572
|
this.generateNode(node.body)
|
|
@@ -549,7 +579,7 @@ class PHPGenerator {
|
|
|
549
579
|
this.indent++
|
|
550
580
|
this.generateNode(node.body)
|
|
551
581
|
this.indent--
|
|
552
|
-
const test = this.generateNode(node.test)
|
|
582
|
+
const test = this.generateNode(node.test || node.condition)
|
|
553
583
|
this.writeLine(`} while (${test});`)
|
|
554
584
|
}
|
|
555
585
|
|
|
@@ -640,7 +670,8 @@ class PHPGenerator {
|
|
|
640
670
|
}
|
|
641
671
|
|
|
642
672
|
generateEchoStatement(node) {
|
|
643
|
-
const
|
|
673
|
+
const exprs = node.expressions || node.arguments || [node.argument]
|
|
674
|
+
const args = exprs.filter(Boolean).map(a => this.generateNode(a)).join(', ')
|
|
644
675
|
this.writeLine(`echo ${args};`)
|
|
645
676
|
}
|
|
646
677
|
|
|
@@ -656,10 +687,19 @@ class PHPGenerator {
|
|
|
656
687
|
}
|
|
657
688
|
|
|
658
689
|
generateUseStatement(node) {
|
|
659
|
-
const
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
690
|
+
const typePrefix = node.useType === 'function' ? 'function ' : (node.useType === 'const' ? 'const ' : '')
|
|
691
|
+
|
|
692
|
+
if (node.imports && node.imports.length > 0) {
|
|
693
|
+
for (const imp of node.imports) {
|
|
694
|
+
const path = this.safeString(imp.path)
|
|
695
|
+
const alias = imp.alias ? ' as ' + imp.alias : ''
|
|
696
|
+
this.writeLine(`use ${typePrefix}${path}${alias};`)
|
|
697
|
+
}
|
|
698
|
+
} else {
|
|
699
|
+
const name = this.safeString(node.name || node.source)
|
|
700
|
+
const alias = node.alias ? ' as ' + node.alias : ''
|
|
701
|
+
this.writeLine(`use ${typePrefix}${name}${alias};`)
|
|
702
|
+
}
|
|
663
703
|
}
|
|
664
704
|
|
|
665
705
|
generateIncludeStatement(node) {
|
|
@@ -772,21 +812,21 @@ class PHPGenerator {
|
|
|
772
812
|
}
|
|
773
813
|
|
|
774
814
|
generateUnaryExpression(node) {
|
|
775
|
-
const argument = this.generateNode(node.argument)
|
|
815
|
+
const argument = this.generateNode(node.argument || node.operand)
|
|
776
816
|
let op = node.operator
|
|
777
817
|
if (op === 'non' || op === 'not') op = '!'
|
|
778
818
|
|
|
779
|
-
if (node.prefix) {
|
|
819
|
+
if (node.prefix !== false) {
|
|
780
820
|
return `${op}${argument}`
|
|
781
821
|
}
|
|
782
822
|
return `${argument}${op}`
|
|
783
823
|
}
|
|
784
824
|
|
|
785
825
|
generateUpdateExpression(node) {
|
|
786
|
-
const argument = this.generateNode(node.argument)
|
|
826
|
+
const argument = this.generateNode(node.argument || node.operand)
|
|
787
827
|
const op = node.operator
|
|
788
828
|
|
|
789
|
-
if (node.prefix) {
|
|
829
|
+
if (node.prefix !== false) {
|
|
790
830
|
return `${op}${argument}`
|
|
791
831
|
}
|
|
792
832
|
return `${argument}${op}`
|
|
@@ -878,43 +918,41 @@ class PHPGenerator {
|
|
|
878
918
|
if (!node) return '$var'
|
|
879
919
|
|
|
880
920
|
const name = this.safeString(node.name || node.id?.name || node)
|
|
881
|
-
const
|
|
882
|
-
const translatedStr = String(translated)
|
|
921
|
+
const nameStr = String(name)
|
|
883
922
|
|
|
884
|
-
if (
|
|
885
|
-
return '$' +
|
|
923
|
+
if (nameStr.startsWith('$')) return nameStr
|
|
924
|
+
return '$' + nameStr
|
|
886
925
|
}
|
|
887
926
|
|
|
888
927
|
generateIdentifier(node) {
|
|
889
928
|
if (!node) return '$var'
|
|
890
929
|
|
|
891
930
|
const name = this.safeString(node.name || node.id?.name || node)
|
|
892
|
-
const
|
|
893
|
-
const translatedStr = String(translated)
|
|
931
|
+
const nameStr = String(name)
|
|
894
932
|
|
|
895
|
-
if (
|
|
933
|
+
if (nameStr.startsWith('$')) return nameStr
|
|
896
934
|
|
|
897
935
|
const keywords = [
|
|
898
936
|
'true', 'false', 'null',
|
|
899
937
|
'self', 'parent', 'static',
|
|
900
938
|
'this', '$this'
|
|
901
939
|
]
|
|
902
|
-
if (keywords.includes(
|
|
903
|
-
if (
|
|
904
|
-
return
|
|
940
|
+
if (keywords.includes(nameStr.toLowerCase())) {
|
|
941
|
+
if (nameStr.toLowerCase() === 'this') return '$this'
|
|
942
|
+
return nameStr
|
|
905
943
|
}
|
|
906
944
|
|
|
907
|
-
if (/^[A-Z]/.test(
|
|
945
|
+
if (/^[A-Z]/.test(nameStr)) return nameStr
|
|
908
946
|
|
|
909
|
-
if (
|
|
947
|
+
if (nameStr.includes('(') || nameStr.includes('::')) return nameStr
|
|
910
948
|
|
|
911
949
|
const superglobals = ['_GET', '_POST', '_SERVER', '_SESSION', '_COOKIE', '_FILES', '_REQUEST', '_ENV', 'GLOBALS']
|
|
912
|
-
const upper =
|
|
913
|
-
if (superglobals.includes(
|
|
950
|
+
const upper = nameStr.toUpperCase()
|
|
951
|
+
if (superglobals.includes(nameStr) || superglobals.includes(upper)) {
|
|
914
952
|
return '$' + upper
|
|
915
953
|
}
|
|
916
954
|
|
|
917
|
-
return '$' +
|
|
955
|
+
return '$' + nameStr
|
|
918
956
|
}
|
|
919
957
|
|
|
920
958
|
generateLiteral(node) {
|
package/package.json
CHANGED
|
@@ -278,6 +278,10 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
278
278
|
|
|
279
279
|
const value = token.value != null ? this.normalizeAccents(String(token.value).toLowerCase()) : ''
|
|
280
280
|
|
|
281
|
+
if (this.isDeclare(value)) {
|
|
282
|
+
return this.parseDeclare(lang)
|
|
283
|
+
}
|
|
284
|
+
|
|
281
285
|
if (this.isNamespace(value)) {
|
|
282
286
|
return this.parseNamespace(lang)
|
|
283
287
|
}
|
|
@@ -371,7 +375,17 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
371
375
|
}
|
|
372
376
|
|
|
373
377
|
isNamespace(value) {
|
|
374
|
-
|
|
378
|
+
if (value === 'namespace') return true
|
|
379
|
+
if (value === 'espace') {
|
|
380
|
+
const next1 = this.peek(1)
|
|
381
|
+
const next2 = this.peek(2)
|
|
382
|
+
if (next1 && next2) {
|
|
383
|
+
const val1 = this.normalizeAccents(String(next1.value).toLowerCase())
|
|
384
|
+
const val2 = this.normalizeAccents(String(next2.value).toLowerCase())
|
|
385
|
+
if (val1 === 'de' && val2 === 'noms') return true
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return false
|
|
375
389
|
}
|
|
376
390
|
|
|
377
391
|
isUse(value) {
|
|
@@ -469,8 +483,54 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
469
483
|
return value === 'match'
|
|
470
484
|
}
|
|
471
485
|
|
|
472
|
-
|
|
486
|
+
isDeclare(value) {
|
|
487
|
+
return ['declare', 'declarer', 'déclarer'].includes(value)
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
parseDeclare(lang) {
|
|
473
491
|
this.advance()
|
|
492
|
+
|
|
493
|
+
const directives = []
|
|
494
|
+
|
|
495
|
+
if (this.match(TokenType.LPAREN)) {
|
|
496
|
+
do {
|
|
497
|
+
const nameToken = this.current()
|
|
498
|
+
const name = nameToken ? this.safeStr(nameToken.value) : ''
|
|
499
|
+
this.advance()
|
|
500
|
+
|
|
501
|
+
this.match(TokenType.EQUALS)
|
|
502
|
+
|
|
503
|
+
const value = this.parseExpression(lang)
|
|
504
|
+
directives.push({ name, value })
|
|
505
|
+
} while (this.match(TokenType.COMMA))
|
|
506
|
+
|
|
507
|
+
this.match(TokenType.RPAREN)
|
|
508
|
+
} else {
|
|
509
|
+
const nameToken = this.current()
|
|
510
|
+
const name = nameToken ? this.safeStr(nameToken.value) : ''
|
|
511
|
+
this.advance()
|
|
512
|
+
|
|
513
|
+
this.match(TokenType.EQUALS)
|
|
514
|
+
|
|
515
|
+
const value = this.parseExpression(lang)
|
|
516
|
+
directives.push({ name, value })
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
return {
|
|
520
|
+
type: 'DeclareStatement',
|
|
521
|
+
directives: directives
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
parseNamespace(lang) {
|
|
526
|
+
const first = this.advance()
|
|
527
|
+
const firstVal = this.normalizeAccents(String(first.value).toLowerCase())
|
|
528
|
+
|
|
529
|
+
if (firstVal === 'espace') {
|
|
530
|
+
this.advance()
|
|
531
|
+
this.advance()
|
|
532
|
+
}
|
|
533
|
+
|
|
474
534
|
const name = this.parseNamespacePath(lang)
|
|
475
535
|
this.skipNewlines()
|
|
476
536
|
|
|
@@ -1098,6 +1158,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1098
1158
|
let variadic = false
|
|
1099
1159
|
let byReference = false
|
|
1100
1160
|
let defaultValue = null
|
|
1161
|
+
let name = null
|
|
1101
1162
|
|
|
1102
1163
|
const val = this.current() ? this.normalizeAccents(String(this.current().value).toLowerCase()) : ''
|
|
1103
1164
|
if (this.phpVisibility.includes(val)) {
|
|
@@ -1111,16 +1172,6 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1111
1172
|
this.advance()
|
|
1112
1173
|
}
|
|
1113
1174
|
|
|
1114
|
-
const currentType = this.current()
|
|
1115
|
-
if (currentType && currentType.type === TokenType.IDENTIFIER) {
|
|
1116
|
-
const typeLower = this.normalizeAccents(String(currentType.value).toLowerCase())
|
|
1117
|
-
if (this.phpTypes[typeLower] || typeLower[0] === typeLower[0].toUpperCase()) {
|
|
1118
|
-
if (!this.peek(1) || this.peek(1).type !== TokenType.EQUALS) {
|
|
1119
|
-
typeHint = this.parseTypeHint(lang)
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
1175
|
if (this.match(TokenType.SPREAD) || this.matchValue('...')) {
|
|
1125
1176
|
variadic = true
|
|
1126
1177
|
}
|
|
@@ -1129,14 +1180,34 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1129
1180
|
byReference = true
|
|
1130
1181
|
}
|
|
1131
1182
|
|
|
1132
|
-
const
|
|
1133
|
-
if (!
|
|
1183
|
+
const currentToken = this.current()
|
|
1184
|
+
if (!currentToken) return null
|
|
1185
|
+
|
|
1186
|
+
const nextToken = this.peek(1)
|
|
1134
1187
|
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
name = name.substring(1)
|
|
1188
|
+
if (nextToken && nextToken.type === TokenType.COLON) {
|
|
1189
|
+
name = this.safeStr(currentToken.value)
|
|
1190
|
+
if (name.startsWith('$')) name = name.substring(1)
|
|
1191
|
+
this.advance()
|
|
1192
|
+
this.advance()
|
|
1193
|
+
typeHint = this.parseTypeHint(lang)
|
|
1194
|
+
} else {
|
|
1195
|
+
const typeLower = this.normalizeAccents(String(currentToken.value).toLowerCase())
|
|
1196
|
+
if (this.phpTypes[typeLower] || /^[A-Z]/.test(currentToken.value)) {
|
|
1197
|
+
typeHint = this.parseTypeHint(lang)
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
const nameToken = this.current()
|
|
1201
|
+
if (nameToken && nameToken.type === TokenType.IDENTIFIER) {
|
|
1202
|
+
name = this.safeStr(nameToken.value)
|
|
1203
|
+
if (name.startsWith('$')) name = name.substring(1)
|
|
1204
|
+
this.advance()
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
if (!name) {
|
|
1209
|
+
name = 'param'
|
|
1138
1210
|
}
|
|
1139
|
-
this.advance()
|
|
1140
1211
|
|
|
1141
1212
|
if (this.match(TokenType.EQUALS)) {
|
|
1142
1213
|
defaultValue = this.parseExpression(lang)
|
|
@@ -1252,9 +1323,10 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1252
1323
|
condition = this.parseExpression(lang)
|
|
1253
1324
|
this.match(TokenType.RPAREN)
|
|
1254
1325
|
} else {
|
|
1255
|
-
condition = this.
|
|
1326
|
+
condition = this.parseConditionUntilColon(lang)
|
|
1256
1327
|
}
|
|
1257
1328
|
|
|
1329
|
+
this.match(TokenType.COLON)
|
|
1258
1330
|
this.skipNewlines()
|
|
1259
1331
|
const consequent = this.parseBlock(lang)
|
|
1260
1332
|
|
|
@@ -1262,31 +1334,64 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1262
1334
|
this.skipNewlines()
|
|
1263
1335
|
|
|
1264
1336
|
const elseVal = this.current() ? this.normalizeAccents(String(this.current().value).toLowerCase()) : ''
|
|
1265
|
-
if (elseVal === 'sinon
|
|
1266
|
-
this.advance()
|
|
1267
|
-
alternate = this.parseConditional(lang)
|
|
1268
|
-
alternate.type = 'ElseIfStatement'
|
|
1269
|
-
} else if (elseVal === 'sinon' || elseVal === 'else') {
|
|
1337
|
+
if (elseVal === 'sinon') {
|
|
1270
1338
|
this.advance()
|
|
1271
1339
|
|
|
1272
1340
|
const nextVal = this.current() ? this.normalizeAccents(String(this.current().value).toLowerCase()) : ''
|
|
1273
1341
|
if (nextVal === 'si' || nextVal === 'if') {
|
|
1274
1342
|
alternate = this.parseConditional(lang)
|
|
1275
|
-
alternate.type = '
|
|
1343
|
+
alternate.type = 'IfStatement'
|
|
1276
1344
|
} else {
|
|
1345
|
+
this.match(TokenType.COLON)
|
|
1277
1346
|
this.skipNewlines()
|
|
1278
1347
|
alternate = this.parseBlock(lang)
|
|
1279
1348
|
}
|
|
1349
|
+
} else if (elseVal === 'else') {
|
|
1350
|
+
this.advance()
|
|
1351
|
+
this.match(TokenType.COLON)
|
|
1352
|
+
this.skipNewlines()
|
|
1353
|
+
alternate = this.parseBlock(lang)
|
|
1280
1354
|
}
|
|
1281
1355
|
|
|
1282
1356
|
return {
|
|
1283
1357
|
type: 'IfStatement',
|
|
1284
|
-
|
|
1358
|
+
test: condition,
|
|
1285
1359
|
consequent: consequent,
|
|
1286
1360
|
alternate: alternate
|
|
1287
1361
|
}
|
|
1288
1362
|
}
|
|
1289
1363
|
|
|
1364
|
+
parseConditionUntilColon(lang) {
|
|
1365
|
+
const startPos = this.pos
|
|
1366
|
+
let depth = 0
|
|
1367
|
+
|
|
1368
|
+
while (!this.isAtEnd()) {
|
|
1369
|
+
const token = this.current()
|
|
1370
|
+
if (!token) break
|
|
1371
|
+
|
|
1372
|
+
if (token.type === TokenType.LPAREN) depth++
|
|
1373
|
+
if (token.type === TokenType.RPAREN) depth--
|
|
1374
|
+
|
|
1375
|
+
if (depth === 0 && token.type === TokenType.COLON) {
|
|
1376
|
+
break
|
|
1377
|
+
}
|
|
1378
|
+
if (depth === 0 && token.type === TokenType.NEWLINE) {
|
|
1379
|
+
break
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
this.advance()
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
const endPos = this.pos
|
|
1386
|
+
this.pos = startPos
|
|
1387
|
+
|
|
1388
|
+
if (endPos > startPos) {
|
|
1389
|
+
return this.parseExpression(lang)
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
return { type: 'Literal', value: true }
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1290
1395
|
parseLoop(lang) {
|
|
1291
1396
|
const token = this.current()
|
|
1292
1397
|
const value = this.normalizeAccents(String(token.value).toLowerCase())
|
|
@@ -1325,7 +1430,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1325
1430
|
|
|
1326
1431
|
parseFor(lang) {
|
|
1327
1432
|
this.advance()
|
|
1328
|
-
|
|
1433
|
+
|
|
1329
1434
|
let init = null
|
|
1330
1435
|
let test = null
|
|
1331
1436
|
let update = null
|
|
@@ -1345,8 +1450,23 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1345
1450
|
update = this.parseExpression(lang)
|
|
1346
1451
|
}
|
|
1347
1452
|
this.match(TokenType.RPAREN)
|
|
1453
|
+
} else {
|
|
1454
|
+
if (!this.check(TokenType.SEMICOLON) && !this.check(TokenType.COLON)) {
|
|
1455
|
+
init = this.parseExpression(lang)
|
|
1456
|
+
}
|
|
1457
|
+
this.match(TokenType.SEMICOLON)
|
|
1458
|
+
|
|
1459
|
+
if (!this.check(TokenType.SEMICOLON) && !this.check(TokenType.COLON)) {
|
|
1460
|
+
test = this.parseExpression(lang)
|
|
1461
|
+
}
|
|
1462
|
+
this.match(TokenType.SEMICOLON)
|
|
1463
|
+
|
|
1464
|
+
if (!this.check(TokenType.COLON) && !this.check(TokenType.NEWLINE)) {
|
|
1465
|
+
update = this.parseExpression(lang)
|
|
1466
|
+
}
|
|
1348
1467
|
}
|
|
1349
1468
|
|
|
1469
|
+
this.match(TokenType.COLON)
|
|
1350
1470
|
this.skipNewlines()
|
|
1351
1471
|
const body = this.parseBlock(lang)
|
|
1352
1472
|
|
|
@@ -1390,7 +1510,7 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1390
1510
|
}
|
|
1391
1511
|
|
|
1392
1512
|
const valueVar = this.current()
|
|
1393
|
-
|
|
1513
|
+
value = this.safeStr(valueVar ? valueVar.value : 'value')
|
|
1394
1514
|
if (value.startsWith('$')) value = value.substring(1)
|
|
1395
1515
|
this.advance()
|
|
1396
1516
|
} else {
|
|
@@ -1398,8 +1518,44 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1398
1518
|
}
|
|
1399
1519
|
|
|
1400
1520
|
this.match(TokenType.RPAREN)
|
|
1521
|
+
} else {
|
|
1522
|
+
const arrayToken = this.current()
|
|
1523
|
+
if (arrayToken) {
|
|
1524
|
+
array = { type: 'Identifier', name: this.safeStr(arrayToken.value) }
|
|
1525
|
+
this.advance()
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
const asVal = this.current() ? this.normalizeAccents(String(this.current().value).toLowerCase()) : ''
|
|
1529
|
+
if (asVal === 'comme' || asVal === 'as') {
|
|
1530
|
+
this.advance()
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
if (this.match(TokenType.AMPERSAND)) {
|
|
1534
|
+
byRef = true
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
const firstVar = this.current()
|
|
1538
|
+
let firstName = this.safeStr(firstVar ? firstVar.value : 'item')
|
|
1539
|
+
if (firstName.startsWith('$')) firstName = firstName.substring(1)
|
|
1540
|
+
this.advance()
|
|
1541
|
+
|
|
1542
|
+
if (this.match(TokenType.DOUBLE_ARROW) || this.matchValue('=>')) {
|
|
1543
|
+
key = firstName
|
|
1544
|
+
|
|
1545
|
+
if (this.match(TokenType.AMPERSAND)) {
|
|
1546
|
+
byRef = true
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
const valueVar = this.current()
|
|
1550
|
+
value = this.safeStr(valueVar ? valueVar.value : 'value')
|
|
1551
|
+
if (value.startsWith('$')) value = value.substring(1)
|
|
1552
|
+
this.advance()
|
|
1553
|
+
} else {
|
|
1554
|
+
value = firstName
|
|
1555
|
+
}
|
|
1401
1556
|
}
|
|
1402
1557
|
|
|
1558
|
+
this.match(TokenType.COLON)
|
|
1403
1559
|
this.skipNewlines()
|
|
1404
1560
|
const body = this.parseBlock(lang)
|
|
1405
1561
|
|
|
@@ -1419,15 +1575,16 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
1419
1575
|
condition = this.parseExpression(lang)
|
|
1420
1576
|
this.match(TokenType.RPAREN)
|
|
1421
1577
|
} else {
|
|
1422
|
-
condition = this.
|
|
1578
|
+
condition = this.parseConditionUntilColon(lang)
|
|
1423
1579
|
}
|
|
1424
1580
|
|
|
1581
|
+
this.match(TokenType.COLON)
|
|
1425
1582
|
this.skipNewlines()
|
|
1426
1583
|
const body = this.parseBlock(lang)
|
|
1427
1584
|
|
|
1428
1585
|
return {
|
|
1429
1586
|
type: 'WhileStatement',
|
|
1430
|
-
|
|
1587
|
+
test: condition,
|
|
1431
1588
|
body: body
|
|
1432
1589
|
}
|
|
1433
1590
|
}
|