Here's a quick n dirty code to play with, based on yours: https://github.com/aballier/required-use
On Sat, 3 Jun 2017 18:58:35 +0200 Alexis Ballier <aball...@gentoo.org> wrote: > > 1. ^^ ( pst1 pst2 pst3.. ) pst1? ( pt1 ) pst2? ( pt2 ) pst3? ( pt3 > > ).. $ python3 ./nsolve.py '^^ ( pst1 pst2 pst3 ) pst1? ( pt1 ) pst2? ( pt2 ) pst3? ( pt3 )' [[!pst1, !pst2, !pst3]? => [pst1], [pst1]? => [!pst2], [pst1]? => [!pst3], [!pst1, pst2]? => [!pst3], [pst1]? => [pt1], [pst2]? => [pt2], [pst3]? => [pt3]] > > 2. ^^ ( pst1 pst2.. ) pst1? ( pt1 ) pst2? ( pt2 ).. ^^ ( pt1 pt2 ) $ python3 ./nsolve.py '^^ ( pst1 pst2 ) pst1? ( pt1 ) pst2? ( pt2 ) ^^ ( pt1 pt2 )' [[!pst1, !pst2]? => [pst1], [pst1]? => [!pst2], [pst1]? => [pt1], [pst2]? => [pt2], [!pt1, !pt2]? => [pt1], [pt1]? => [!pt2]] [[pt1]? => [!pt2]] can break [[pst2]? => [pt2]] > ^^ ( pst1 pst2.. ) pst1? ( pt1 !pt2 ... ) pst2? ( !pt1 pt2 ... ).. $ python3 ./nsolve.py '^^ ( pst1 pst2 ) pst1? ( pt1 !pt2 ) pst2? ( !pt1 pt2 )' [[!pst1, !pst2]? => [pst1], [pst1]? => [!pst2], [pst1]? => [pt1], [pst1]? => [!pt2], [pst2]? => [!pt1], [pst2]? => [pt2]] [[pst2]? => [!pt1]] can break [[pst1]? => [pt1]] [[pst2]? => [pt2]] can break [[pst1]? => [!pt2]] > pst1? ( pt1 !pt2 ... ) > pst2? ( !pt1? ( pt2 !pt3 ... ) ) > pst3? ( !pt1? ( !pt2? ( pt3 !pt4 ... ) ) ) $ python3 ./nsolve.py '^^ ( pst1 pst2 ) pst1? ( pt1 !pt2 ) pst2? ( !pst1? ( !pt1 pt2 ) )' [[!pst1, !pst2]? => [pst1], [pst1]? => [!pst2], [pst1]? => [pt1], [pst1]? => [!pt2], [pst2, !pst1]? => [!pt1], [pst2, !pst1]? => [pt2]] All good. > > 3. doc? ( || ( pt3 pt4 ) ) || ( pt1 pt2 pt3 pt4 ) $ python3 ./nsolve.py 'doc? ( || ( pt3 pt4 ) ) || ( pt1 pt2 pt3 pt4 )' [[doc, !pt3, !pt4]? => [pt3], [!pt1, !pt2, !pt3, !pt4]? => [pt1]] Note: the code only reports errors if a clause can break another clause left to it. It doesn't do topological sorting nor cycle reporting yet. Alexis.