packages feed

conditional-restriction-parser-0.1.0.4: src/ConditionalRestriction/Internal/Parse/RestrictionParser.hs

-- | Parser for conditional restrictions.
module ConditionalRestriction.Internal.Parse.RestrictionParser where

import ConditionalRestriction.Internal.Parse.OpeningHoursParser
  ( pOpeningHours,
  )
import ConditionalRestriction.Internal.Parse.ParserLib
  ( Parser,
    anyOf,
    dbl,
    noneOf,
    strip,
    word,
    ws,
  )
import ConditionalRestriction.Parse.AST
  ( ComparisonOp (..),
    Condition (..),
    ConditionalRestriction (..),
    Expression (..),
  )
import Control.Applicative (Alternative (many, some, (<|>)))
import Data.Functor ()

-- | Parse conditional restrictions, e.g. @"90 \@ 18:00-22:00; 50 \@ wet"@.
pConditionalRestriction :: Parser String ConditionalRestriction
pConditionalRestriction = ConditionalRestriction <$> ((:) <$> pExpression <*> many (word ";" *> pExpression))

pExpression :: Parser String Expression
pExpression = Expression <$> (strip <$> many (noneOf "@")) <*> (word "@" *> pMultipleConditions)

pMultipleConditions :: Parser String [Condition]
pMultipleConditions =
  (word "(" *> pMultipleConditions <* word ")")
    <|> (:) <$> pCondition <*> many (word "AND" *> pCondition)

pCondition :: Parser String Condition
pCondition =
  (word "(" *> pCondition <* word ")")
    <|> (OH <$> pOpeningHours)
    <|> (Comparison <$> pIdentifier <*> pCompOperator <*> dbl <* ws)
    <|> (Absolute <$> pIdentifier)

pCompOperator :: Parser String ComparisonOp
pCompOperator =
  (GtEq <$ word ">=")
    <|> (LtEq <$ word "<=")
    <|> (Eq <$ word "=")
    <|> (Lt <$ word "<")
    <|> (Gt <$ word ">")

pIdentifier :: Parser String String
pIdentifier = some (anyOf $ ['a' .. 'z'] ++ ['_', '-']) <* ws