Skip to content

Instantly share code, notes, and snippets.

@kakkun61
Created January 5, 2020 06:32
Show Gist options
  • Save kakkun61/739718aa1bf5fe5be83ee497a58f0113 to your computer and use it in GitHub Desktop.
Save kakkun61/739718aa1bf5fe5be83ee497a58f0113 to your computer and use it in GitHub Desktop.
供養
module Main
( Version (Version)
, VersionRange (..)
) where
import Prelude
import Effect (Effect)
import Effect.Console (log)
import Node.FS.Sync
import Node.Path
import Data.String.Regex
import Data.String.Read
import Data.Show
import Text.Parsing.Parser (Parser, runParser)
import Text.Parsing.Parser as P
import Text.Parsing.Parser.Combinators as P
import Text.Parsing.Parser.Token as P
import Text.Parsing.Parser.String as P
import Data.Array
import Data.Functor
import Data.Either
import Data.Maybe
import Data.Char.Unicode as Char
import Simple.JSON (class ReadForeign, readJSON)
import Node.Platform
import Node.Process
import Data.Semigroup
import Foreign
import Node.Buffer as Buffer
import Node.Encoding
import Data.Map (Map)
import Data.Map as Map
import Data.Set as Set
import Data.Set (Set)
import Effect.Exception
import Data.Traversable
import Data.Tuple
import Data.Array as Array
import Control.Plus
import Node.FS.Stats
import Control.Category
import Foreign as Foreign
import Foreign.Object (Object)
newtype Version = Version { major :: Int, minor :: Int, patch :: Int }
data VersionRange
= RangeEqual Version
| RangeLessThan Version
| RangeGreaterThan Version
| RangeAnd VersionRange VersionRange
| RangeOr VersionRange VersionRange
instance showVersion :: Show Version where
show (Version v) = show v.major <> "." <> show v.minor <> "." <> show v.patch
instance readVersion :: Read Version where
read str = e2m $ runParser str versionParser
instance readForeignVersion :: ReadForeign Version where
readImpl raw = do
str <- Foreign.readString raw
case read str of
Just ver -> pure ver
Nothing -> Foreign.fail $ ForeignError "version parsing failed"
instance showVersionRange :: Show VersionRange where
show (RangeEqual v) = "== " <> show v
show (RangeLessThan v) = "< " <> show v
show (RangeGreaterThan v) = "> " <> show v
show (RangeAnd r0 r1) = "(" <> show r0 <> " and " <> show r1 <> ")"
show (RangeOr r0 r1) = "(" <> show r0 <> " or " <> show r1 <> ")"
instance readVersionRange :: Read VersionRange where
read str =
e2m $ runParser str do
void P.whiteSpace
P.choice
[ do
v0 <- versionParser
void P.whiteSpace
P.choice
[ P.try P.eof $> RangeEqual v0
, P.try do
void $ P.char '<'
eq0 <- P.option false $ P.char '=' $> true
void P.whiteSpace
void $ P.char 'v'
void P.whiteSpace
let
left =
if eq0
then RangeOr (RangeEqual v0) (RangeGreaterThan v0)
else RangeGreaterThan v0
P.choice
[ P.try P.eof $> left
, do
void $ P.whiteSpace
right <- rightParser
pure $ RangeAnd left right
]
]
, do
void $ P.char 'v'
void P.whiteSpace
rightParser
]
where
rightParser = do
void $ P.char '<'
eq <- P.option false $ P.char '=' $> true
void $ P.whiteSpace
v <- versionParser
void $ P.whiteSpace
pure
if eq
then RangeOr (RangeEqual v) (RangeLessThan v)
else RangeLessThan v
instance readForeignVersionRange :: ReadForeign VersionRange where
readImpl raw = do
str <- Foreign.readString raw
case read str of
Just vr -> pure vr
Nothing -> Foreign.fail $ ForeignError "version range parsing failed"
e2m :: forall e a. Either e a -> Maybe a
e2m (Left e) = Nothing
e2m (Right a) = Just a
m2p :: forall a. Maybe a -> Parser String a
m2p Nothing = P.fail "m2p"
m2p (Just a) = pure a
versionParser :: Parser String Version
versionParser = do
maybeMajor <- da2i <$> some P.digit
void $ P.char '.'
maybeMinor <- da2i <$> some P.digit
void $ P.char '.'
maybePatch <- da2i <$> some P.digit
m2p do
major <- maybeMajor
minor <- maybeMinor
patch <- maybePatch
pure $ Version { major, minor, patch }
where
da2i :: Array Char -> Maybe Int
da2i a =
go 0 a
where
go :: Int -> Array Char -> Maybe Int
go acc a =
case uncons a of
Just u -> do
i <- Char.digitToInt u.head
go (10 * acc + i) u.tail
Nothing -> pure acc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment