1 + if true then 1 else 1
should also not parse
Operators are also not allowed to have an `if`, `let`, `with` or `assert` expression as their argument (just like functions).
This commit is contained in:
parent
82c19b650c
commit
fe596a3e3a
|
@ -14,10 +14,10 @@ import Prelude hiding (elem)
|
|||
|
||||
-- | The lexer for this parser is defined in 'Nix.Parser.Library'.
|
||||
nixExpr :: Parser NExpr
|
||||
nixExpr = whiteSpace *> foldl' makeParser nixTerm nixOperators where
|
||||
nixExpr = whiteSpace *> (nixToplevelForm <|> foldl' makeParser nixOpArg nixOperators)
|
||||
where
|
||||
makeParser term (Left NSelectOp) = nixSelect term
|
||||
makeParser term (Left NAppOp)
|
||||
= foldl' (fmap Fix . NApp) <$> term <*> many nixFunArg
|
||||
makeParser term (Left NAppOp) = chainl1 term $ pure $ \a b -> Fix (NApp a b)
|
||||
makeParser term (Left NHasAttrOp) = nixHasAttr term
|
||||
makeParser term (Right ops) = buildExpressionParser [map buildOp ops] term
|
||||
|
||||
|
@ -55,25 +55,13 @@ nixHasAttr term = build <$> term <*> optional (reservedOp "?" *> nixSelector) wh
|
|||
build t Nothing = t
|
||||
build t (Just s) = Fix $ NHasAttr t s
|
||||
|
||||
nixFunArgUnamb :: Parser NExpr
|
||||
nixFunArgUnamb = choice
|
||||
nixOpArg :: Parser NExpr
|
||||
nixOpArg = nixSelect $ choice
|
||||
[ nixInt, nixBool, nixNull, nixParens, nixList, nixPath, nixSPath, nixUri
|
||||
, nixStringExpr ]
|
||||
, nixStringExpr, nixSet, nixSym ]
|
||||
|
||||
nixFunArg :: Parser NExpr
|
||||
nixFunArg = nixSelect $ nixFunArgUnamb <|> nixSet <|> nixSym
|
||||
|
||||
nixTerm :: Parser NExpr
|
||||
nixTerm = nixSelect $ choice
|
||||
[ nixFunArgUnamb
|
||||
, nixLambda
|
||||
, nixSym
|
||||
, nixSet
|
||||
, nixLet
|
||||
, nixIf
|
||||
, nixAssert
|
||||
, nixWith
|
||||
]
|
||||
nixToplevelForm :: Parser NExpr
|
||||
nixToplevelForm = choice [nixLambda, nixLet, nixIf, nixAssert, nixWith]
|
||||
|
||||
nixSym :: Parser NExpr
|
||||
nixSym = mkSym <$> identifier
|
||||
|
@ -93,7 +81,7 @@ nixParens :: Parser NExpr
|
|||
nixParens = parens nixExpr <?> "parens"
|
||||
|
||||
nixList :: Parser NExpr
|
||||
nixList = brackets (Fix . NList <$> many nixFunArg) <?> "list"
|
||||
nixList = brackets (Fix . NList <$> many nixOpArg) <?> "list"
|
||||
|
||||
pathChars :: String
|
||||
pathChars = ['A'..'Z'] ++ ['a'..'z'] ++ "._-+" ++ ['0'..'9']
|
||||
|
@ -103,9 +91,9 @@ nixSPath = mkPath True <$> try (char '<' *> some (oneOf ('/':pathChars)) <* symb
|
|||
<?> "spath"
|
||||
|
||||
nixPath :: Parser NExpr
|
||||
nixPath = token $ fmap (mkPath False) $ (++)
|
||||
nixPath = token $ notFollowedBy (try (string "//")) *> fmap (mkPath False) ((++)
|
||||
<$> (try ((++) <$> many (oneOf pathChars) <*> string "/") <?> "path")
|
||||
<*> some (oneOf ('/':pathChars))
|
||||
<*> some (oneOf ('/':pathChars)))
|
||||
<?> "path"
|
||||
|
||||
nixLet :: Parser NExpr
|
||||
|
@ -137,13 +125,15 @@ nixLambda = Fix <$> (NAbs <$> (try argExpr <?> "lambda arguments") <*> nixExpr)
|
|||
nixStringExpr :: Parser NExpr
|
||||
nixStringExpr = Fix . NStr <$> nixString
|
||||
|
||||
uriAfterColonC :: Parser Char
|
||||
uriAfterColonC = alphaNum <|> oneOf "%/?:@&=+$,-_.!~*'"
|
||||
|
||||
nixUri :: Parser NExpr
|
||||
nixUri = token $ fmap (mkUri . pack) $ (++)
|
||||
<$> try ((++) <$> (scheme <* char ':') <*> fmap (\x -> [':',x]) afterColonC)
|
||||
<*> many afterColonC
|
||||
<$> try ((++) <$> (scheme <* char ':') <*> fmap (\x -> [':',x]) uriAfterColonC)
|
||||
<*> many uriAfterColonC
|
||||
where
|
||||
scheme = (:) <$> letter <*> many (alphaNum <|> oneOf "+-.")
|
||||
afterColonC = alphaNum <|> oneOf "%/?:@&=+$,-_.!~*'"
|
||||
|
||||
nixString :: Parser (NString NExpr)
|
||||
nixString = doubleQuoted <|> indented <?> "string"
|
||||
|
@ -177,7 +167,7 @@ nixString = doubleQuoted <|> indented <?> "string"
|
|||
|
||||
argExpr :: Parser (Formals NExpr)
|
||||
argExpr = choice
|
||||
[ idOrAtPattern <$> identifier <*> optional (symbolic '@' *> paramSet)
|
||||
[ idOrAtPattern <$> identifierNotUri <*> optional (symbolic '@' *> paramSet)
|
||||
, setOrAtPattern <$> paramSet <*> optional (symbolic '@' *> identifier)
|
||||
] <* symbolic ':'
|
||||
where
|
||||
|
@ -187,6 +177,9 @@ argExpr = choice
|
|||
argList :: Parser [(Text, Maybe NExpr)]
|
||||
argList = braces (argName `sepBy` symbolic ',') <?> "arglist"
|
||||
|
||||
identifierNotUri :: Parser Text
|
||||
identifierNotUri = notFollowedBy nixUri *> identifier
|
||||
|
||||
argName :: Parser (Text, Maybe NExpr)
|
||||
argName = (,) <$> identifier
|
||||
<*> optional (symbolic '?' *> nixExpr)
|
||||
|
|
|
@ -354,6 +354,12 @@ mkBool = Fix . NConstant . NBool
|
|||
mkNull :: NExpr
|
||||
mkNull = Fix (NConstant NNull)
|
||||
|
||||
mkOper :: NUnaryOp -> NExpr -> NExpr
|
||||
mkOper op = Fix . NOper . NUnary op
|
||||
|
||||
mkOper2 :: NBinaryOp -> NExpr -> NExpr -> NExpr
|
||||
mkOper2 op a = Fix . NOper . NBinary op a
|
||||
|
||||
-- | An 'NValue' is the most reduced form of an 'NExpr' after evaluation
|
||||
-- is completed.
|
||||
data NValueF r
|
||||
|
|
|
@ -116,6 +116,8 @@ case_lambda_or_uri = do
|
|||
assertParseString "a :b" $ Fix $ NAbs (FormalName "a") (mkSym "b")
|
||||
assertParseString "a c:def" $ Fix $ NApp (mkSym "a") (mkUri "c:def")
|
||||
assertParseString "c:def: c" $ Fix $ NApp (mkUri "c:def:") (mkSym "c")
|
||||
assertParseString "a:{}" $ Fix $ NAbs (FormalName "a") $ Fix $ NSet NonRec []
|
||||
assertParseString "a:[a]" $ Fix $ NAbs (FormalName "a") $ Fix $ NList [mkSym "a"]
|
||||
assertParseFail "def:"
|
||||
|
||||
case_lambda_pattern :: Assertion
|
||||
|
@ -266,9 +268,20 @@ case_indented_string_escape = assertParseString
|
|||
|
||||
case_operator_fun_app :: Assertion
|
||||
case_operator_fun_app = do
|
||||
assertParseString "a ++ b" $ Fix $ NOper (NBinary NConcat (mkSym "a") (mkSym "b"))
|
||||
assertParseString "a ++ f b" $ Fix $ NOper (NBinary NConcat (mkSym "a") (Fix
|
||||
(NApp (mkSym "f") (mkSym "b"))))
|
||||
assertParseString "a ++ b" $ mkOper2 NConcat (mkSym "a") (mkSym "b")
|
||||
assertParseString "a ++ f b" $ mkOper2 NConcat (mkSym "a") $ Fix $ NApp
|
||||
(mkSym "f") (mkSym "b")
|
||||
|
||||
case_operators :: Assertion
|
||||
case_operators = do
|
||||
assertParseString "1 + 2 - 3" $ mkOper2 NMinus
|
||||
(mkOper2 NPlus (mkInt 1) (mkInt 2)) (mkInt 3)
|
||||
assertParseFail "1 + if true then 1 else 2"
|
||||
assertParseString "1 + (if true then 2 else 3)" $ mkOper2 NPlus (mkInt 1) $ Fix $ NIf
|
||||
(mkBool True) (mkInt 2) (mkInt 3)
|
||||
assertParseString "{ a = 3; } // rec { b = 4; }" $ mkOper2 NUpdate
|
||||
(Fix $ NSet NonRec [NamedVar (mkSelector "a") (mkInt 3)])
|
||||
(Fix $ NSet Rec [NamedVar (mkSelector "b") (mkInt 4)])
|
||||
|
||||
tests :: TestTree
|
||||
tests = $testGroupGenerator
|
||||
|
|
Loading…
Reference in a new issue