@@ -145,8 +145,8 @@ module Streamly.Internal.Data.Parser.ParserD
145 , takeFramedByEsc_
145 , takeFramedByEsc_
146 , takeFramedByGeneric
146 , takeFramedByGeneric
147 , wordFramedBy
147 , wordFramedBy
148− , wordQuotedBy
148+ , wordWithQuotes
149− , blockQuotedBy
149+ , blockWithQuotes
151 -- Matching strings
151 -- Matching strings
152 -- , prefixOf -- match any prefix of a given string
152 -- , prefixOf -- match any prefix of a given string
@@ -1504,7 +1504,7 @@ wordFramedBy :: Monad m =>
1504 (a -> Bool) -- ^ Matches escape elem?
1504 (a -> Bool) -- ^ Matches escape elem?
1505 -> (a -> Bool) -- ^ Matches left quote?
1505 -> (a -> Bool) -- ^ Matches left quote?
1506 -> (a -> Bool) -- ^ matches right quote?
1506 -> (a -> Bool) -- ^ matches right quote?
1507− -> (a -> Bool) -- ^ matches word seperator?
1507+ -> (a -> Bool) -- ^ matches word separator?
1508 -> Fold m a b
1508 -> Fold m a b
1509 -> Parser a m b
1509 -> Parser a m b
1510wordFramedBy isEsc isBegin isEnd isSep
1510wordFramedBy isEsc isBegin isEnd isSep
@@ -1592,38 +1592,48 @@ data WordQuotedState s b a =
1592-- XXX If quote start and end chars are different then quotes can be nested
1592-- XXX If quote start and end chars are different then quotes can be nested
1593-- without escaping. However, is there a case for the use of nested quotes?
1593-- without escaping. However, is there a case for the use of nested quotes?
1595−-- XXX Simplify like blockQuotedBy
1595+-- XXX Simplify like blockWithQuotes
1597−-- | Like 'wordFramedBy' but the closing quote is determined by the opening
1597+-- | Like 'wordBy' but word separators within quotes are ignored. Quote
1598−-- quote. The first quote begin starts a quote that is closed by its
1598+-- character can be used within quotes if escaped using the supplied escape
1599−-- corresponding closing quote.
1599+-- char. A different quoting character can be used inside quotes without
1600+-- escaping. Starting quote determines the ending quote.
1601−-- 'wordFramedBy' and 'wordQuotedBy' both allow multiple quote characters based
1602+-- Example:
1602−-- on the predicates but 'wordQuotedBy' always fixes the quote at the first
1603−-- occurrence and then it is closed only by the corresponding closing quote.
1604−-- Therefore, other quoting characters can be embedded inside it as normal
1605−-- characters. On the other hand, 'wordFramedBy' would close the quote as soon
1606−-- as it encounters any of the closing quotes.
1607+-- >>> '"' -> Just x
1608+-- >>> '\'' -> Just x
1608−-- >>> q = (`elem` ['"', '\''])
1612+-- >>> rq = (`elem` ['"', '\''])
1609−-- >>> p kQ = Parser.wordQuotedBy kQ (== '\\') q q id isSpace Fold.toList
1613+-- >>> p keep = Parser.wordWithQuotes keep (== '\\') lq rq isSpace Fold.toList
1611-- >>> Stream.parse (p False) $ Stream.fromList "a\"b'c\";'d\"e'f ghi"
1615-- >>> Stream.parse (p False) $ Stream.fromList "a\"b'c\";'d\"e'f ghi"
1612-- Right "ab'c;d\"ef"
1616-- Right "ab'c;d\"ef"
1618+-- Outer quotes and backslashes from the input string are removed by Haskell,
1619+-- therefore, the actual input string looks like:
1620+-- a"b'c";'d"e'f ghi
1621+-- From this the outer quotes are stripped by the parser, double quotes inside
1622+-- single quotes or vice-versa are kept.
1614-- >>> Stream.parse (p True) $ Stream.fromList "a\"b'c\";'d\"e'f ghi"
1624-- >>> Stream.parse (p True) $ Stream.fromList "a\"b'c\";'d\"e'f ghi"
1615-- Right "a\"b'c\";'d\"e'f"
1625-- Right "a\"b'c\";'d\"e'f"
1617−{-# INLINE wordQuotedBy #-}
1627+{-# INLINE wordWithQuotes #-}
1618−wordQuotedBy :: (Monad m, Eq a) =>
1628+wordWithQuotes :: (Monad m, Eq a) =>
1619 Bool -- ^ keep the quotes in the output
1629 Bool -- ^ keep the quotes in the output
1620 -> (a -> Bool) -- ^ Matches an escape elem?
1630 -> (a -> Bool) -- ^ Matches an escape elem?
1621 -> (a -> Maybe a) -- ^ If left quote, return right quote, else nothing.
1631 -> (a -> Maybe a) -- ^ If left quote, return right quote, else nothing.
1622 -> (a -> Bool) -- ^ Matches a right quote?
1632 -> (a -> Bool) -- ^ Matches a right quote?
1623− -> (a -> Bool) -- ^ Matches a word seperator?
1633+ -> (a -> Bool) -- ^ Matches a word separator?
1624 -> Fold m a b
1634 -> Fold m a b
1625 -> Parser a m b
1635 -> Parser a m b
1626−wordQuotedBy keepQuotes isEsc toRight isEnd isSep
1636+wordWithQuotes keepQuotes isEsc toRight isEnd isSep
1627 (Fold fstep finitial fextract) =
1637 (Fold fstep finitial fextract) =
1628 Parser step initial extract
1638 Parser step initial extract
@@ -1635,7 +1645,7 @@ wordQuotedBy keepQuotes isEsc toRight isEnd isSep
1635 case res of
1645 case res of
1636 FL.Partial s -> IPartial (WordQuotedSkipPre s)
1646 FL.Partial s -> IPartial (WordQuotedSkipPre s)
1637 FL.Done _ ->
1647 FL.Done _ ->
1638− error "wordQuotedBy: fold done without input"
1648+ error "wordWithQuotes: fold done without input"
1640 {-# INLINE process #-}
1650 {-# INLINE process #-}
1641 process s a n ql qr = do
1651 process s a n ql qr = do
@@ -1664,7 +1674,7 @@ wordQuotedBy keepQuotes isEsc toRight isEnd isSep
1664 else return $ Continue 0 $ WordQuotedWord s 1 a qr
1674 else return $ Continue 0 $ WordQuotedWord s 1 a qr
1666 | isEnd a ->
1676 | isEnd a ->
1667− return $ Error "wordQuotedBy: missing frame start"
1677+ return $ Error "wordWithQuotes: missing frame start"
1668 | otherwise -> processUnquoted s a
1678 | otherwise -> processUnquoted s a
1669 step (WordUnquotedWord s) a
1679 step (WordUnquotedWord s) a
1670 | isEsc a = return $ Continue 0 $ WordUnquotedEsc s
1680 | isEsc a = return $ Continue 0 $ WordUnquotedEsc s
@@ -1679,7 +1689,7 @@ wordQuotedBy keepQuotes isEsc toRight isEnd isSep
1679 else return $ Continue 0 $ WordQuotedWord s 1 a qr
1689 else return $ Continue 0 $ WordQuotedWord s 1 a qr
1680 Nothing ->
1690 Nothing ->
1681 if isEnd a
1691 if isEnd a
1682− then return $ Error "wordQuotedBy: missing frame start"
1692+ then return $ Error "wordWithQuotes: missing frame start"
1683 else processUnquoted s a
1693 else processUnquoted s a
1684 step (WordQuotedWord s n ql qr) a
1694 step (WordQuotedWord s n ql qr) a
1685 | isEsc a = return $ Continue 0 $ WordQuotedEsc s n ql qr
1695 | isEsc a = return $ Continue 0 $ WordQuotedEsc s n ql qr
@@ -1713,11 +1723,11 @@ wordQuotedBy keepQuotes isEsc toRight isEnd isSep
1713 extract (WordQuotedWord s n _ _) =
1723 extract (WordQuotedWord s n _ _) =
1714 if n == 0
1724 if n == 0
1715 then fmap (Done 0) $ fextract s
1725 then fmap (Done 0) $ fextract s
1716− else err "wordQuotedBy: missing frame end"
1726+ else err "wordWithQuotes: missing frame end"
1717 extract WordQuotedEsc {} =
1727 extract WordQuotedEsc {} =
1718− err "wordQuotedBy: trailing escape"
1728+ err "wordWithQuotes: trailing escape"
1719 extract (WordUnquotedEsc _) =
1729 extract (WordUnquotedEsc _) =
1720− err "wordQuotedBy: trailing escape"
1730+ err "wordWithQuotes: trailing escape"
1721 extract (WordQuotedSkipPost b) = return (Done 0 b)
1731 extract (WordQuotedSkipPost b) = return (Done 0 b)
1723data BlockParseState s =
1733data BlockParseState s =
@@ -1733,26 +1743,27 @@ data BlockParseState s =
1734-- XXX Put a limit on nest level to keep the API safe.
1744-- XXX Put a limit on nest level to keep the API safe.
1736−-- | Parse a block using block enclosed by open, close identifiers, block
1746+-- | Parse a block enclosed within open, close brackets. Block contents may be
1737−-- identifiers inside quotes are ignored. Quoting characters can be escaped. A
1747+-- quoted, brackets inside quotes are ignored. Quoting characters can be used
1738−-- block can have a nested block inside it.
1748+-- within quotes if escaped. A block can have a nested block inside it.
1750+-- Quote begin and end chars are the same. Block brackets and quote chars must
1740−-- Block chars and quote chars must not overlap. Block start and end chars must
1751+-- not overlap. Block start and end brackets must be different for nesting
1741−-- not be the same for nesting without escaping.
1752+-- blocks within blocks.
1743−-- >>> p = Parser.blockQuotedBy '{' '}' '"' '\\' Fold.toList
1754+-- >>> p = Parser.blockWithQuotes '{' '}' '"' '\\' Fold.toList
1744-- >>> Stream.parse p $ Stream.fromList "{msg: \"hello world\"}"
1755-- >>> Stream.parse p $ Stream.fromList "{msg: \"hello world\"}"
1745-- Right "msg: \"hello world\""
1756-- Right "msg: \"hello world\""
1747−{-# INLINE blockQuotedBy #-}
1758+{-# INLINE blockWithQuotes #-}
1748−blockQuotedBy :: (Monad m, Eq a) =>
1759+blockWithQuotes :: (Monad m, Eq a) =>
1749− a -- ^ Block opening char
1760+ a -- ^ Block opening bracket
1750− -> a -- ^ Block closing char
1761+ -> a -- ^ Block closing bracket
1751 -> a -- ^ quote char
1762 -> a -- ^ quote char
1752 -> a -- ^ escape char
1763 -> a -- ^ escape char
1753 -> Fold m a b
1764 -> Fold m a b
1754 -> Parser a m b
1765 -> Parser a m b
1755−blockQuotedBy bopen bclose quote esc
1766+blockWithQuotes bopen bclose quote esc
1756 (Fold fstep finitial fextract) =
1767 (Fold fstep finitial fextract) =
1757 Parser step initial extract
1768 Parser step initial extract
@@ -1764,7 +1775,7 @@ blockQuotedBy bopen bclose quote esc
1764 case res of
1775 case res of
1765 FL.Partial s -> IPartial (BlockInit s)
1776 FL.Partial s -> IPartial (BlockInit s)
1766 FL.Done _ ->
1777 FL.Done _ ->
1767− error "wordQuotedBy: fold finished without input"
1778+ error "blockWithQuotes: fold finished without input"
1769 {-# INLINE process #-}
1780 {-# INLINE process #-}
1770 process s a nextState = do
1781 process s a nextState = do
@@ -1778,7 +1789,7 @@ blockQuotedBy bopen bclose quote esc
1779 $ if a == bopen
1790 $ if a == bopen
1780 then Continue 0 $ BlockUnquoted 1 s
1791 then Continue 0 $ BlockUnquoted 1 s
1781− else Error "blockQuotedBy: missing block start"
1792+ else Error "blockWithQuotes: missing block start"
1782 step (BlockUnquoted level s) a =
1793 step (BlockUnquoted level s) a =
1783 if a == bopen
1794 if a == bopen
1784 then process s a (BlockUnquoted (level + 1))
1795 then process s a (BlockUnquoted (level + 1))
@@ -1804,12 +1815,12 @@ blockQuotedBy bopen bclose quote esc
1805 extract (BlockInit s) = fmap (Done 0) $ fextract s
1816 extract (BlockInit s) = fmap (Done 0) $ fextract s
1806 extract (BlockUnquoted level _) =
1817 extract (BlockUnquoted level _) =
1807− err $ "blockQuotedBy: finished at block nest level " ++ show level
1818+ err $ "blockWithQuotes: finished at block nest level " ++ show level
1808 extract (BlockQuoted level _) =
1819 extract (BlockQuoted level _) =
1809− err $ "blockQuotedBy: finished, inside an unfinished quote, "
1820+ err $ "blockWithQuotes: finished, inside an unfinished quote, "
1810 ++ "at block nest level " ++ show level
1821 ++ "at block nest level " ++ show level
1811 extract (BlockQuotedEsc level _) =
1822 extract (BlockQuotedEsc level _) =
1812− err $ "blockQuotedBy: finished, inside an unfinished quote, "
1823+ err $ "blockWithQuotes: finished, inside an unfinished quote, "
1813 ++ "after an escape char, at block nest level " ++ show level
1824 ++ "after an escape char, at block nest level " ++ show level
1815{-# ANN type GroupByState Fuse #-}
1826{-# ANN type GroupByState Fuse #-}