From 9f66b6432fd8025f115289e6b2a9db1579385634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Smr=C5=BE?= Date: Sat, 5 Sep 2026 09:57:31 +0200 Subject: Fix parsing of shell argument starting with variable expansion --- src/Parser/Expr.hs | 12 ++++++++---- src/Parser/Shell.hs | 16 +++++++++++++++- test/asset/shell/expansion.et | 1 + test/script/shell.et | 1 + 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/Parser/Expr.hs b/src/Parser/Expr.hs index 2d0b770..b2c6b84 100644 --- a/src/Parser/Expr.hs +++ b/src/Parser/Expr.hs @@ -14,6 +14,7 @@ module Parser.Expr ( variable, constructor, + someExpansion, expansionTypeCheck, expressionExpansion, stringExpansion, @@ -110,10 +111,8 @@ someExpansion = do , between (char '{') (char '}') (someExpr FunctionTerm) ] -expressionExpansion :: forall a. ExprType a => Text -> TestParser (Expr a) -expressionExpansion tname = do - off <- stateOffset <$> getParserState - SomeExpr e <- someExpansion +expansionTypeCheck :: forall a. ExprType a => Int -> Text -> SomeExpr -> TestParser (Expr a) +expansionTypeCheck off tname (SomeExpr e) = do let err = do registerParseError $ FancyError off $ S.singleton $ ErrorFail $ T.unpack $ T.concat [ tname, T.pack " expansion not defined for '", textExprType e, T.pack "'" ] @@ -121,6 +120,11 @@ expressionExpansion tname = do maybe err (return . (<$> e)) $ listToMaybe $ catMaybes [ cast (id :: a -> a), exprExpansionConvTo, exprExpansionConvFrom ] +expressionExpansion :: forall a. ExprType a => Text -> TestParser (Expr a) +expressionExpansion tname = do + off <- stateOffset <$> getParserState + expansionTypeCheck off tname =<< someExpansion + stringExpansion :: TestParser (Expr Text) stringExpansion = expressionExpansion "string" diff --git a/src/Parser/Shell.hs b/src/Parser/Shell.hs index 8c8ef46..2d6026a 100644 --- a/src/Parser/Shell.hs +++ b/src/Parser/Shell.hs @@ -99,10 +99,24 @@ parseArgument = choice parseArguments :: TestParser (Expr ShellArguments) parseArguments = do arglists <- many $ choice - [ expressionExpansion "shell arguments" <* sc + [ do + off <- stateOffset <$> getParserState + se <- someExpansion + choice + [ do + notFollowedBy space1 + arg <- expansionTypeCheck off "shell argument" se + txt <- parseTextArgument + return $ joinArgument <$> arg <*> txt + , do + expansionTypeCheck off "shell arguments" se <* sc + ] , fmap (ShellArguments . (: [])) <$> parseArgument ] return $ fmap mconcat $ foldr (liftA2 (:)) (Pure []) $ arglists + where + joinArgument (ShellArgument x) y = ShellArguments [ ShellArgument (x <> y) ] + joinArgument ax y = ShellArguments [ ax, ShellArgument y ] parseCommand :: TestParser (Expr ShellCommand) parseCommand = label "shell statement" $ do diff --git a/test/asset/shell/expansion.et b/test/asset/shell/expansion.et index 3f318ab..b947eb6 100644 --- a/test/asset/shell/expansion.et +++ b/test/asset/shell/expansion.et @@ -17,3 +17,4 @@ test Test: $cmd H I $cmdlist J $cmdlist K $ilist L $int M $special N + echo ${str}O P$str diff --git a/test/script/shell.et b/test/script/shell.et index 36eaff7..90ff29a 100644 --- a/test/script/shell.et +++ b/test/script/shell.et @@ -197,6 +197,7 @@ test ShellVariableExpansion: expect /child-stdout sh H I/ expect /child-stdout sh w x y z J/ expect /child-stdout sh w x y z K 1 2 3 4 5 L 2 M < > \| \& \; N/ + expect /child-stdout sh some stringO Psome string/ expect /run-test-result Test done/ expect /run-done 1 1 0 0/ flush -- cgit v1.2.3