44{-# LANGUAGE TemplateHaskell #-}
55
66module Language.Nix.Identifier
7- ( Identifier , ident , quote , needsQuoting
7+ ( Identifier , ident , quote , needsQuoting , nixKeywords
88 , parseSimpleIdentifier , parseQuotedIdentifier
9+ -- TODO: why do we expose quote?
910 )
1011 where
1112
@@ -44,6 +45,7 @@ import Text.PrettyPrint.HughesPJClass as PP
4445-- __Warning__: Identifiers /may not/ contain @\'\\0\'@, but this is not
4546-- checked during construction!
4647--
48+ -- See also <https://nix.dev/manual/nix/2.30/language/identifiers.html>.
4749declareLenses [d | newtype Identifier = Identifier { ident :: String }
4850 deriving (Show, Eq, Ord, IsString, Generic)
4951 |]
@@ -75,10 +77,17 @@ instance CoArbitrary Identifier
7577instance Pretty Identifier where
7678 pPrint = view (ident . to quote . to text)
7779
80+ -- | Note that this parser is more lenient than Nix w.r.t. simple identifiers,
81+ -- since it will accept 'nixKeywords'.
7882instance HasParser Identifier where
7983 parser = parseQuotedIdentifier <|> parseSimpleIdentifier
8084
8185-- | Parsec parser for simple identifiers, i.e. those that don't need quoting.
86+ -- The parser is equivalent to the regular expression @^[a-zA-Z_][a-zA-Z0-9_'-]*$@
87+ -- which the Nix parser uses.
88+ --
89+ -- Note that this parser will accept keywords which would not be parsed as
90+ -- identifiers by Nix, see 'nixKeywords'.
8291parseSimpleIdentifier :: CharParser st tok m Identifier
8392parseSimpleIdentifier = do
8493 c <- satisfy (\ x -> x == ' _' || isAlpha x)
@@ -104,10 +113,19 @@ parseQuotedIdentifier = Identifier <$> qstring
104113 return [c1,c2]
105114
106115-- | Checks whether a given string needs quoting when interpreted as an
107- -- 'Identifier'. Simple identifiers that don't need quoting match the
108- -- regular expression @^[a-zA-Z_][a-zA-Z0-9_'-]*$@.
116+ -- 'Identifier'.
109117needsQuoting :: String -> Bool
110- needsQuoting = isLeft . runParser (parseSimpleIdentifier >> eof) () " "
118+ needsQuoting s =
119+ s `elem` nixKeywords
120+ || isLeft (runParser (parseSimpleIdentifier >> eof) () " " s)
121+
122+ -- | List of strings that are parseable as simple identifiers (see
123+ -- 'parseSimpleIdentifier') in isolation, but won't be accepted by Nix because
124+ -- [keywords](https://nix.dev/manual/nix/2.30/language/identifiers.html#keywords)
125+ -- take precedence.
126+ nixKeywords :: [String ]
127+ nixKeywords =
128+ [ " assert" , " with" , " if" , " then" , " else" , " let" , " in" , " rec" , " inherit" , " or" ]
111129
112130-- | Helper function to quote a given identifier string if necessary.
113131--
0 commit comments