diff options
author | Roman Smrž <roman.smrz@seznam.cz> | 2022-08-23 21:39:22 +0200 |
---|---|---|
committer | Roman Smrž <roman.smrz@seznam.cz> | 2022-08-23 21:39:22 +0200 |
commit | 6e183bf63ad75da44a030d0d6f5060e8b745d2ca (patch) | |
tree | d67cfca8031319e2a643a8bf4b423a2901283679 /src | |
parent | 85fe4fa7427ef67be9177e682e64bbe5fe8b6c59 (diff) |
Expression expansion in strings and regexes
Diffstat (limited to 'src')
-rw-r--r-- | src/Parser.hs | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/src/Parser.hs b/src/Parser.hs index 77a2877..027c358 100644 --- a/src/Parser.hs +++ b/src/Parser.hs @@ -123,15 +123,26 @@ addVarName _ name = do Nothing -> return () modify $ \s -> s { testVars = (name, SomeExprType @a Proxy) : testVars s } -varExpansion :: TestParser VarName -varExpansion = do +someExpansion :: TestParser SomeExpr +someExpansion = do void $ char '$' choice - [ VarName . (:[]) . TL.toStrict <$> takeWhile1P Nothing (\x -> isAlphaNum x || x == '_') - ,do void $ char '{' - name <- varName - void $ char '}' - return name + [do name <- VarName . (:[]) . TL.toStrict <$> takeWhile1P Nothing (\x -> isAlphaNum x || x == '_') + SomeVarValue (_ :: a) <- lookupVar name + return $ SomeExpr $ Variable @a name + , between (char '{') (char '}') someExpr + ] + +stringExpansion :: Text -> TestParser (Expr Text) +stringExpansion tname = do + off <- stateOffset <$> getParserState + SomeExpr e <- someExpansion + let err = parseError $ FancyError off $ S.singleton $ ErrorFail $ T.unpack $ T.concat + [ tname, T.pack " expansion not defined for '", textExprType e, T.pack "'" ] + + maybe err return $ listToMaybe $ catMaybes + [ cast e + , UnOp (T.pack . show @Integer) <$> cast e ] integerLiteral :: TestParser (Expr Integer) @@ -139,7 +150,7 @@ integerLiteral = Literal . read . TL.unpack <$> takeWhile1P (Just "integer") isD quotedString :: TestParser (Expr Text) quotedString = label "string" $ lexeme $ do - symbol "\"" + void $ char '"' let inner = choice [ char '"' >> return [] , takeWhile1P Nothing (`notElem` "\"\\$") >>= \s -> (Literal (TL.toStrict s):) <$> inner @@ -153,14 +164,14 @@ quotedString = label "string" $ lexeme $ do , char 't' >> return '\t' ] (Literal (T.singleton c) :) <$> inner - ,do name <- varExpansion - (Variable name :) <$> inner + ,do e <- stringExpansion (T.pack "string") + (e:) <$> inner ] Concat <$> inner regex :: TestParser (Expr Regex) regex = label "regular expression" $ lexeme $ do - symbol "/" + void $ char '/' let inner = choice [ char '/' >> return [] , takeWhile1P Nothing (`notElem` "/\\$") >>= \s -> (Literal (TL.toStrict s) :) <$> inner @@ -170,8 +181,8 @@ regex = label "regular expression" $ lexeme $ do , anySingle >>= \c -> return (Literal $ T.pack ['\\', c]) ] (s:) <$> inner - ,do name <- varExpansion - (Variable name :) <$> inner + ,do e <- stringExpansion (T.pack "regex") + (e:) <$> inner ] expr <- Regex <$> inner _ <- eval expr -- test regex parsing with empty variables |