    _ -> Nothing
  }

rulePowersOfTen :: Rule
rulePowersOfTen = Rule
  { name = "powers of tens"
  , pattern =
    [ regex "(ათასი?|მილიონი?|მილიარდი?)"
    ]
  , prod = \case
      (Token RegexMatch (GroupMatch (match:_)):_) -> case Text.toLower match of
        "ათასი" -> double 1e3 >>= withGrain 3 >>= withMultipliable
        "ათას" -> double 1e3 >>= withGrain 3 >>= withMultipliable
        "მილიონი"  -> double 1e6 >>= withGrain 6 >>= withMultipliable
        "მილიონ"  -> double 1e6 >>= withGrain 6 >>= withMultipliable
        "მილიარდი"  -> double 1e9 >>= withGrain 9 >>= withMultipliable
        "მილიარდ"  -> double 1e9 >>= withGrain 9 >>= withMultipliable
        _          -> Nothing
      _ -> Nothing
  }

ruleCompositeTens :: Rule
ruleCompositeTens = Rule
  { name = "integer 21..99"
  , pattern =
    [ oneOf [20,40..90]
    , numberBetween 1 20
    ]
  , prod = \case
      (Token Numeral NumeralData{TNumeral.value = tens}:
       Token Numeral NumeralData{TNumeral.value = units}:
       _) -> double $ tens + units
      _ -> Nothing
  }

ruleCompositeHundreds :: Rule
ruleCompositeHundreds = Rule
  { name = "integer 100..999"
  , pattern =
    [ oneOf [100,200..900]
    , oneOf [20,40..90]
    , numberBetween 1 20
    ]
  , prod = \case
      (Token Numeral NumeralData{T
hundredsMap :: HashMap Text Integer
hundredsMap = HashMap.fromList
  [ ( "ასი"      , 100 )
  , ( "ორასი"    , 200 )
  , ( "სამასი"   , 300 )
  , ( "ოთხასი"   , 400 )
  , ( "ხუთასი"   , 500 )
  , ( "ექვსასი"  , 600 )
  , ( "შვიდასი"  , 700 )
  , ( "რვაასი"   , 800 )
  , ( "ცხრაასი"  , 900 )
  , ( "ას"       , 100 )
  , ( "ორას"     , 200 )
  , ( "სამას"    , 300 )
  , ( "ოთხას"    , 400 )
  , ( "ხუთას"    , 500 )
  , ( "ექვსას"   , 600 )
  , ( "შვიდას"   , 700 )
  , ( "რვაას"    , 800 )
  , ( "ცხრაას"   , 900 )
  , ( "ორ ას"    , 200 )
  , ( "სამ ას"   , 300 )
  , ( "ოთხ ას"   , 400 )
  , ( "ხუთ ას"   , 500 )
  , ( "ექვს ას"  , 600 )
  , ( "შვიდ ას"  , 700 )
  , ( "რვა ას"   , 800 )
  , ( "ცხრა ას"  , 900 )
  , ( "ორ ასი"   , 200 )
  , ( "სამ ასი"  , 300 )
  , ( "ოთხ ასი"  , 400 )
  , ( "ხუთ ასი"  , 500 )
  , ( "ექვს ასი" , 600 )
  , ( "შვიდ ასი" , 700 )
  , ( "რვა ასი"  , 800 )
  , ( "ცხრა ასი" , 900 )
  ]
hundredsMap = HashMap.fromList
  [ ( "ასი"      , 100 )
  , ( "ორასი"    , 200 )
  , ( "სამასი"   , 300 )
  , ( "ოთხასი"   , 400 )
  , ( "ხუთასი"   , 500 )
  , ( "ექვსასი"  , 600 )
  , ( "შვიდასი"  , 700 )
  , ( "რვაასი"   , 800 )
  , ( "ცხრაასი"  , 900 )
  , ( "ას"       , 100 )
  , ( "ორას"     , 200 )
  , ( "სამას"    , 300 )
  , ( "ოთხას"    , 400 )
  , ( "ხუთას"    , 500 )
  , ( "ექვსას"   , 600 )
  , ( "შვიდას"   , 700 )
  , ( "რვაას"    , 800 )
  , ( "ცხრაას"   , 900 )
  , ( "ორ ას"    , 200 )
  , ( "სამ ას"   , 300 )
  , ( "ოთხ ას"   , 400 )
  , ( "ხუთ ას"   , 500 )
  , ( "ექვს ას"  , 600 )
  , ( "შვიდ ას"  , 700 )
  , ( "რვა ას"   , 800 )
  , ( "ცხრა ას"  , 900 )
  , ( "ორ ასი"   , 200 )
  , ( "სამ ასი"  , 300 )
  , ( "ოთხ ასი"  , 400 )
  , ( "ხუთ ასი"  , 500 )
  , ( "ექვს ასი" , 600 )
  , ( "შვიდ ასი" , 700 )
  , ( "რვა ასი"  , 800 )
  , ( "ცხრა ასი" , 900 )
  ]