Skip to content

Commit

Permalink
Support hex, octal, and binary numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
triallax committed Sep 20, 2022
1 parent 5002e3f commit 504f6d3
Showing 1 changed file with 29 additions and 20 deletions.
49 changes: 29 additions & 20 deletions src/Insect/Parser.purs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ import Data.Maybe (Maybe(..), fromMaybe)
import Data.NonEmpty (NonEmpty, (:|))
import Data.Semigroup.Foldable (foldl1, foldr1)
import Data.String (fromCodePointArray, codePointFromChar, singleton)
import Data.Tuple.Nested ((/\))
import Insect.Environment (Environment, StoredFunction(..))
import Insect.Language (BinOp(..), Expression(..), Command(..), Statement(..), Identifier)
import Quantities (DerivedUnit, (./))
import Quantities as Q
import Parsing (ParserT, Parser, ParseError, runParser, fail)
import Parsing.Combinators (option, optionMaybe, try, (<?>), notFollowedBy)
import Parsing.String (string, char, eof)
import Parsing.String.Basic (oneOf)
import Parsing.String.Basic (hexDigit, octDigit, oneOf)
import Parsing.Token (GenLanguageDef(..), LanguageDef, TokenParser, digit, letter, makeTokenParser)

-- | A type synonym for the main Parser type with `String` as input.
Expand Down Expand Up @@ -88,36 +89,25 @@ whiteSpace ∷ P Unit
whiteSpace = token.whiteSpace

-- | Parse a number.
number P Decimal
number = do
number' P Char String P String
number' digit' expSymbol = do
decimalPart ← fractionalPart <|> do
intPart ← digits
mFracPart ← optionMaybe fractionalPart
pure (intPart <> fromMaybe "" mFracPart)

mExpPartoptionMaybe $ try do
_ ← string "e"
expPartoption "" $ try do
_ ← string expSymbol
notFollowedBy identStart
sad ← signAndDigits
pure ("e" <> sad)
let expPart = fromMaybe "" mExpPart
pure (expSymbol <> sad)

whiteSpace

let floatStr = decimalPart <> expPart

case fromString floatStr of
Just num →
if isFinite num
then pure num
else fail "This number is too large"
Nothing → fail $ "Parsing of number failed for input '" <> floatStr <> "'"

pure $ decimalPart <> expPart
where
digits P String
digits = do
ds ← some $ oneOf ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] <?> "a digit"
pure $ fromCharArray (fromFoldable ds)
digits = (fromCharArray <<< fromFoldable) <$> some digit'

fractionalPart P String
fractionalPart = (<>) <$> string "." <*> digits
Expand All @@ -127,9 +117,28 @@ number = do
signAndDigits P String
signAndDigits = do
sign ← option '+' (oneOf ['+', '-'])
intPart ← digits
intPart ← (fromCharArray <<< fromFoldable) <$> some digit
pure $ singleton (codePointFromChar sign) <> intPart

number P Decimal
number = try do
numberPrefix /\ digit' /\ expSymbol ←
option ("" /\ digit /\ "e") $ char '0'
*> ((char 'x' <|> char 'X') $> ("0x" /\ hexDigit /\ "p")
<|> (char 'o' <|> char 'O') $> ("0o" /\ octDigit /\ "p")
<|> (char 'b' <|> char 'B') $> ("0b" /\ (oneOf ['0', '1'] <?> "binary digit") /\ "p"))

numberWithoutPrefix ← number' digit' expSymbol

let floatStr = numberPrefix <> numberWithoutPrefix

case fromString floatStr of
Just num →
if isFinite num
then pure num
else fail "This number is too large"
Nothing → fail $ "Parsing of number failed for input '" <> floatStr <> "'"

-- | A helper type for entries in the dictionary.
data DictEntry a = DictEntry a (Array String)

Expand Down

0 comments on commit 504f6d3

Please sign in to comment.