@@ -1332,7 +1332,7 @@ template and(rules...) if (rules.length > 0)
1332
1332
}
1333
1333
else
1334
1334
{
1335
- auto firstLongestFailedMatch = result.children.countUntil!(c => c.failEnd > temp.end);
1335
+ auto firstLongestFailedMatch = result.children.firstLongestFailedMatch( temp.end);
1336
1336
if (firstLongestFailedMatch == -1) {
1337
1337
result.children ~= temp;// add the failed node, to indicate which failed
1338
1338
if (temp.matches.length > 0)
@@ -1345,8 +1345,8 @@ template and(rules...) if (rules.length > 0)
1345
1345
// so that it is no longer successful and we want to move its failedChild into its children.
1346
1346
failedChildFixup(result.children[firstLongestFailedMatch], result.children[firstLongestFailedMatch].failEnd);
1347
1347
}
1348
- result.end = result.children.map!(c => c.end).maxElement ;
1349
- result.failEnd = result.children.map!(c => c.failEnd).maxElement ;
1348
+ result.end = result.children.maxEnd() ;
1349
+ result.failEnd = result.children.maxFailEnd() ;
1350
1350
version (tracer)
1351
1351
{
1352
1352
if (shouldTrace(getName!(r)(), p))
@@ -1380,33 +1380,54 @@ template and(rules...) if (rules.length > 0)
1380
1380
return name;
1381
1381
}
1382
1382
1383
- // A child ParseTree has kept track of an alternate ParseTree (in failedChild) that matches longer.
1384
- // whenever the 'and' rule fails we want to rewrite that child so that the failedChild is
1385
- // moved into its children, the successful is set to false, the end is set the its failEnd,
1386
- // the failEnd is reset, and all that info is propagated upwards the tree so intermediate
1387
- // nodes reflect the proper state.
1388
- bool failedChildFixup(ref ParseTree p, size_t failEnd) {
1389
- if (p.failedChild.length > 0) {
1390
- p.children ~= p.failedChild[0];
1391
- p.failedChild = [];
1392
- p.successful = false;
1393
- p.end = p.failEnd;
1394
- p.failEnd = p.children.map!(c => c.failEnd).maxElement();
1395
- return true;
1396
- } else {
1397
- bool result = false;
1398
- foreach(ref c; p.children) {
1399
- if (c.failEnd != failEnd)
1400
- continue;
1401
- if (failedChildFixup(c, failEnd)) {
1402
- p.end = c.end;
1403
- p.successful = false;
1404
- p.failEnd = p.children.map!(c => c.failEnd).maxElement();
1405
- result = true;
1406
- }
1383
+ }
1384
+
1385
+ auto firstLongestFailedMatch(ParseTree[] children, size_t threshold) {
1386
+ return children.countUntil!(c => c.failEnd > threshold);
1387
+ }
1388
+
1389
+ auto maxFailEnd(ParseTree[] children)
1390
+ {
1391
+ return children.map!(c => c.failEnd).maxElement;
1392
+ }
1393
+
1394
+ auto maxEnd(ParseTree[] children)
1395
+ {
1396
+ return children.map!(c => c.end).maxElement;
1397
+ }
1398
+
1399
+ // A child ParseTree has kept track of an alternate ParseTree (in failedChild) that matches longer.
1400
+ // whenever the 'and' rule fails we want to rewrite that child so that the failedChild is
1401
+ // moved into its children, the successful is set to false, the end is set the its failEnd,
1402
+ // the failEnd is reset, and all that info is propagated upwards the tree so intermediate
1403
+ // nodes reflect the proper state.
1404
+ bool failedChildFixup(ref ParseTree p, size_t failEnd)
1405
+ {
1406
+ if (p.failedChild.length > 0)
1407
+ {
1408
+ p.children ~= p.failedChild[0];
1409
+ p.failedChild = [];
1410
+ p.successful = false;
1411
+ p.end = p.failEnd;
1412
+ p.failEnd = p.children.map!(c => c.failEnd).maxElement();
1413
+ return true;
1414
+ }
1415
+ else
1416
+ {
1417
+ bool result = false;
1418
+ foreach (ref c; p.children)
1419
+ {
1420
+ if (c.failEnd != failEnd)
1421
+ continue;
1422
+ if (failedChildFixup(c, failEnd))
1423
+ {
1424
+ p.end = c.end;
1425
+ p.successful = false;
1426
+ p.failEnd = p.children.map!(c => c.failEnd).maxElement();
1427
+ result = true;
1407
1428
}
1408
- return result;
1409
1429
}
1430
+ return result;
1410
1431
}
1411
1432
}
1412
1433
@@ -1725,8 +1746,8 @@ template or(rules...) if (rules.length > 0)
1725
1746
longestFail.matches = longestFail.matches.length == 0 ? [orErrorString] :
1726
1747
longestFail.matches[0..$-1] // discarding longestFail error message
1727
1748
~ [orErrorString]; // and replacing it by the new, concatenated one.
1728
- auto children = results[].filter!(r => max(r.end, r.failEnd) >= maxFailedLength).array( );
1729
- return ParseTree(name, false, longestFail.matches, p.input, p.end, longestFail.end, children, children.map!(c => c.failEnd).maxElement );
1749
+ auto children = results[].getUpto( maxFailedLength);
1750
+ return ParseTree(name, false, longestFail.matches, p.input, p.end, longestFail.end, children, children.maxFailEnd );
1730
1751
}
1731
1752
1732
1753
ParseTree or(string input)
@@ -1740,6 +1761,10 @@ template or(rules...) if (rules.length > 0)
1740
1761
}
1741
1762
}
1742
1763
1764
+ auto getUpto(ParseTree[] children, size_t minFailedLength) {
1765
+ return children.filter!(r => max(r.end, r.failEnd) >= minFailedLength).array();
1766
+ }
1767
+
1743
1768
unittest // 'or' unit test
1744
1769
{
1745
1770
alias charRange!('a','b') ab;
0 commit comments