R1DistinctionChecker

R1DistinctionChecker compile: 'extractDrawsFromLines: lines "Return an OrderedCollection of draw specs. Each spec is a 2-element Array: {distinctionString . markedSideOrNil}. Accepted forms: [DRAW: A / B] [DRAW: A / B | A] (explicit marked side)" | draws marker | draws := OrderedCollection new. marker := ''[DRAW:''. lines do: [:ln | | start | start := ln findString: marker startingAt: 1. [start > 0] whileTrue: [ | end raw payload parts dist marked | end := ln findString: '']'' startingAt: start. end = 0 ifTrue: [ ^ draws ]. "malformed; stop early" raw := ln copyFrom: start + marker size to: end - 1. payload := raw withBlanksTrimmed. parts := payload findTokens: ''|''. dist := (parts first ifNil: ['''']) withBlanksTrimmed. marked := (parts size >= 2 ifTrue: [ (parts second ifNil: ['''']) withBlanksTrimmed ] ifFalse: [ nil ]). draws add: { dist . (marked isEmpty ifTrue: [ nil ] ifFalse: [ marked ]) }. start := ln findString: marker startingAt: end + 1 ] ]. ^ draws.'. R1DistinctionChecker compile: 'checkR1: markdownString "Rule R1: No section may presuppose a distinction that has not been drawn earlier." | sections violations drawnSoFar | sections := self sectionize: markdownString. violations := OrderedCollection new. drawnSoFar := Set new. sections withIndexDo: [:lines :idx | | draws presupposed undrawn | draws := self extractDrawsFromLines: lines. "R1 only cares whether the distinction was drawn at all (not which side was marked)." draws do: [:spec | drawnSoFar add: spec first ]. presupposed := self scanPresuppositionsInLines: lines. undrawn := presupposed copyWithoutAll: drawnSoFar. undrawn isEmpty ifFalse: [ violations add: { idx . undrawn asArray sorted } ] ]. ^ violations asArray.'.

–– chatgpt