@@ -1382,6 +1382,7 @@ class Parser
1382
1382
auto startIndex = index;
1383
1383
auto node = allocator.make! AttributeDeclaration;
1384
1384
node.line = current.line;
1385
+ moveStartIndexBefore(startIndex, attribute);
1385
1386
node.attribute = attribute is null ? parseAttribute() : attribute;
1386
1387
mixin (tokenCheck! " :" );
1387
1388
node.tokens = tokens[startIndex .. index];
@@ -1593,10 +1594,11 @@ class Parser
1593
1594
* $(LITERAL 'case') $(RULE assignExpression) $(LITERAL ':') $(LITERAL '...') $(LITERAL 'case') $(RULE assignExpression) $(LITERAL ':') $(RULE declarationsAndStatements)
1594
1595
* ;)
1595
1596
*/
1596
- CaseRangeStatement parseCaseRangeStatement (ExpressionNode low)
1597
+ CaseRangeStatement parseCaseRangeStatement (ExpressionNode low, size_t startIndex = - 1 )
1597
1598
{
1598
1599
mixin (traceEnterAndExit! (__FUNCTION__ ));
1599
- auto startIndex = index;
1600
+ if (startIndex == - 1 )
1601
+ startIndex = index;
1600
1602
auto node = allocator.make! CaseRangeStatement;
1601
1603
assert (low ! is null );
1602
1604
node.low = low;
@@ -1620,10 +1622,11 @@ class Parser
1620
1622
* $(LITERAL 'case') $(RULE _argumentList) $(LITERAL ':') $(RULE declarationsAndStatements)
1621
1623
* ;)
1622
1624
*/
1623
- CaseStatement parseCaseStatement (ArgumentList argumentList = null )
1625
+ CaseStatement parseCaseStatement (ArgumentList argumentList = null , size_t startIndex = - 1 )
1624
1626
{
1625
1627
mixin (traceEnterAndExit! (__FUNCTION__ ));
1626
- auto startIndex = index;
1628
+ if (startIndex == - 1 )
1629
+ startIndex = index;
1627
1630
auto node = allocator.make! CaseStatement;
1628
1631
node.argumentList = argumentList;
1629
1632
const colon = expect(tok! " :" );
@@ -3148,6 +3151,7 @@ class Parser
3148
3151
mixin (traceEnterAndExit! (__FUNCTION__ ));
3149
3152
auto startIndex = index;
3150
3153
auto node = allocator.make! EqualExpression;
3154
+ moveStartIndexBefore(startIndex, shift);
3151
3155
node.left = shift is null ? parseShiftExpression() : shift;
3152
3156
mixin (nullCheck! ` node.left` );
3153
3157
if (currentIsOneOf(tok! " ==" , tok! " !=" ))
@@ -3190,6 +3194,7 @@ class Parser
3190
3194
mixin (traceEnterAndExit! (__FUNCTION__ ));
3191
3195
auto startIndex = index;
3192
3196
auto node = allocator.make! ExpressionStatement;
3197
+ moveStartIndexBefore(startIndex, expression);
3193
3198
node.expression = expression is null ? parseExpression() : expression;
3194
3199
if (node.expression is null || expect(tok! " ;" ) is null )
3195
3200
return null ;
@@ -3575,7 +3580,10 @@ class Parser
3575
3580
break ;
3576
3581
default :
3577
3582
if (unary ! is null )
3583
+ {
3584
+ moveStartIndexBefore(startIndex, unary);
3578
3585
node.unaryExpression = unary;
3586
+ }
3579
3587
else
3580
3588
mixin (parseNodeQ! (` node.unaryExpression` , ` UnaryExpression` ));
3581
3589
if (currentIs(tok! " !" ))
@@ -3633,6 +3641,8 @@ class Parser
3633
3641
comment = null ;
3634
3642
StackBuffer memberFunctionAttributes;
3635
3643
node.attributes = attributes;
3644
+ foreach (attr; attributes)
3645
+ moveStartIndexBefore(startIndex, attr);
3636
3646
3637
3647
if (isAuto)
3638
3648
{
@@ -3660,7 +3670,10 @@ class Parser
3660
3670
if (type is null )
3661
3671
mixin (parseNodeQ! (` node.returnType` , ` Type` ));
3662
3672
else
3673
+ {
3674
+ moveStartIndexBefore(startIndex, type);
3663
3675
node.returnType = type;
3676
+ }
3664
3677
}
3665
3678
3666
3679
mixin (tokenCheck! (` node.name` , " identifier" ));
@@ -4117,6 +4130,7 @@ class Parser
4117
4130
mixin (traceEnterAndExit! (__FUNCTION__ ));
4118
4131
auto startIndex = index;
4119
4132
auto node = allocator.make! IdentityExpression;
4133
+ moveStartIndexBefore(startIndex, shift);
4120
4134
mixin (nullCheck! ` node.left = shift is null ? parseShiftExpression() : shift` );
4121
4135
if (currentIs(tok! " !" ))
4122
4136
{
@@ -4291,6 +4305,7 @@ class Parser
4291
4305
{
4292
4306
auto startIndex = index;
4293
4307
auto node = allocator.make! ImportBindings;
4308
+ moveStartIndexBefore(startIndex, singleImport);
4294
4309
mixin (nullCheck! ` node.singleImport = singleImport is null ? parseSingleImport() : singleImport` );
4295
4310
mixin (tokenCheck! " :" );
4296
4311
StackBuffer importBinds;
@@ -4425,6 +4440,7 @@ class Parser
4425
4440
mixin (traceEnterAndExit! (__FUNCTION__ ));
4426
4441
auto startIndex = index;
4427
4442
auto node = allocator.make! IndexExpression;
4443
+ moveStartIndexBefore(startIndex, unaryExpression);
4428
4444
mixin (nullCheck! ` node.unaryExpression = unaryExpression is null ? parseUnaryExpression() : unaryExpression` );
4429
4445
mixin (tokenCheck! " [" );
4430
4446
StackBuffer indexes;
@@ -4484,6 +4500,7 @@ class Parser
4484
4500
mixin (traceEnterAndExit! (__FUNCTION__ ));
4485
4501
auto startIndex = index;
4486
4502
auto node = allocator.make! InExpression;
4503
+ moveStartIndexBefore(startIndex, shift);
4487
4504
mixin (nullCheck! ` node.left = shift is null ? parseShiftExpression() : shift` );
4488
4505
if (currentIs(tok! " !" ))
4489
4506
{
@@ -6214,9 +6231,9 @@ class Parser
6214
6231
if (argumentList is null )
6215
6232
return null ;
6216
6233
if (argumentList.items.length == 1 && startsWith(tok! " :" , tok! " .." ))
6217
- node.caseRangeStatement = parseCaseRangeStatement(argumentList.items[0 ]);
6234
+ node.caseRangeStatement = parseCaseRangeStatement(argumentList.items[0 ], startIndex );
6218
6235
else
6219
- node.caseStatement = parseCaseStatement(argumentList);
6236
+ node.caseStatement = parseCaseStatement(argumentList, startIndex );
6220
6237
break ;
6221
6238
case tok! " default" :
6222
6239
mixin (parseNodeQ! (` node.defaultStatement` , ` DefaultStatement` ));
@@ -7954,6 +7971,8 @@ class Parser
7954
7971
if (newUnary) newUnary.tokens = tokens[startIndex .. index];
7955
7972
return newUnary;
7956
7973
}
7974
+ if (node ! is null )
7975
+ node.tokens = tokens[startIndex .. index]; // for parseFunctionCallExpression to inherit
7957
7976
mixin (nullCheck! ` newUnary.functionCallExpression = parseFunctionCallExpression(node)` );
7958
7977
node = newUnary;
7959
7978
break ;
@@ -7966,6 +7985,8 @@ class Parser
7966
7985
break ;
7967
7986
case tok! " [" :
7968
7987
auto n = allocator.make! UnaryExpression;
7988
+ if (node ! is null )
7989
+ node.tokens = tokens[startIndex .. index]; // for parseIndexExpression to inherit
7969
7990
n.indexExpression = parseIndexExpression(node);
7970
7991
node = n;
7971
7992
break ;
@@ -8076,6 +8097,7 @@ class Parser
8076
8097
return null ;
8077
8098
ownArray(node.storageClasses, storageClasses);
8078
8099
8100
+ moveStartIndexBefore(startIndex, type);
8079
8101
node.type = type is null ? parseType() : type;
8080
8102
node.comment = comment;
8081
8103
comment = null ;
@@ -8733,6 +8755,27 @@ protected: final:
8733
8755
}
8734
8756
}
8735
8757
8758
+ void moveStartIndexBefore (ref size_t startIndex, const BaseNode child, string func = __FUNCTION__ )
8759
+ {
8760
+ if (child ! is null )
8761
+ {
8762
+ debug
8763
+ {
8764
+ assert (child.tokens.length,
8765
+ " AST parameter must be finalized or receive early tokens slice before calling "
8766
+ ~ func);
8767
+ }
8768
+ else
8769
+ {
8770
+ if (! child.tokens.length)
8771
+ return ;
8772
+ }
8773
+
8774
+ startIndex = min(startIndex, &child.tokens[0 ] - &tokens[0 ]);
8775
+ assert (startIndex >= 0 && startIndex < tokens.length);
8776
+ }
8777
+ }
8778
+
8736
8779
bool currentIsMemberFunctionAttribute () const
8737
8780
{
8738
8781
return moreTokens && isMemberFunctionAttribute(current.type);
@@ -8743,6 +8786,7 @@ protected: final:
8743
8786
{
8744
8787
ExpressionNode node;
8745
8788
auto startIndex = index;
8789
+ moveStartIndexBefore(startIndex, part);
8746
8790
mixin (" node = part is null ? parse" ~ ExpressionPartType.stringof ~ " () : part;" );
8747
8791
if (node is null )
8748
8792
return null ;
0 commit comments