summaryrefslogtreecommitdiff
path: root/src/Expression.hs
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2026-07-05 17:47:54 +0200
committerRoman Smrž <roman.smrz@seznam.cz>2026-07-11 15:24:37 +0200
commit4d2de6a51f555cb2365e161c082223e7d9f21bc8 (patch)
treec4c19abb35253db98f65d249539198496ebce0bc /src/Expression.hs
parent0b3b675bfc9e78ee563d526f17184e317a962ae8 (diff)
Range expression parsing
Diffstat (limited to 'src/Expression.hs')
-rw-r--r--src/Expression.hs74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/Expression.hs b/src/Expression.hs
index 6b1adc9..95ba815 100644
--- a/src/Expression.hs
+++ b/src/Expression.hs
@@ -9,14 +9,28 @@ module Expression (
evaluateDeclaredRevision, evaluateDeclaredRange,
evaluateRevision, evaluateRange,
getRangeCommits, getAddedRangeCommits,
+
+ isRangeExpressionDynamic,
+ isRevisionExpressionDynamic,
+
+ parseRangeExpression,
) where
import Control.Concurrent.STM
import Control.Monad.IO.Class
+import Data.Bifunctor
+import Data.Char
import Data.Kind
+import Data.List.NonEmpty qualified as NE
import Data.Maybe
+import Data.Proxy
import Data.Text (Text)
+import Data.Text qualified as T
+import Data.Void
+
+import Text.Megaparsec
+import Text.Megaparsec.Char
import Job.Types
import Output
@@ -112,3 +126,63 @@ getAddedRangeCommits repo (CommitRange ar br) (CommitRange ar' br') = do
(++)
<$> listCommitsFrom repo a'b (catMaybes [ b' ]) -- added by moving B to B'
<*> listCommitsFrom repo (catMaybes [ a' ]) (catMaybes [ a, b, b' ]) -- added by moving A to A'
+
+
+isRangeExpressionDynamic :: RangeExpression -> Bool
+isRangeExpressionDynamic = \case
+ RangeExpression x y -> isRevisionExpressionDynamic x || isRevisionExpressionDynamic y
+
+isRevisionExpressionDynamic :: RevisionExpression -> Bool
+isRevisionExpressionDynamic = \case
+ StaticRef _ -> False
+ WatchedRef _ -> True
+ ModifiedRevision _ e -> isRevisionExpressionDynamic e
+
+
+type ExprParser = Parsec Void Text
+
+parseRangeExpression :: Text -> Either String DeclaredRangeExpression
+parseRangeExpression = bimap errorBundlePretty id . runParser parser ""
+ where
+ parser :: ExprParser DeclaredRangeExpression
+ parser = do
+ rev1 <- parseRevision
+ expr <- choice
+ [ do
+ _ <- string ".."
+ rev2 <- parseRevision
+ return $ RangeExpression rev2 rev1
+ , do
+ return $ RangeExpression rev1 (ModifiedRevision "^" rev1)
+ ]
+
+ (char ':' >> eof) <|> eof
+ return expr
+
+ parseRevision :: ExprParser DeclaredRevisionExpression
+ parseRevision = do
+ tok <- fmap T.concat $ some $ choice
+ [ takeWhile1P Nothing (\x -> isAlphaNum x || x `elem` [ '_', '-', '/' ])
+ , try $ string "." <* notFollowedBy (char '.')
+ ]
+
+ rev <- choice
+ [ do
+ _ <- char '('
+ arg <- takeWhileP Nothing (\x -> isAlphaNum x || x `elem` [ '_', '-', '/', '.' ])
+ _ <- char ')'
+ case tok of
+ "watch" -> return $ WatchedRef arg
+ _ -> unexpected $ Tokens $ NE.fromList $ chunkToTokens @Text Proxy tok
+
+ , do
+ return $ StaticRef tok
+ ]
+
+ choice
+ [ do
+ suffix <- takeWhile1P Nothing (\x -> isNumber x || x `elem` [ '~', '^', '@', '{', '}' ])
+ return $ ModifiedRevision suffix rev
+ , do
+ return rev
+ ]