///|
/// Explains why a lexical Roman candidate was not accepted.
pub(all) enum ScanRejectionReason {
  SingleSymbolExcluded
  CandidateTooLong(Int)
  CandidateParseFailed(RomanReportError)
} derive(Eq, Debug)

///|
/// Retains one accepted candidate and its configured parse evidence.
pub(all) struct RomanScanMatch {
  span : SourceSpan
  source_text : String
  report : ParseReport
} derive(Eq, Debug)

///|
/// Retains one rejected candidate when requested by ScanConfig.
pub(all) struct RomanScanRejection {
  span : SourceSpan
  source_text : String
  reason : ScanRejectionReason
} derive(Eq, Debug)

///|
/// Returns document matches and deterministic scanning counters.
pub(all) struct RomanScanReport {
  matches : Array[RomanScanMatch]
  rejections : Array[RomanScanRejection]
  candidates_examined : Int
} derive(Eq, Debug)