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