static ParsedWithTokens pwt_combine(A value, ParsedWithTokens p1, ParsedWithTokens p2) { assertSame(p1.tok, p2.tok); ret new ParsedWithTokens(value, p1.tok, min(p1.iStart, p2.iStart), max(p1.iRemaining, p2.iRemaining)); } // shorter version taking value of first pwt static ParsedWithTokens pwt_combine(ParsedWithTokens p1, ParsedWithTokens p2) { ret pwt_combine(p1!, p1, p2); } // entirely different meaning static L> pwt_combine(Iterable> l1, Iterable> l2, IF2 f) { new L> out; for (ParsedWithTokens a : l1) for (ParsedWithTokens b : pwt_toTheRightOf(l2, l1)) out.add(pwt_combine(f.get(a!, b!), a, b)); ret out; }