verseRangeRefFromStr function
Parse a string into a VerseRangeRef.
Implementation
VerseRangeRef verseRangeRefFromStr(String ref, {BibleLanguageEnum? language}) {
_ensureReferenceIsNotEmpty(ref);
final normalizedLanguage = _bookLookup.normalizeLanguage(language);
final match = _verseRangeRefPattern.firstMatch(ref);
if (match == null) {
throw ParseVerseRefError(
code: 'pattern_mismatch',
details: 'reference "$ref" does not match expected format');
}
final startChapter = _parseReferenceNumber(
match.group(2)!,
component: 'start chapter',
maximum: maxReferenceChapterNumber,
);
final startVerse = _parseVerseToken(
match.group(3)!,
component: 'start verse',
);
final endVerse = _parseVerseToken(
match.group(6)!,
component: 'end verse',
);
final endChapterMatch = match.group(5);
final endChapter = endChapterMatch != null
? _parseReferenceNumber(
endChapterMatch,
component: 'end chapter',
maximum: maxReferenceChapterNumber,
)
: startChapter;
final startBook =
_bookLookup.parseBookName(match.group(1)!, normalizedLanguage);
final endBookMatch = match.group(4);
final endBook = endBookMatch != null
? _bookLookup.parseBookName(endBookMatch, normalizedLanguage)
: startBook;
final start = VerseRef(
book: startBook,
chapter: startChapter,
verse: startVerse.verse,
subdivision: startVerse.subdivision,
);
final end = VerseRef(
book: endBook,
chapter: endChapter,
verse: endVerse.verse,
subdivision: endVerse.subdivision,
);
if (endBook == startBook && start.compareTo(end) >= 0) {
throw ParseVerseRefError(
code: 'same_book_range_not_ascending',
details:
'end reference must come after start reference for same-book ranges');
}
if (start.compareTo(end) >= 0) {
throw ParseVerseRefError.typed(
code: ReferenceParseErrorCode.crossBookRangeNotAscending,
details: 'end reference must come after start reference',
);
}
return VerseRangeRef.checked(start: start, end: end);
}