@@ -20,7 +20,10 @@ module Data.Syntax.Char (
2020 spaces,
2121 spaces_,
2222 spaces1,
23− endOfLine
23+ endOfLine,
24+ digitDec,
25+ digitOct,
26+ digitHex
2427 ) where
2528
2629import Control.Lens.SemiIso
@@ -68,3 +71,27 @@ spaces1 = constant (opoint ' ') /$/ takeWhile1 isSpace
6871-- | Accepts a single newline. Generates a newline.
6972endOfLine :: SyntaxChar syn seq => syn ()
7073endOfLine = char '\n'
74+
75+-- | A decimal digit.
76+digitDec :: SyntaxChar syn seq => syn Int
77+digitDec = semiIso toChar toInt /$/ anyChar
78+ where toInt c | isDigit c = Right (digitToInt c)
79+ | otherwise = Left ("Expected a decimal digit, got " ++ [c])
80+ toChar i | i >= 0 && i <= 9 = Right (intToDigit i)
81+ | otherwise = Left ("Expected a decimal digit, got number " ++ show i)
82+
83+-- | An octal digit.
84+digitOct :: SyntaxChar syn seq => syn Int
85+digitOct = semiIso toChar toInt /$/ anyChar
86+ where toInt c | isOctDigit c = Right (digitToInt c)
87+ | otherwise = Left ("Expected an octal digit, got " ++ [c])
88+ toChar i | i >= 0 && i <= 7 = Right (intToDigit i)
89+ | otherwise = Left ("Expected an octal digit, got number " ++ show i)
90+
91+-- | A hex digit.
92+digitHex :: SyntaxChar syn seq => syn Int
93+digitHex = semiIso toChar toInt /$/ anyChar
94+ where toInt c | isHexDigit c = Right (digitToInt c)
95+ | otherwise = Left ("Expected a hex digit, got " ++ [c])
96+ toChar i | i >= 0 && i <= 15 = Right (intToDigit i)
97+ | otherwise = Left ("Expected a hex digit, got number " ++ show i)