packages feed

Earley-0.13.0.1: examples/RomanNumerals.hs

{-# LANGUAGE RecursiveDo #-}
module Main where

import Control.Applicative ((<|>), (<**>))
import System.Environment (getArgs)
import Text.Earley

numeral :: String -> Int -> Prod r String Char Int
numeral str n = n <$ list str

romanNumeralsGrammar :: Grammar r (Prod r String Char Int)
romanNumeralsGrammar = mdo

  thousands <- rule
    $ pure 0
    <|> numeral "M" 1000 <**> fmap (+) thousands

  le300 <- rule
    $ pure 0
    <|> numeral "C" 100
    <|> numeral "CC" 200
    <|> numeral "CCC" 300

  hundreds <- rule
    $ le300
    <|> numeral "CD" 400
    <|> numeral "D" 500 <**> fmap (+) le300
    <|> numeral "CM" 900

  le30 <- rule
    $ pure 0
    <|> numeral "X" 10
    <|> numeral "XX" 20
    <|> numeral "XXX" 30

  tens <- rule 
    $ le30
    <|> numeral "XL" 40
    <|> numeral "L" 50 <**> fmap (+) le30
    <|> numeral "XC" 90

  le3 <- rule
    $ pure 0
    <|> numeral "I" 1
    <|> numeral "II" 2
    <|> numeral "III" 3

  units <- rule
    $ le3
    <|> numeral "IV" 4
    <|> numeral "V" 5 <**> fmap (+) le3
    <|> numeral "IX" 9

  return
    $ thousands
    <**> fmap (+) hundreds
    <**> fmap (+) tens
    <**> fmap (+) units


main :: IO ()
main = do
  x:_ <- getArgs
  print $ fullParses (parser romanNumeralsGrammar) x