Skip to content

Instantly share code, notes, and snippets.

@asm0dey
Created May 5, 2026 21:42
Show Gist options
  • Select an option

  • Save asm0dey/7c6077108147f233d816c98a4249053c to your computer and use it in GitHub Desktop.

Select an option

Save asm0dey/7c6077108147f233d816c98a4249053c to your computer and use it in GitHub Desktop.
/**
* Build the Roman-numeral regex fragment via Sift. Mirrors the structure of
* the canonical Python guessit/rebulk Roman regex: a lookahead asserting at
* least one Roman character, followed by greedy thousands / hundreds / tens
* / ones blocks with subtractive pairs listed first so they bind before the
* base letters.
*/
private static SiftPattern<Fragment> buildRomanFragment() {
var romanChar = SiftPatterns.anyOf(
SiftPatterns.literal("M"), SiftPatterns.literal("C"),
SiftPatterns.literal("D"), SiftPatterns.literal("L"),
SiftPatterns.literal("X"), SiftPatterns.literal("V"),
SiftPatterns.literal("I"));
var romanRun = Sift.fromAnywhere().oneOrMore().of(romanChar);
var thousands = Sift.between(0, 4).character('M');
var hundreds = SiftPatterns.anyOf(
SiftPatterns.literal("CM"),
SiftPatterns.literal("CD"),
Sift.fromAnywhere().optional().character('D')
.then().between(0, 3).character('C'));
var tens = SiftPatterns.anyOf(
SiftPatterns.literal("XC"),
SiftPatterns.literal("XL"),
Sift.fromAnywhere().optional().character('L')
.then().between(0, 3).character('X'));
var ones = SiftPatterns.anyOf(
SiftPatterns.literal("IX"),
SiftPatterns.literal("IV"),
Sift.fromAnywhere().optional().character('V')
.then().between(0, 3).character('I'));
return Sift.fromAnywhere()
.mustBeFollowedBy(romanRun)
.followedBy(List.of(thousands, hundreds, tens, ones));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment