Skip to content

Commit 5225ea1

Browse files
authored
Merge pull request #280 from skoppe/flatten-templates
Fix #272 by moving template code around
2 parents 09bbc34 + 545d786 commit 5225ea1

File tree

1 file changed

+55
-30
lines changed

1 file changed

+55
-30
lines changed

pegged/peg.d

+55-30
Original file line numberDiff line numberDiff line change
@@ -1332,7 +1332,7 @@ template and(rules...) if (rules.length > 0)
13321332
}
13331333
else
13341334
{
1335-
auto firstLongestFailedMatch = result.children.countUntil!(c => c.failEnd > temp.end);
1335+
auto firstLongestFailedMatch = result.children.firstLongestFailedMatch(temp.end);
13361336
if (firstLongestFailedMatch == -1) {
13371337
result.children ~= temp;// add the failed node, to indicate which failed
13381338
if (temp.matches.length > 0)
@@ -1345,8 +1345,8 @@ template and(rules...) if (rules.length > 0)
13451345
// so that it is no longer successful and we want to move its failedChild into its children.
13461346
failedChildFixup(result.children[firstLongestFailedMatch], result.children[firstLongestFailedMatch].failEnd);
13471347
}
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();
13501350
version (tracer)
13511351
{
13521352
if (shouldTrace(getName!(r)(), p))
@@ -1380,33 +1380,54 @@ template and(rules...) if (rules.length > 0)
13801380
return name;
13811381
}
13821382
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;
14071428
}
1408-
return result;
14091429
}
1430+
return result;
14101431
}
14111432
}
14121433
@@ -1725,8 +1746,8 @@ template or(rules...) if (rules.length > 0)
17251746
longestFail.matches = longestFail.matches.length == 0 ? [orErrorString] :
17261747
longestFail.matches[0..$-1] // discarding longestFail error message
17271748
~ [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);
17301751
}
17311752
17321753
ParseTree or(string input)
@@ -1740,6 +1761,10 @@ template or(rules...) if (rules.length > 0)
17401761
}
17411762
}
17421763
1764+
auto getUpto(ParseTree[] children, size_t minFailedLength) {
1765+
return children.filter!(r => max(r.end, r.failEnd) >= minFailedLength).array();
1766+
}
1767+
17431768
unittest // 'or' unit test
17441769
{
17451770
alias charRange!('a','b') ab;

0 commit comments

Comments
 (0)