Skip to content

Commit bb1ebba

Browse files
committed
Parser: refactor
1 parent 9c4d123 commit bb1ebba

File tree

1 file changed

+101
-60
lines changed

1 file changed

+101
-60
lines changed

src/Nix/Parser.hs

Lines changed: 101 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ import Prettyprinter ( Doc
8585
import Text.Megaparsec hiding ( State )
8686
import Text.Megaparsec.Char
8787
import qualified Text.Megaparsec.Char.Lexer as L
88+
import Nix.Utils ( bool )
8889

8990
infixl 3 <+>
9091
(<+>) :: MonadPlus m => m a -> m a -> m a
@@ -93,18 +94,23 @@ infixl 3 <+>
9394
---------------------------------------------------------------------------------
9495

9596
nixExpr :: Parser NExprLoc
96-
nixExpr = makeExprParser nixTerm $ fmap (fmap snd) (nixOperators nixSelector)
97+
nixExpr =
98+
makeExprParser
99+
nixTerm $
100+
(fmap . fmap)
101+
snd
102+
(nixOperators nixSelector)
97103

98104
antiStart :: Parser Text
99105
antiStart = symbol "${" <?> show ("${" :: String)
100106

101107
nixAntiquoted :: Parser a -> Parser (Antiquoted a NExprLoc)
102108
nixAntiquoted p =
103-
Antiquoted
104-
<$> (antiStart *> nixToplevelForm <* symbol "}")
105-
<+> Plain
106-
<$> p
107-
<?> "anti-quotation"
109+
Antiquoted <$>
110+
(antiStart *> nixToplevelForm <* symbol "}")
111+
<+> Plain <$>
112+
p
113+
<?> "anti-quotation"
108114

109115
selDot :: Parser ()
110116
selDot = try (symbol "." *> notFollowedBy nixPath) <?> "."
@@ -133,13 +139,18 @@ nixSelect term =
133139
, Maybe NExprLoc
134140
)
135141
-> NExprLoc
136-
build t Nothing = t
137-
build t (Just (s, o)) = nSelectLoc t s o
142+
build t mexpr =
143+
maybe
144+
t
145+
(uncurry (nSelectLoc t))
146+
mexpr
138147

139148
nixSelector :: Parser (Ann SrcSpan (NAttrPath NExprLoc))
140-
nixSelector = annotateLocation $ do
141-
(x : xs) <- keyName `sepBy1` selDot
142-
pure $ x :| xs
149+
nixSelector =
150+
annotateLocation $
151+
do
152+
(x : xs) <- keyName `sepBy1` selDot
153+
pure $ x :| xs
143154

144155
nixTerm :: Parser NExprLoc
145156
nixTerm = do
@@ -159,12 +170,12 @@ nixTerm = do
159170
$ [ nixSelect nixSet | c == 'r' ]
160171
<> [ nixPath | pathChar c ]
161172
<> if isDigit c
162-
then [nixFloat, nixInt]
173+
then [ nixFloat, nixInt ]
163174
else
164175
[ nixUri | isAlpha c ]
165176
<> [ nixBool | c == 't' || c == 'f' ]
166177
<> [ nixNull | c == 'n' ]
167-
<> [nixSelect nixSym]
178+
<> [ nixSelect nixSym ]
168179

169180
nixToplevelForm :: Parser NExprLoc
170181
nixToplevelForm = keywords <+> nixLambda <+> nixExpr
@@ -216,11 +227,12 @@ slash =
216227
-- | A path surrounded by angle brackets, indicating that it should be
217228
-- looked up in the NIX_PATH environment variable at evaluation.
218229
nixSearchPath :: Parser NExprLoc
219-
nixSearchPath = annotateLocation1
220-
( mkPathF True
221-
<$> try (char '<' *> many (satisfy pathChar <+> slash) <* symbol ">")
222-
<?> "spath"
223-
)
230+
nixSearchPath =
231+
annotateLocation1
232+
(mkPathF True <$>
233+
try (char '<' *> many (satisfy pathChar <+> slash) <* symbol ">")
234+
<?> "spath"
235+
)
224236

225237
pathStr :: Parser FilePath
226238
pathStr = lexeme $ liftM2
@@ -235,15 +247,18 @@ nixLet :: Parser NExprLoc
235247
nixLet = annotateLocation1
236248
(reserved "let" *> (letBody <+> letBinders) <?> "let block")
237249
where
238-
letBinders = NLet <$> nixBinders <*> (reserved "in" *> nixToplevelForm)
250+
letBinders =
251+
NLet
252+
<$> nixBinders
253+
<*> (reserved "in" *> nixToplevelForm)
239254
-- Let expressions `let {..., body = ...}' are just desugared
240255
-- into `(rec {..., body = ...}).body'.
241256
letBody = (\x -> NSelect x (StaticKey "body" :| mempty) Nothing) <$> aset
242257
aset = annotateLocation1 $ NSet NRecursive <$> braces nixBinders
243258

244259
nixIf :: Parser NExprLoc
245260
nixIf = annotateLocation1
246-
( NIf
261+
(NIf
247262
<$> (reserved "if" *> nixExpr)
248263
<*> (reserved "then" *> nixToplevelForm)
249264
<*> (reserved "else" *> nixToplevelForm)
@@ -252,15 +267,15 @@ nixIf = annotateLocation1
252267

253268
nixAssert :: Parser NExprLoc
254269
nixAssert = annotateLocation1
255-
( NAssert
270+
(NAssert
256271
<$> (reserved "assert" *> nixToplevelForm)
257272
<*> (semi *> nixToplevelForm)
258273
<?> "assert"
259274
)
260275

261276
nixWith :: Parser NExprLoc
262277
nixWith = annotateLocation1
263-
( NWith
278+
(NWith
264279
<$> (reserved "with" *> nixToplevelForm)
265280
<*> (semi *> nixToplevelForm)
266281
<?> "with"
@@ -275,11 +290,20 @@ nixString = nStr <$> annotateLocation nixString'
275290
nixUri :: Parser NExprLoc
276291
nixUri = lexeme $ annotateLocation1 $ try $ do
277292
start <- letterChar
278-
protocol <- many $ satisfy $ \x ->
279-
isAlpha x || isDigit x || x `elem` ("+-." :: String)
293+
protocol <- many $
294+
satisfy $
295+
\ x ->
296+
isAlpha x
297+
|| isDigit x
298+
|| (`elem` ("+-." :: String)) x
280299
_ <- string ":"
281-
address <- some $ satisfy $ \x ->
282-
isAlpha x || isDigit x || x `elem` ("%/?:@&=+$,-_.!~*'" :: String)
300+
address <-
301+
some $
302+
satisfy $
303+
\ x ->
304+
isAlpha x
305+
|| isDigit x
306+
|| (`elem` ("%/?:@&=+$,-_.!~*'" :: String)) x
283307
pure $ NStr $ DoubleQuoted
284308
[Plain $ pack $ start : protocol ++ ':' : address]
285309

@@ -289,54 +313,66 @@ nixString' = lexeme (doubleQuoted <+> indented <?> "string")
289313
doubleQuoted :: Parser (NString NExprLoc)
290314
doubleQuoted =
291315
DoubleQuoted
292-
. removePlainEmpty
293-
. mergePlain
294-
<$> ( doubleQ
295-
*> many (stringChar doubleQ (void $ char '\\') doubleEscape)
296-
<* doubleQ
297-
)
316+
. removePlainEmpty
317+
. mergePlain <$>
318+
( doubleQ
319+
*> many (stringChar doubleQ (void $ char '\\') doubleEscape)
320+
<* doubleQ
321+
)
298322
<?> "double quoted string"
299323

300324
doubleQ = void (char '"')
301325
doubleEscape = Plain . singleton <$> (char '\\' *> escapeCode)
302326

303327
indented :: Parser (NString NExprLoc)
304328
indented =
305-
stripIndent
306-
<$> ( indentedQ
307-
*> many (stringChar indentedQ indentedQ indentedEscape)
308-
<* indentedQ
309-
)
329+
stripIndent <$>
330+
(indentedQ
331+
*> many (stringChar indentedQ indentedQ indentedEscape)
332+
<* indentedQ
333+
)
310334
<?> "indented string"
311335

312336
indentedQ = void (string "''" <?> "\"''\"")
313-
indentedEscape = try $ do
314-
indentedQ
315-
(Plain <$> ("''" <$ char '\'' <+> "$" <$ char '$')) <+> do
316-
_ <- char '\\'
317-
c <- escapeCode
318-
pure $ if c == '\n' then EscapedNewline else Plain $ singleton c
337+
indentedEscape =
338+
try $
339+
do
340+
indentedQ
341+
(Plain <$> ("''" <$ char '\'' <+> "$" <$ char '$')) <+>
342+
do
343+
_ <- char '\\'
344+
c <- escapeCode
345+
346+
pure $
347+
bool
348+
EscapedNewline
349+
(Plain $ singleton c)
350+
(c /= '\n')
319351

320352
stringChar end escStart esc =
321-
Antiquoted
322-
<$> (antiStart *> nixToplevelForm <* char '}')
323-
<+> Plain
324-
. singleton
325-
<$> char '$'
326-
<+> esc
327-
<+> Plain
328-
. pack
329-
<$> some plainChar
353+
Antiquoted <$>
354+
(antiStart *> nixToplevelForm <* char '}')
355+
<+> Plain . singleton <$>
356+
char '$' <+> esc <+> Plain . pack <$>
357+
some plainChar
330358
where
331359
plainChar =
332360
notFollowedBy (end <+> void (char '$') <+> escStart) *> anySingle
333361

334-
escapeCode = msum [ c <$ char e | (c, e) <- escapeCodes ] <+> anySingle
362+
escapeCode =
363+
msum
364+
[ c <$ char e | (c, e) <- escapeCodes ]
365+
<+> anySingle
335366

336367
-- | Gets all of the arguments for a function.
337368
argExpr :: Parser (Params NExprLoc)
338369
argExpr =
339-
msum [atLeft, onlyname, atRight] <* symbol ":"
370+
msum
371+
[ atLeft
372+
, onlyname
373+
, atRight
374+
]
375+
<* symbol ":"
340376
where
341377
-- An argument not in curly braces. There's some potential ambiguity
342378
-- in the case of, for example `x:y`. Is it a lambda function `x: y`, or
@@ -394,12 +430,15 @@ nixBinders :: Parser [Binding NExprLoc]
394430
nixBinders = (inherit <+> namedVar) `endBy` semi where
395431
inherit =
396432
do
397-
-- We can't use 'reserved' here because it would consume the whitespace
398-
-- after the keyword, which is not exactly the semantics of C++ Nix.
433+
-- We can't use 'reserved' here because it would consume the whitespace
434+
-- after the keyword, which is not exactly the semantics of C++ Nix.
399435
try $ string "inherit" *> lookAhead (void (satisfy reservedEnd))
400436
p <- getSourcePos
401437
x <- whiteSpace *> optional scope
402-
Inherit x <$> many keyName <*> pure p <?> "inherited binding"
438+
Inherit x
439+
<$> many keyName
440+
<*> pure p
441+
<?> "inherited binding"
403442
namedVar =
404443
do
405444
p <- getSourcePos
@@ -411,7 +450,8 @@ nixBinders = (inherit <+> namedVar) `endBy` semi where
411450
scope = nixParens <?> "inherit scope"
412451

413452
keyName :: Parser (NKeyName NExprLoc)
414-
keyName = dynamicKey <+> staticKey where
453+
keyName = dynamicKey <+> staticKey
454+
where
415455
staticKey = StaticKey <$> identifier
416456
dynamicKey = DynamicKey <$> nixAntiquoted nixString'
417457

@@ -498,8 +538,9 @@ float :: Parser Double
498538
float = lexeme L.float
499539

500540
reservedNames :: HashSet Text
501-
reservedNames = HashSet.fromList
502-
["let", "in", "if", "then", "else", "assert", "with", "rec", "inherit"]
541+
reservedNames =
542+
HashSet.fromList
543+
["let", "in", "if", "then", "else", "assert", "with", "rec", "inherit"]
503544

504545
type Parser = ParsecT Void Text (State SourcePos)
505546

0 commit comments

Comments
 (0)