diff --git a/doc/arbtt.xml b/doc/arbtt.xml index f601cca..92989a4 100644 --- a/doc/arbtt.xml +++ b/doc/arbtt.xml @@ -300,7 +300,7 @@ These expressions can be compared to integers. Expression week of year $date evaluates to an integer, from 0 to 53, corresponding to the week of year. January 1 falls in week 0. - These expressions can be compared to integers. + These expressions are integers, and can be combined and compared as such. @@ -316,6 +316,12 @@ succeeds if any of them succeeds. + + Integer expressions can be combined via + + (addition), - (subtraction), * (multiplication), + operators. + + Regular expressions are written either between slashes (/ regular expression /), or after a letter m followed by any symbol @@ -458,6 +464,8 @@ week of year month year + + number literal @@ -502,6 +510,12 @@ | > | >= + + MathOp + + | - | + * + + ConditionBinding condition Literal = in diff --git a/src/Categorize.hs b/src/Categorize.hs index e785785..208c364 100644 --- a/src/Categorize.hs +++ b/src/Categorize.hs @@ -69,6 +69,7 @@ data CondPrim | CondRegexList (CtxFun [RE.Regex]) newtype Cmp = Cmp (forall a. Ord a => a -> a -> Bool) +newtype Math = Math (forall a. Num a => a -> a -> a) data DateVar = DvDate | DvNow @@ -226,6 +227,8 @@ parseCondExpr = buildExpressionParser [ , Prefix (reserved lang "month" >> return evalMonth) , Prefix (reserved lang "year" >> return evalYear) , Prefix (reserved lang "format" >> return formatDate) ], + [ Infix (evalMath <$> parseMath) AssocLeft + ], [ Infix (reservedOp lang "=~" >> return checkRegex) AssocNone , Infix (checkCmp <$> parseCmp) AssocNone ], @@ -283,6 +286,15 @@ checkNot cp = Left $ printf "Cannot apply ! to an expression of type %s" (cpType cp) +evalMath :: Math -> CondPrim -> CondPrim -> Erring CondPrim +evalMath (Math (?)) (CondInteger getN1) (CondInteger getN2) = Right $ CondInteger $ \ctx -> do + n1 <- getN1 ctx + n2 <- getN2 ctx + return $ n1 ? n2 +evalMath _ cp1 cp2 = Left $ + printf "Cannot do math on expressions of type %s and type %s" + (cpType cp1) (cpType cp2) + checkCmp :: Cmp -> CondPrim -> CondPrim -> Erring CondPrim checkCmp (Cmp (?)) (CondInteger getN1) (CondInteger getN2) = Right $ CondCond $ \ctx -> do n1 <- getN1 ctx @@ -390,6 +402,13 @@ formatDate (CondDate df) = Right $ CondString $ \ctx -> formatDate cp = Left $ printf "Cannot format an expression of type %s, only $date." (cpType cp) +parseMath :: Parser Math +parseMath = choice $ map (\(s,o) -> reservedOp lang s >> return o) + [("+",Math (+)), + ("-", Math (-)), + ("*",Math (*)) + ] + parseCmp :: Parser Cmp parseCmp = choice $ map (\(s,o) -> reservedOp lang s >> return o) [(">=",Cmp (>=)),