Skip to content

Commit 9af13b1

Browse files
committed
Improve list parser
Current parser for lists, like `packages:` in `cabal.project.local`, fails to process some input, for example: packages: foo/foo.cabal , bar/bar.cabal , baz/baz.cabal This commit simplifies the parser by using `sepBy` directly and by handling indented fields more uniformly.
1 parent 5f2ed1c commit 9af13b1

File tree

2 files changed

+19
-10
lines changed

2 files changed

+19
-10
lines changed

src/Hie/Cabal/Parser.hs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,19 +92,24 @@ parseString = parseQuoted <|> unqualName
9292
unqualName :: Parser Text
9393
unqualName = takeWhile1 (not . (\c -> isSpace c || c == ','))
9494

95+
-- | Skip spaces and if enf of line is reached, skip it as well and require that
96+
-- next one starts with indent.
97+
--
98+
-- Used for parsing fields.
99+
optSkipToNextLine :: Indent -> Parser ()
100+
optSkipToNextLine i = do
101+
skipMany $ satisfy (\c -> isSpace c && not (isEndOfLine c))
102+
mChar <- peekChar
103+
case mChar of
104+
Just c | isEndOfLine c ->
105+
char c *> indent i *> pure ()
106+
_ -> pure ()
107+
108+
-- | Comma or space separated list, with optional new lines.
95109
parseList :: Indent -> Parser [Text]
96110
parseList i = items <|> (emptyOrComLine >> indent i >> items)
97111
where
98-
items = do
99-
skipMany tabOrSpace
100-
h <- parseString
101-
skipMany tabOrSpace
102-
skipMany (char ',')
103-
t <-
104-
items
105-
<|> (skipToNextLine >> indent i >> parseList i)
106-
<|> pure []
107-
pure $ h : t
112+
items = sepBy parseString (optSkipToNextLine i *> skipMany (char ',') *> optSkipToNextLine i)
108113

109114
pathMain :: Indent -> [Text] -> Text -> [Text] -> [Text] -> Parser [Text]
110115
pathMain i p m o a =

test/Spec.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ spec = do
8686
$ it "quoted list"
8787
$ ("\"one\"\n two\n three3" :: Text) ~> parseList 1
8888
`shouldParse` ["one", "two", "three3"]
89+
describe "Should Succeed"
90+
$ it "list with leading commas"
91+
$ ("one\n , two\n , three3" :: Text) ~> parseList 1
92+
`shouldParse` ["one", "two", "three3"]
8993

9094
exeSection :: Text
9195
exeSection =

0 commit comments

Comments
 (0)