Blame src/Text/Regex/Glob/Generic/RegexParser.hs

Packit 5b08af
{-# LANGUAGE FlexibleContexts #-}
Packit 5b08af
Packit 5b08af
-- ------------------------------------------------------------
Packit 5b08af
Packit 5b08af
{- |
Packit 5b08af
   Copyright  : Copyright (C) 2014- Uwe Schmidt
Packit 5b08af
   License    : MIT
Packit 5b08af
Packit 5b08af
   Maintainer : Uwe Schmidt (uwe@fh-wedel.de)
Packit 5b08af
   Stability  : stable
Packit 5b08af
   Portability: portable
Packit 5b08af
Packit 5b08af
   csh style Glob Pattern Parser for Regular Expressions
Packit 5b08af
-}
Packit 5b08af
Packit 5b08af
-- ------------------------------------------------------------
Packit 5b08af
Packit 5b08af
module Text.Regex.Glob.Generic.RegexParser
Packit 5b08af
    ( parseRegex
Packit 5b08af
    , parseRegexNoCase
Packit 5b08af
    )
Packit 5b08af
where
Packit 5b08af
Packit 5b08af
import           Data.Char                               (isLower, isUpper,
Packit 5b08af
                                                          toLower, toUpper)
Packit 5b08af
Packit 5b08af
import           Text.ParserCombinators.Parsec
Packit 5b08af
import           Text.Regex.XMLSchema.Generic.Regex
Packit 5b08af
import           Text.Regex.XMLSchema.Generic.StringLike
Packit 5b08af
Packit 5b08af
-- ------------------------------------------------------------
Packit 5b08af
Packit 5b08af
-- | parse a glob pattern
Packit 5b08af
Packit 5b08af
parseRegex :: StringLike s => s -> GenRegex s
Packit 5b08af
parseRegex
Packit 5b08af
    = parseRegex' mkSymRng . toString
Packit 5b08af
Packit 5b08af
parseRegexNoCase :: StringLike s => s -> GenRegex s
Packit 5b08af
parseRegexNoCase
Packit 5b08af
    = parseRegex' mkNoCaseSymRng . toString
Packit 5b08af
Packit 5b08af
parseRegex' :: StringLike s => (Char -> Char -> GenRegex s) -> String -> GenRegex s
Packit 5b08af
parseRegex' mkS
Packit 5b08af
    = either (mkZero' . ("syntax error: " ++) . show) id
Packit 5b08af
      .
Packit 5b08af
      parse ( do
Packit 5b08af
              r <- pattern mkS
Packit 5b08af
              eof
Packit 5b08af
              return r
Packit 5b08af
            ) ""
Packit 5b08af
Packit 5b08af
-- ------------------------------------------------------------
Packit 5b08af
Packit 5b08af
pattern  :: StringLike s => (Char -> Char -> GenRegex s) -> Parser (GenRegex s)
Packit 5b08af
pattern mkS
Packit 5b08af
    = many part >>= return . mkSeqs
Packit 5b08af
    where
Packit 5b08af
      -- part :: Parser (GenRegex s)
Packit 5b08af
      part
Packit 5b08af
          = ( many1 (noneOf "\\?*[{") >>= return . mkWord' )
Packit 5b08af
            <|>
Packit 5b08af
            ( char '?' >> return mkDot )
Packit 5b08af
            <|>
Packit 5b08af
            ( char '*' >> return mkAll )
Packit 5b08af
            <|>
Packit 5b08af
            ( between (char '{') (char '}') wordList )
Packit 5b08af
            <|>
Packit 5b08af
            ( between (char '[') (char ']') charSet )
Packit 5b08af
            <|>
Packit 5b08af
            ( do c <- char '\\' >> anyChar
Packit 5b08af
                 return $ mkS c c
Packit 5b08af
            )
Packit 5b08af
      mkWord'
Packit 5b08af
          = mkSeqs . map (\ c -> mkS c c)
Packit 5b08af
Packit 5b08af
      -- wordList :: Parser (GenRegex s)
Packit 5b08af
      wordList
Packit 5b08af
          = sepBy (many1 (noneOf ",}")) (char ',')
Packit 5b08af
            >>= return . foldr mkAlt (mkZero' "") . map mkWord'
Packit 5b08af
Packit 5b08af
      -- charSet :: Parser (GenRegex s)
Packit 5b08af
      charSet
Packit 5b08af
          = ( do p1 <- charSet' anyChar
Packit 5b08af
                 ps <- many $ charSet' (noneOf "]")
Packit 5b08af
                 return $ foldr mkAlt (mkZero' "") (p1 : ps)
Packit 5b08af
            )
Packit 5b08af
          where
Packit 5b08af
            charSet' cp
Packit 5b08af
                = do c1 <- cp
Packit 5b08af
                     c2 <- rest c1
Packit 5b08af
                     return $ mkS c1 c2
Packit 5b08af
            rest c1
Packit 5b08af
                = option c1 (char '-' >> anyChar)
Packit 5b08af
Packit 5b08af
-- ------------------------------------------------------------
Packit 5b08af
Packit 5b08af
mkNoCaseSymRng :: StringLike s => Char -> Char -> GenRegex s
Packit 5b08af
mkNoCaseSymRng c1 c2
Packit 5b08af
    | isLower c1
Packit 5b08af
      &&
Packit 5b08af
      isLower c2
Packit 5b08af
          = mkAlt (mkSymRng (toUpper c1) (toUpper c2)) (mkSymRng c1 c2)
Packit 5b08af
    | isUpper c1
Packit 5b08af
      &&
Packit 5b08af
      isUpper c2
Packit 5b08af
          = mkAlt (mkSymRng (toLower c1) (toLower c2)) (mkSymRng c1 c2)
Packit 5b08af
    | otherwise
Packit 5b08af
        = mkSymRng c1 c2
Packit 5b08af
Packit 5b08af
-- ------------------------------------------------------------