|
| 1 | +/* |
| 2 | + To find iter nodes that are derived from the same repetition expression, we |
| 3 | + look for adjacent iter nodes that have the same source interval and the same |
| 4 | + number of children. |
| 5 | +
|
| 6 | + A few things to note: |
| 7 | + - The children of `*` and `+` nodes can't be nullable, so the associated iter |
| 8 | + nodes always consume some input, and therefore consecutive nodes that have |
| 9 | + the same interval must come from the same repetition expression. |
| 10 | + - We *could* mistake `a? b?` for (a b)?`, if neither of them comsume any input. |
| 11 | + However, for the purposes of this module, those two cases are equivalent |
| 12 | + anyways, since we only care about finding the correct order of the non-iter |
| 13 | + nodes. |
| 14 | + */ |
| 15 | +const isIterSibling = (refNode, n) => { |
| 16 | + return ( |
| 17 | + n.isIteration() && |
| 18 | + n.source.startIdx === refNode.source.startIdx && |
| 19 | + n.source.endIdx === refNode.source.endIdx && |
| 20 | + n.children.length === refNode.children.length |
| 21 | + ); |
| 22 | +}; |
| 23 | + |
| 24 | +export function recoverIterOrder(nodes, depth = 0) { |
| 25 | + const ans = []; |
| 26 | + for (let i = 0; i < nodes.length; i++) { |
| 27 | + const n = nodes[i]; |
| 28 | + if (!n.isIteration()) { |
| 29 | + ans.push(n); |
| 30 | + continue; |
| 31 | + } |
| 32 | + |
| 33 | + // We found an iter node, now find its siblings. |
| 34 | + const siblings = [n]; |
| 35 | + // Find the first node that's *not* part of the current list. |
| 36 | + for (let j = i + 1; j < nodes.length && isIterSibling(n, nodes[j]); j++) { |
| 37 | + siblings.push(nodes[j]); |
| 38 | + i = j; |
| 39 | + } |
| 40 | + const cousins = []; |
| 41 | + const numRows = siblings[0].children.length; |
| 42 | + for (let row = 0; row < numRows; row++) { |
| 43 | + cousins.push(...siblings.map(sib => sib.children[row])); |
| 44 | + } |
| 45 | + ans.push(...recoverIterOrder(cousins, depth + 1)); |
| 46 | + } |
| 47 | + return ans; |
| 48 | +} |
0 commit comments