content: module Language.SQL.SpiderSQL.Lexer where
  
  import Control.Applicative (Alternative ((<|>)), Applicative (liftA2))
  import Control.Monad.Reader.Class (MonadReader)
  import Data.Char (toLower)
  import Data.Foldable (asum)
  import Language.SQL.SpiderSQL.Prelude (columnNameP, doubleP, intP, isAnd, isAs, isAsc, isAvg, isBetween, isClosedParenthesis, isComma, isCount, isDesc, isDistinct, isDivide, isDot, isEq, isExcept, isFrom, isGe, isGroupBy, isGt, isHaving, isIn, isIntersect, isJoin, isLe, isLike, isLimit, isLt, isMax, isMin, isMinus, isNe, isNot, isOn, isOpenParenthesis, isOr, isOrderBy, isPlus, isSelect, isStar, isSum, isTimes, isUnion, isWhere, manyAtMost, quotedString, tableNameP)
  import Picard.Types (SQLSchema (..))
  import Text.Parser.Char (CharParsing (..), alphaNum, digit, spaces)
  import Text.Parser.Combinators (Parsing (notFollowedBy), sepBy)
  
  -- | @lexSpiderSQL@ produces a list of strings.
  --
  -- Aliases are restricted to the pattern 'T*' where '*' is equal to one or more digits.
  lexSpiderSQL :: (CharParsing m, Monad m, MonadReader SQLSchema m) => m [String]
  lexSpiderSQL =
    let keywords = [isSelect, isDistinct, isMax, isMin, isCount, isSum, isAvg, isFrom, isJoin, isOn, isAs, isAnd, isOr, isNot, isIn, isLike, isBetween, isWhere, isGroupBy, isOrderBy, isAsc, isDesc, isHaving, isLimit, isIntersect, isExcept, isUnion]
        punctuation = [isComma, isClosedParenthesis, isOpenParenthesis, isDot]
        operators = [isMinus, isPlus, isTimes, isDivide, isStar, isEq, isGe, isLe, isGt, isLt, isNe]
        primitives = [show <$> doubleP 16, show <$> intP 8, quotedString 32]
        aliasP = do
          _ <- satisfy (\c -> toLower c == 't')
          digits <- liftA2 (:) digit (manyAtMost (9 :: Int) digit)
          pure $ "T" <> digits
        identifiers =
          let terminate q = q <* notFollowedBy (alphaNum <|> char '_')
           in terminate <$> [tableNameP, columnNameP, aliasP]
        p = asum $ identifiers <> keywords <> punctuation <> operators <> primitives
     in sepBy p spaces
  