Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ jobs:

- name: Set up a PureScript toolchain
uses: purescript-contrib/setup-purescript@main
with:
purs-tidy: "latest"

- name: Cache PureScript dependencies
uses: actions/cache@v2
Expand All @@ -32,3 +34,6 @@ jobs:

- name: Run tests
run: spago test --no-install

- name: Check formatting
run: purs-tidy check src test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
!.gitignore
!.github
!.editorconfig
!.tidyrc.json

output
generated-docs
Expand Down
10 changes: 10 additions & 0 deletions .tidyrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"importSort": "source",
"importWrap": "source",
"indent": 2,
"operatorsFile": null,
"ribbon": 1,
"typeArrowPlacement": "first",
"unicode": "never",
"width": null
}
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ New features:
Bugfixes:

Other improvements:
- Added `purs-tidy` formatter (#76 by @thomashoneyman)

- Run slowest tests last and print status updates (#72)

Expand Down
11 changes: 6 additions & 5 deletions src/Text/Parsing/StringParser.purs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ instance applicativeParser :: Applicative Parser where
instance altParser :: Alt Parser where
alt (Parser p1) (Parser p2) = Parser \s ->
case p1 s of
Left { error, pos } | s.pos == pos -> p2 s
| otherwise -> Left { error, pos }
Left { error, pos }
| s.pos == pos -> p2 s
| otherwise -> Left { error, pos }
right -> right

instance plusParser :: Plus Parser where
Expand All @@ -87,8 +88,8 @@ instance monadPlusParser :: MonadPlus Parser
instance monadRecParser :: MonadRec Parser where
tailRecM f a = Parser \str -> tailRecM (\st -> map split (unParser (f st.state) st.str)) { state: a, str }
where
split { result: Loop state, suffix: str } = Loop { state, str }
split { result: Done b, suffix } = Done { result: b, suffix }
split { result: Loop state, suffix: str } = Loop { state, str }
split { result: Done b, suffix } = Done { result: b, suffix }

instance lazyParser :: Lazy (Parser a) where
defer f = Parser $ \str -> unParser (f unit) str
Expand All @@ -101,7 +102,7 @@ fail error = Parser \{ pos } -> Left { pos, error }
-- |
-- | `try p` backtracks even if input was consumed.
try :: forall a. Parser a -> Parser a
try (Parser p) = Parser \(s@{ pos }) -> lmap (_ { pos = pos}) (p s)
try (Parser p) = Parser \(s@{ pos }) -> lmap (_ { pos = pos }) (p s)

instance semigroupParser :: Semigroup a => Semigroup (Parser a) where
append = lift2 append
Expand Down
61 changes: 29 additions & 32 deletions src/Text/Parsing/StringParser/CodePoints.purs
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,14 @@ anyChar = Parser \{ str, pos } ->
Nothing -> Left { pos, error: "CodePoint " <> show cp <> " is not a character" }
Nothing -> Left { pos, error: "Unexpected EOF" }
where
toChar = fromCharCode <<< fromEnum
toChar = fromCharCode <<< fromEnum

-- | Match any digit.
anyDigit :: Parser Char
anyDigit = try do
c <- anyChar
if c >= '0' && c <= '9'
then pure c
else fail $ "Character " <> show c <> " is not a digit"
if c >= '0' && c <= '9' then pure c
else fail $ "Character " <> show c <> " is not a digit"

-- | Match the specified string.
string :: String -> Parser String
Expand All @@ -76,9 +75,8 @@ string nt = Parser \s ->
satisfy :: (Char -> Boolean) -> Parser Char
satisfy f = try do
c <- anyChar
if f c
then pure c
else fail $ "Character " <> show c <> " did not satisfy predicate"
if f c then pure c
else fail $ "Character " <> show c <> " did not satisfy predicate"

-- | Match the specified character.
char :: Char -> Parser Char
Expand All @@ -87,7 +85,7 @@ char c = satisfy (_ == c) <?> "Could not match character " <> show c
-- | Match many whitespace characters.
whiteSpace :: Parser String
whiteSpace = do
cs <- many (satisfy \ c -> c == '\n' || c == '\r' || c == ' ' || c == '\t')
cs <- many (satisfy \c -> c == '\n' || c == '\r' || c == ' ' || c == '\t')
pure (foldMap singleton cs)

-- | Skip many whitespace characters.
Expand All @@ -106,17 +104,15 @@ noneOf = satisfy <<< flip notElem
lowerCaseChar :: Parser Char
lowerCaseChar = try do
c <- anyChar
if toCharCode c `elem` (97 .. 122)
then pure c
else fail $ "Expected a lower case character but found " <> show c
if toCharCode c `elem` (97 .. 122) then pure c
else fail $ "Expected a lower case character but found " <> show c

-- | Match any upper case character.
upperCaseChar :: Parser Char
upperCaseChar = try do
c <- anyChar
if toCharCode c `elem` (65 .. 90)
then pure c
else fail $ "Expected an upper case character but found " <> show c
if toCharCode c `elem` (65 .. 90) then pure c
else fail $ "Expected an upper case character but found " <> show c

-- | Match any letter.
anyLetter :: Parser Char
Expand All @@ -135,21 +131,22 @@ regex pat =
Right r ->
matchRegex r
where
-- ensure the pattern only matches the current position in the parse
pattern =
case stripPrefix (Pattern "^") pat of
Nothing ->
"^" <> pat
_ ->
pat
matchRegex :: Regex.Regex -> Parser String
matchRegex r =
Parser \{ str, pos } ->
let
remainder = drop pos str
in
case NEA.head <$> Regex.match r remainder of
Just (Just matched) ->
Right { result: matched, suffix: { str, pos: pos + length matched } }
_ ->
Left { pos, error: "no match" }
-- ensure the pattern only matches the current position in the parse
pattern =
case stripPrefix (Pattern "^") pat of
Nothing ->
"^" <> pat
_ ->
pat

matchRegex :: Regex.Regex -> Parser String
matchRegex r =
Parser \{ str, pos } ->
let
remainder = drop pos str
in
case NEA.head <$> Regex.match r remainder of
Just (Just matched) ->
Right { result: matched, suffix: { str, pos: pos + length matched } }
_ ->
Left { pos, error: "no match" }
59 changes: 28 additions & 31 deletions src/Text/Parsing/StringParser/CodeUnits.purs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ anyChar = Parser \{ str, pos } ->
anyDigit :: Parser Char
anyDigit = try do
c <- anyChar
if c >= '0' && c <= '9'
then pure c
else fail $ "Character " <> show c <> " is not a digit"
if c >= '0' && c <= '9' then pure c
else fail $ "Character " <> show c <> " is not a digit"

-- | Match the specified string.
string :: String -> Parser String
Expand All @@ -71,9 +70,8 @@ string nt = Parser \s ->
satisfy :: (Char -> Boolean) -> Parser Char
satisfy f = try do
c <- anyChar
if f c
then pure c
else fail $ "Character " <> show c <> " did not satisfy predicate"
if f c then pure c
else fail $ "Character " <> show c <> " did not satisfy predicate"

-- | Match the specified character.
char :: Char -> Parser Char
Expand All @@ -82,7 +80,7 @@ char c = satisfy (_ == c) <?> "Could not match character " <> show c
-- | Match many whitespace characters.
whiteSpace :: Parser String
whiteSpace = do
cs <- many (satisfy \ c -> c == '\n' || c == '\r' || c == ' ' || c == '\t')
cs <- many (satisfy \c -> c == '\n' || c == '\r' || c == ' ' || c == '\t')
pure (foldMap singleton cs)

-- | Skip many whitespace characters.
Expand All @@ -101,17 +99,15 @@ noneOf = satisfy <<< flip notElem
lowerCaseChar :: Parser Char
lowerCaseChar = try do
c <- anyChar
if toCharCode c `elem` (97 .. 122)
then pure c
else fail $ "Expected a lower case character but found " <> show c
if toCharCode c `elem` (97 .. 122) then pure c
else fail $ "Expected a lower case character but found " <> show c

-- | Match any upper case character.
upperCaseChar :: Parser Char
upperCaseChar = try do
c <- anyChar
if toCharCode c `elem` (65 .. 90)
then pure c
else fail $ "Expected an upper case character but found " <> show c
if toCharCode c `elem` (65 .. 90) then pure c
else fail $ "Expected an upper case character but found " <> show c

-- | Match any letter.
anyLetter :: Parser Char
Expand All @@ -130,21 +126,22 @@ regex pat =
Right r ->
matchRegex r
where
-- ensure the pattern only matches the current position in the parse
pattern =
case SCU.stripPrefix (Pattern "^") pat of
Nothing ->
"^" <> pat
_ ->
pat
matchRegex :: Regex.Regex -> Parser String
matchRegex r =
Parser \{ str, pos } ->
let
remainder = SCU.drop pos str
in
case NEA.head <$> Regex.match r remainder of
Just (Just matched) ->
Right { result: matched, suffix: { str, pos: pos + SCU.length matched } }
_ ->
Left { pos, error: "no match" }
-- ensure the pattern only matches the current position in the parse
pattern =
case SCU.stripPrefix (Pattern "^") pat of
Nothing ->
"^" <> pat
_ ->
pat

matchRegex :: Regex.Regex -> Parser String
matchRegex r =
Parser \{ str, pos } ->
let
remainder = SCU.drop pos str
in
case NEA.head <$> Regex.match r remainder of
Just (Just matched) ->
Right { result: matched, suffix: { str, pos: pos + SCU.length matched } }
_ ->
Left { pos, error: "no match" }
41 changes: 25 additions & 16 deletions src/Text/Parsing/StringParser/Combinators.purs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ module Text.Parsing.StringParser.Combinators
( lookAhead
, many
, many1
, withError, (<?>)
, withError
, (<?>)
, between
, option
, optional
Expand Down Expand Up @@ -97,9 +98,11 @@ sepEndBy p sep = map NEL.toList (sepEndBy1 p sep) <|> pure Nil
sepEndBy1 :: forall a sep. Parser a -> Parser sep -> Parser (NonEmptyList a)
sepEndBy1 p sep = do
a <- p
(do _ <- sep
( do
_ <- sep
as <- sepEndBy p sep
pure (cons' a as)) <|> pure (NEL.singleton a)
pure (cons' a as)
) <|> pure (NEL.singleton a)

-- | Parse one or more separated values, ending with a separator.
endBy1 :: forall a sep. Parser a -> Parser sep -> Parser (NonEmptyList a)
Expand All @@ -125,9 +128,12 @@ chainl1 p f = do

-- | Parse one or more values separated by a left-associative operator.
chainl1' :: forall a. Parser a -> Parser (a -> a -> a) -> a -> Parser a
chainl1' p f a = (do f' <- f
a' <- p
chainl1' p f (f' a a')) <|> pure a
chainl1' p f a =
( do
f' <- f
a' <- p
chainl1' p f (f' a a')
) <|> pure a

-- | Parse one or more values separated by a right-associative operator.
chainr1 :: forall a. Parser a -> Parser (a -> a -> a) -> Parser a
Expand All @@ -137,9 +143,12 @@ chainr1 p f = do

-- | Parse one or more values separated by a right-associative operator.
chainr1' :: forall a. Parser a -> Parser (a -> a -> a) -> a -> Parser a
chainr1' p f a = (do f' <- f
a' <- chainr1 p f
pure $ f' a a') <|> pure a
chainr1' p f a =
( do
f' <- f
a' <- chainr1 p f
pure $ f' a a'
) <|> pure a

-- | Parse using any of a collection of parsers.
choice :: forall f a. Foldable f => f (Parser a) -> Parser a
Expand All @@ -155,13 +164,13 @@ many1Till p end = do
x <- p
tailRecM inner (pure x)
where
ending acc = do
_ <- end
pure $ Done (NEL.reverse acc)
continue acc = do
c <- p
pure $ Loop (NEL.cons c acc)
inner acc = ending acc <|> continue acc
ending acc = do
_ <- end
pure $ Done (NEL.reverse acc)
continue acc = do
c <- p
pure $ Loop (NEL.cons c acc)
inner acc = ending acc <|> continue acc

cons' :: forall a. a -> List a -> NonEmptyList a
cons' h t = NonEmptyList (h :| t)
Loading