├── .gitignore ├── README.md └── src ├── Main.idr ├── Prefix.idr ├── RegExp.idr ├── RegExpParser.idr ├── Search.idr ├── SmartCons.idr ├── Substring.idr └── makefile /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .DS_Store 3 | *.ibc 4 | igrep* 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A verified regular expression matching tool in Idris 2 | =================================== 3 | 4 | A formalized tool for searching using regular expression. This development is based on the article: 5 | 6 | [Regular-expression derivatives reexamined](https://www.mpi-sws.org/~turon/re-deriv.pdf) 7 | 8 | by Owens et. al. 9 | 10 | Usage 11 | ----- 12 | 13 | igrep [REGEXP] [FILE_LIST] 14 | 15 | where 16 | 17 | - REGEXP: Regular expression to be searched. 18 | - FILE_LIST: List of files to be considered for searching. 19 | 20 | 21 | Syntax of Regular Expressions 22 | ------------------------ 23 | 24 | The syntax of regular expressions is as follows: 25 | 26 | e ::= e + e 27 | | e e 28 | | e * 29 | | ( e ) 30 | | c 31 | 32 | where c is some character that isn't +, (,) and *. 33 | Note that currently the tool does not support operators like 34 | complement, intersection and the empty set. 35 | 36 | 37 | Dependencies 38 | ----------- 39 | 40 | The igrep tool depends on the following Idris libraries: 41 | 42 | - [Lightyear](https://github.com/ziman/lightyear), a parser combinator 43 | library for Idris. 44 | - [Effects](https://github.com/idris-lang/Idris-dev/tree/master/libs/effects), 45 | effectful computations in Idris. 46 | 47 | Effects library is already shipped within Idris compiler and Lightyear 48 | can be easily installed. Just download the library using the URL above 49 | and execute: 50 | 51 | make clean 52 | make test 53 | make install 54 | 55 | The development is done using Idris version 0.9.19. 56 | -------------------------------------------------------------------------------- /src/Main.idr: -------------------------------------------------------------------------------- 1 | module Main 2 | 3 | import Effects 4 | import Effect.File 5 | import Effect.StdIO 6 | import Effect.System 7 | 8 | import RegExpParser 9 | import RegExp 10 | import Substring 11 | 12 | 13 | printUsage : {[STDIO]} Eff () 14 | printUsage = putStrLn "Usage: igrep [REGEXP] [FILELIST]" 15 | 16 | 17 | search : RegExp -> String -> String 18 | search e s with (subStringDec e (map toNat (unpack s))) 19 | search e s | Yes _ = s 20 | search e s | No _ = "" 21 | 22 | 23 | readFile : { [FILE_IO (OpenFile Read)] } Eff (List String) 24 | readFile = readFile' [] 25 | where 26 | readFile' : List String -> { [FILE_IO (OpenFile Read)] } Eff (List String) 27 | readFile' acc = if (not (! eof)) then 28 | readFile' (! readLine :: acc) 29 | else pure (reverse acc) 30 | 31 | searchLines : RegExp -> { [FILE_IO (OpenFile Read)] } Eff (List String) 32 | searchLines e = do 33 | ls <- readFile 34 | pure (filter (not . isNil . unpack) (map (search e) ls)) 35 | 36 | searchFile : RegExp -> String -> {[FILE_IO ()]} Eff (List String) 37 | searchFile e f 38 | = case !(open f Read) of 39 | True => do 40 | xs <- searchLines e 41 | close 42 | return xs 43 | False => pure [] 44 | 45 | searchFiles : RegExp -> List String -> {[STDIO, FILE_IO ()]} Eff (List String) 46 | searchFiles _ [] = return [] 47 | searchFiles e (f::fs) 48 | = do 49 | r <- searchFile e f 50 | rs <- searchFiles e fs 51 | return (r ++ ["\n"] ++ rs) 52 | 53 | 54 | process : List String -> {[STDIO, FILE_IO ()]} Eff () 55 | process [] = return () 56 | process [ x ] = printUsage 57 | process (x :: e :: []) = printUsage 58 | process (x :: e :: fs) with (parse pExp e) 59 | process (x :: e :: fs) | Left err = putStrLn ("Parser error on:" ++ err) 60 | process (x :: e :: fs) | Right r 61 | = do 62 | ss <- searchFiles r fs 63 | putStrLn (concat ss) 64 | 65 | interface_ : {[STDIO, SYSTEM, FILE_IO ()]} Eff () 66 | interface_ = do 67 | putStrLn "IGrep - grep for Idris" 68 | args <- getArgs 69 | process args 70 | 71 | main : IO () 72 | main = run interface_ 73 | -------------------------------------------------------------------------------- /src/Prefix.idr: -------------------------------------------------------------------------------- 1 | module Prefix 2 | 3 | import RegExp 4 | import Search 5 | 6 | %default total 7 | %access public export 8 | 9 | 10 | -- very simple inversion lemma 11 | 12 | lemma_cons_inv : {A : Type} -> {x : A} -> {xs : List A} -> 13 | {y : A} -> {ys : List A} -> 14 | (x :: xs) = (y :: ys) -> (x = y, xs = ys) 15 | lemma_cons_inv Refl = (Refl , Refl) 16 | 17 | -- defining prefixes of a string 18 | 19 | data Prefix : (e : RegExp) -> (xs : List Nat) -> Type where 20 | MkPrefix : (ys : List Nat) -> 21 | (zs : List Nat) -> 22 | (eq : xs = ys ++ zs) -> 23 | (re : InRegExp ys e) -> 24 | Prefix e xs 25 | 26 | noPrefixNil : Not (InRegExp [] e) -> Not (Prefix e []) 27 | noPrefixNil ne (MkPrefix [] zs eq re) = ne re 28 | noPrefixNil ne (MkPrefix (x :: xs) zs eq re) = lemma_val_not_nil (sym eq) 29 | 30 | noPrefixCons : Not (InRegExp [] e) -> Not (Prefix.Prefix (deriv e x) xs) -> Not (Prefix.Prefix e (x :: xs)) 31 | noPrefixCons nnil nder (MkPrefix [] zs eq re) = nnil re 32 | noPrefixCons nnil nder (MkPrefix (y :: ys) zs eq re) with (lemma_cons_inv eq) 33 | noPrefixCons {x = y}{xs = ys ++ zs} nnil nder (MkPrefix (y :: ys) zs eq re) 34 | | (Refl , Refl) = nder (MkPrefix ys zs Refl (derivComplete re)) 35 | 36 | 37 | -- prefix decidability 38 | 39 | prefixDec : (e : RegExp) -> (xs : List Nat) -> Dec (Prefix e xs) 40 | prefixDec e [] with (hasEmptyDec e) 41 | prefixDec e [] | (Yes prf) = Yes (MkPrefix [] [] Refl prf) 42 | prefixDec e [] | (No contra) = No (noPrefixNil contra) 43 | prefixDec e (x :: xs) with (hasEmptyDec e) 44 | prefixDec e (x :: xs) | (Yes prf) = Yes (MkPrefix [] (x :: xs) Refl prf) 45 | prefixDec e (x :: xs) | (No contra) with (prefixDec (deriv e x) xs) 46 | prefixDec e (x :: xs) | (No contra) | (Yes (MkPrefix ys zs eq re)) 47 | = Yes (MkPrefix (x :: ys) zs (cong {f = (\ ks => x :: ks)} eq) (derivSound re)) 48 | prefixDec e (x :: xs) | (No contra) | (No contra1) = No (noPrefixCons contra contra1) 49 | -------------------------------------------------------------------------------- /src/RegExp.idr: -------------------------------------------------------------------------------- 1 | module RegExp 2 | 3 | %default total 4 | %access public export 5 | 6 | data RegExp : Type where 7 | Zero : RegExp 8 | Eps : RegExp 9 | Chr : Nat -> RegExp 10 | Cat : RegExp -> RegExp -> RegExp 11 | Alt : RegExp -> RegExp -> RegExp 12 | Star : RegExp -> RegExp 13 | 14 | data InRegExp : List Nat -> RegExp -> Type where 15 | InEps : InRegExp [] Eps 16 | InChr : InRegExp [ a ] (Chr a) 17 | InCat : InRegExp xs l -> 18 | InRegExp ys r -> 19 | zs = xs ++ ys -> 20 | InRegExp zs (Cat l r) 21 | InAltL : InRegExp xs l -> 22 | InRegExp xs (Alt l r) 23 | InAltR : InRegExp xs r -> 24 | InRegExp xs (Alt l r) 25 | InStar : InRegExp xs (Alt Eps (Cat e (Star e))) -> 26 | InRegExp xs (Star e) 27 | 28 | inZeroInv : InRegExp xs Zero -> Void 29 | inZeroInv InEps impossible 30 | 31 | inEpsInv : InRegExp xs Eps -> xs = [] 32 | inEpsInv InEps = Refl 33 | 34 | inEpsCons : InRegExp (x :: xs) Eps -> Void 35 | inEpsCons InEps impossible 36 | 37 | inChrNil : InRegExp [] (Chr c) -> Void 38 | inChrNil InEps impossible 39 | 40 | concatNil : Prelude.List.Nil = (xs ++ ys) -> (xs = Prelude.List.Nil , ys = Prelude.List.Nil) 41 | concatNil {xs = []}{ys = []} p = (Refl, Refl) 42 | concatNil {xs = []}{ys = (x :: xs)} p = void (lemma_val_not_nil (sym p)) 43 | concatNil {xs = (x :: xs)}{ys = ys} p = void (lemma_val_not_nil (sym p)) 44 | 45 | inCatNil : InRegExp [] (Cat e e') -> (InRegExp [] e , InRegExp [] e') 46 | inCatNil (InCat x y prf) with (concatNil prf) 47 | inCatNil (InCat x y prf) | (Refl , Refl) = (x, y) 48 | 49 | inAltNil : InRegExp [] (Alt e e') -> Either (InRegExp [] e) (InRegExp [] e') 50 | inAltNil (InAltL x) = Left x 51 | inAltNil (InAltR x) = Right x 52 | -------------------------------------------------------------------------------- /src/RegExpParser.idr: -------------------------------------------------------------------------------- 1 | module RegExpParser 2 | 3 | import public Lightyear 4 | import public Lightyear.Char 5 | import public Lightyear.Strings 6 | 7 | import RegExp 8 | import SmartCons 9 | 10 | %access public export 11 | 12 | pChar : Parser RegExp 13 | pChar = (Chr . toNat) <$> noneOf "[]()*+" 14 | 15 | pAtom : Parser RegExp 16 | pAtom = foldl1 (.@.) <$> some pChar 17 | 18 | pstar : Parser (RegExp -> RegExp) 19 | pstar = const star <$> lexeme (char '*') 20 | 21 | pPlus : Parser (RegExp -> RegExp) 22 | pPlus = const (\e => Cat e (star e)) <$> lexeme (char '+') 23 | 24 | pInBracketsChar : Parser RegExp 25 | pInBracketsChar = (Chr . toNat) <$> noneOf "[]^" 26 | 27 | pBrackets : Parser RegExp 28 | pBrackets = foldl Alt Zero <$> (brackets (many pInBracketsChar)) 29 | 30 | pStar : Parser (RegExp -> RegExp) 31 | pStar = pstar <|> pure id 32 | 33 | mutual 34 | pFactor : Parser RegExp 35 | pFactor = pBrackets <|>| pAtom <|>| (parens pExp) 36 | 37 | pTerm : Parser RegExp 38 | pTerm = f <$> pFactor <*> (pPlus <|>| pStar) 39 | where 40 | f e g = g e 41 | 42 | pExp : Parser RegExp 43 | pExp = foldl Cat Eps <$> many pTerm 44 | -------------------------------------------------------------------------------- /src/Search.idr: -------------------------------------------------------------------------------- 1 | module Search 2 | 3 | import Data.Fin 4 | import RegExp 5 | import SmartCons 6 | 7 | %default total 8 | %access public export 9 | 10 | -- emptyness test 11 | 12 | hasEmptyDec : (e : RegExp) -> Dec (InRegExp [] e) 13 | hasEmptyDec Zero = No (void . inZeroInv) 14 | hasEmptyDec Eps = Yes InEps 15 | hasEmptyDec (Chr c) = No inChrNil 16 | hasEmptyDec (Cat e e') with (hasEmptyDec e) 17 | hasEmptyDec (Cat e e') | (Yes prf) with (hasEmptyDec e') 18 | hasEmptyDec (Cat e e') | (Yes prf) | (Yes prf') = Yes (InCat prf prf' Refl) 19 | hasEmptyDec (Cat e e') | (Yes prf) | (No contra) = No (contra . snd . inCatNil) 20 | hasEmptyDec (Cat e e') | (No contra) = No (contra . fst . inCatNil) 21 | hasEmptyDec (Alt e e') with (hasEmptyDec e) 22 | hasEmptyDec (Alt e e') | (Yes prf) = Yes (InAltL prf) 23 | hasEmptyDec (Alt e e') | (No contra) with (hasEmptyDec e') 24 | hasEmptyDec (Alt e e') | (No contra) | (Yes prf) = Yes (InAltR prf) 25 | hasEmptyDec (Alt e e') | (No contra) | (No f) = No (void . either contra f . inAltNil) 26 | hasEmptyDec (Star e) = Yes (InStar (InAltL InEps)) 27 | 28 | 29 | -- derivative definition 30 | 31 | deriv : (e : RegExp) -> Nat -> RegExp 32 | deriv Zero c = Zero 33 | deriv Eps c = Zero 34 | deriv (Chr c') c with (decEq c' c) 35 | deriv (Chr c) c | Yes Refl = Eps 36 | deriv (Chr c') c | No nprf = Zero 37 | deriv (Alt l r) c = (deriv l c) .|. (deriv r c) 38 | deriv (Star e) c = (deriv e c) .@. (Star e) 39 | deriv (Cat l r) c with (hasEmptyDec l) 40 | deriv (Cat l r) c | Yes prf = ((deriv l c) .@. r) .|. (deriv r c) 41 | deriv (Cat l r) c | No nprf = (deriv l c) .@. r 42 | 43 | derivSound : InRegExp xs (deriv e x) -> InRegExp (x :: xs) e 44 | derivSound {e = (Chr c)} {x = x}{xs = xs} pr with (decEq c x) 45 | derivSound {e = (Chr c)} {x = c}{xs = []} pr | Yes Refl = InChr 46 | derivSound {e = (Chr c)} {x = c}{xs = (x :: xs)} pr | Yes Refl = void (inEpsCons pr) 47 | derivSound {e = (Chr c)} {x = x}{xs = xs} InEps | No contra impossible 48 | derivSound {e = Zero} pr = void (inZeroInv pr) 49 | derivSound {e = Eps} pr = void (inZeroInv pr) 50 | derivSound {e = (Cat e e')}{xs = xs}{x = x} pr with (hasEmptyDec e) 51 | derivSound {e = (Cat e e')}{xs = xs}{x = x} pr | (Yes prf) 52 | with (altOptSound (deriv e x .@. e') (deriv e' x) xs pr) 53 | derivSound {e = (Cat e e')}{xs = xs}{x = x} pr | (Yes prf) | (InAltL y) 54 | with (catOptSound (deriv e x) e' xs y) 55 | derivSound {e = (Cat e e')}{xs = xs}{x = x} pr | (Yes prf) | (InAltL y) | (InCat z w s) 56 | = rewrite s in InCat (derivSound z) w Refl 57 | derivSound {e = (Cat e e')}{xs = xs}{x = x} pr | (Yes prf) | (InAltR y) with (derivSound y) 58 | derivSound {e = (Cat e e')}{xs = xs}{x = x} pr | (Yes prf) | (InAltR y) | k = 59 | InCat prf k Refl 60 | derivSound {e = (Cat e e')}{xs = xs}{x = x} pr | (No contra) 61 | with (catOptSound (deriv e x) e' xs pr) 62 | derivSound {e = (Cat e e')}{xs = xs}{x = x} pr | (No contra) | (InCat y z prf) 63 | with (derivSound y) 64 | derivSound {e = (Cat e e')}{xs = xs}{x = x} pr | (No contra) | (InCat y z p) | k 65 | = rewrite p in InCat k z Refl 66 | derivSound {e = (Alt e e')}{xs = xs}{x = x} pr with (altOptSound (deriv e x) (deriv e' x) xs pr) 67 | derivSound {e = (Alt e e')}{xs = xs}{x = x} pr | (InAltL y) = InAltL (derivSound y) 68 | derivSound {e = (Alt e e')}{xs = xs}{x = x} pr | (InAltR y) = InAltR (derivSound y) 69 | derivSound {e = (Star e)}{xs = xs}{x = x} pr with (catOptSound (deriv e x) (Star e) xs pr) 70 | derivSound {e = (Star e)}{xs = xs}{x = x} pr | (InCat y z prf) with (derivSound y) 71 | derivSound {e = (Star e)}{xs = xs}{x = x} pr | (InCat y z prf) | k 72 | = rewrite prf in InStar (InAltR (InCat k z Refl)) 73 | 74 | 75 | derivComplete : InRegExp (x :: xs) e -> InRegExp xs (deriv e x) 76 | derivComplete {e = Zero}{xs = xs}{x = x} pr = void (inZeroInv pr) 77 | derivComplete {e = Eps}{xs = xs}{x = x} pr with (inEpsInv pr) 78 | derivComplete {e = Eps}{xs = xs}{x = x} pr | eq = void (lemma_val_not_nil eq) 79 | derivComplete {e = (Chr y)}{xs = xs}{x = x} pr with (decEq y x) 80 | derivComplete {e = (Chr x)}{xs = []}{x = x} InChr | (Yes Refl) = InEps 81 | derivComplete {e = (Chr x)}{xs = []}{x = x} InChr | (No contra) = void (contra Refl) 82 | derivComplete {e = (Cat y z)}{xs = xs}{x = x} pr with (hasEmptyDec y) 83 | derivComplete {e = (Cat y z)}{xs = xs}{x = x} (InCat {xs = []} w s Refl) | (Yes prf) 84 | = altOptComplete (deriv y x .@. z) (deriv z x) xs (InAltR (derivComplete s)) 85 | derivComplete {e = (Cat y z)}{xs = ys ++ ys1}{x = x} (InCat {xs = (x :: ys)}{ys = ys1} w s Refl) 86 | | (Yes prf) 87 | = altOptComplete (deriv y x .@. z) (deriv z x) _ 88 | (InAltL (catOptComplete (deriv y x) z (ys ++ ys1) 89 | (InCat (derivComplete w) s Refl))) 90 | derivComplete {e = (Cat y z)}{xs = xs}{x = x} (InCat {xs = []} w s eq) | (No contra) 91 | = void (contra w) 92 | derivComplete {e = (Cat y z)}{xs = ys ++ ys1}{x = x} (InCat {xs = (x :: ys)}{ys = ys1} w s Refl) 93 | | (No contra) 94 | = catOptComplete (deriv y x) z (ys ++ ys1) (InCat (derivComplete w) s Refl) 95 | derivComplete {e = (Alt e e')}{xs = xs}{x = x} (InAltL y) 96 | = altOptComplete (deriv e x) (deriv e' x) xs (InAltL (derivComplete y)) 97 | derivComplete {e = (Alt e e')}{xs = xs}{x = x} (InAltR y) 98 | = altOptComplete (deriv e x) (deriv e' x) xs (InAltR (derivComplete y)) 99 | derivComplete {e = (Star y)}{xs = xs}{x = x} (InStar (InAltL z)) 100 | = void (lemma_val_not_nil (inEpsInv z)) 101 | derivComplete {e = (Star y)}{xs = xs}{x = x} (InStar (InAltR (InCat {xs = []} z w Refl))) 102 | = derivComplete w 103 | derivComplete {e = (Star y)}{xs = ys ++ ys1}{x = x} (InStar (InAltR (InCat {xs = (x :: ys)}{ys = ys1} z w Refl))) 104 | = catOptComplete (deriv y x) (Star y) (ys ++ ys1) (InCat (derivComplete z) w Refl) 105 | -------------------------------------------------------------------------------- /src/SmartCons.idr: -------------------------------------------------------------------------------- 1 | module SmartCons 2 | 3 | import Data.Fin 4 | import RegExp 5 | 6 | %access public export 7 | %default total 8 | 9 | appendNilR : (xs : List a) -> xs = xs ++ [] 10 | appendNilR [] = Refl 11 | appendNilR (x :: xs) = cong (appendNilR xs) 12 | 13 | inRegLemma : InRegExp xs1 e -> xs = xs1 ++ [] -> InRegExp xs e 14 | inRegLemma {xs1} pr eq with (trans (appendNilR xs1) (sym eq)) 15 | | Refl = pr 16 | infixl 4 .|. 17 | 18 | (.|.) : RegExp -> RegExp -> RegExp 19 | Zero .|. e = e 20 | e .|. Zero = e 21 | e .|. e' = Alt e e' 22 | 23 | infixl 5 .@. 24 | 25 | (.@.) : RegExp -> RegExp -> RegExp 26 | Zero .@. e = Zero 27 | Eps .@. e = e 28 | e .@. Zero = Zero 29 | e .@. Eps = e 30 | e .@. e' = Cat e e' 31 | 32 | star : RegExp -> RegExp 33 | star Zero = Eps 34 | star Eps = Eps 35 | star e = Star e 36 | 37 | altOptSound : (l : RegExp) -> 38 | (r : RegExp) -> 39 | (xs : List Nat) -> 40 | InRegExp xs (l .|. r) -> 41 | InRegExp xs (Alt l r) 42 | altOptSound Zero r xs pr = InAltR pr 43 | altOptSound Eps Zero xs pr = InAltL pr 44 | altOptSound Eps Eps xs pr = pr 45 | altOptSound Eps (Chr x) xs pr = pr 46 | altOptSound Eps (Cat x y) xs pr = pr 47 | altOptSound Eps (Alt x y) xs pr = pr 48 | altOptSound Eps (Star x) xs pr = pr 49 | altOptSound (Chr x) Zero xs pr = InAltL pr 50 | altOptSound (Chr x) Eps xs pr = pr 51 | altOptSound (Chr x) (Chr y) xs pr = pr 52 | altOptSound (Chr x) (Cat y z) xs pr = pr 53 | altOptSound (Chr x) (Alt y z) xs pr = pr 54 | altOptSound (Chr x) (Star y) xs pr = pr 55 | altOptSound (Cat x y) Zero xs pr = InAltL pr 56 | altOptSound (Cat x y) Eps xs pr = pr 57 | altOptSound (Cat x y) (Chr z) xs pr = pr 58 | altOptSound (Cat x y) (Cat z w) xs pr = pr 59 | altOptSound (Cat x y) (Alt z w) xs pr = pr 60 | altOptSound (Cat x y) (Star z) xs pr = pr 61 | altOptSound (Alt x y) Zero xs pr = InAltL pr 62 | altOptSound (Alt x y) Eps xs pr = pr 63 | altOptSound (Alt x y) (Chr z) xs pr = pr 64 | altOptSound (Alt x y) (Cat z w) xs pr = pr 65 | altOptSound (Alt x y) (Alt z w) xs pr = pr 66 | altOptSound (Alt x y) (Star z) xs pr = pr 67 | altOptSound (Star x) Zero xs pr = InAltL pr 68 | altOptSound (Star x) Eps xs pr = pr 69 | altOptSound (Star x) (Chr y) xs pr = pr 70 | altOptSound (Star x) (Cat y z) xs pr = pr 71 | altOptSound (Star x) (Alt y z) xs pr = pr 72 | altOptSound (Star x) (Star y) xs pr = pr 73 | 74 | altOptComplete : (l : RegExp) -> 75 | (r : RegExp) -> 76 | (xs : List Nat) -> 77 | InRegExp xs (Alt l r) -> 78 | InRegExp xs (l .|. r) 79 | altOptComplete Zero r xs (InAltL x) = void (inZeroInv x) 80 | altOptComplete Zero r xs (InAltR x) = x 81 | altOptComplete Eps Zero xs (InAltL x) = x 82 | altOptComplete Eps Zero xs (InAltR x) = void (inZeroInv x) 83 | altOptComplete Eps Eps xs pr = pr 84 | altOptComplete Eps (Chr x) xs pr = pr 85 | altOptComplete Eps (Cat x y) xs pr = pr 86 | altOptComplete Eps (Alt x y) xs pr = pr 87 | altOptComplete Eps (Star x) xs pr = pr 88 | altOptComplete (Chr x) Zero xs (InAltL y) = y 89 | altOptComplete (Chr x) Zero xs (InAltR y) = void (inZeroInv y) 90 | altOptComplete (Chr x) Eps xs pr = pr 91 | altOptComplete (Chr x) (Chr y) xs pr = pr 92 | altOptComplete (Chr x) (Cat y z) xs pr = pr 93 | altOptComplete (Chr x) (Alt y z) xs pr = pr 94 | altOptComplete (Chr x) (Star y) xs pr = pr 95 | altOptComplete (Cat x y) Zero xs (InAltL z) = z 96 | altOptComplete (Cat x y) Zero xs (InAltR z) = void (inZeroInv z) 97 | altOptComplete (Cat x y) Eps xs pr = pr 98 | altOptComplete (Cat x y) (Chr z) xs pr = pr 99 | altOptComplete (Cat x y) (Cat z w) xs pr = pr 100 | altOptComplete (Cat x y) (Alt z w) xs pr = pr 101 | altOptComplete (Cat x y) (Star z) xs pr = pr 102 | altOptComplete (Alt x y) Zero xs (InAltL z) = z 103 | altOptComplete (Alt x y) Zero xs (InAltR z) = void (inZeroInv z) 104 | altOptComplete (Alt x y) Eps xs pr = pr 105 | altOptComplete (Alt x y) (Chr z) xs pr = pr 106 | altOptComplete (Alt x y) (Cat z w) xs pr = pr 107 | altOptComplete (Alt x y) (Alt z w) xs pr = pr 108 | altOptComplete (Alt x y) (Star z) xs pr = pr 109 | altOptComplete (Star x) Zero xs (InAltL y) = y 110 | altOptComplete (Star x) Zero xs (InAltR y) = void (inZeroInv y) 111 | altOptComplete (Star x) Eps xs pr = pr 112 | altOptComplete (Star x) (Chr y) xs pr = pr 113 | altOptComplete (Star x) (Cat y z) xs pr = pr 114 | altOptComplete (Star x) (Alt y z) xs pr = pr 115 | altOptComplete (Star x) (Star y) xs pr = pr 116 | 117 | catOptSound : (l : RegExp) -> 118 | (r : RegExp) -> 119 | (xs : List Nat) -> 120 | InRegExp xs (l .@. r) -> 121 | InRegExp xs (Cat l r) 122 | catOptSound Zero r xs pr = void (inZeroInv pr) 123 | catOptSound Eps r xs pr = InCat InEps pr Refl 124 | catOptSound (Chr x) Zero xs pr = void (inZeroInv pr) 125 | catOptSound (Chr x) Eps xs pr = InCat pr InEps (appendNilR xs) 126 | catOptSound (Chr x) (Chr y) xs pr = pr 127 | catOptSound (Chr x) (Cat y z) xs pr = pr 128 | catOptSound (Chr x) (Alt y z) xs pr = pr 129 | catOptSound (Chr x) (Star y) xs pr = pr 130 | catOptSound (Cat x y) Zero xs pr = void (inZeroInv pr) 131 | catOptSound (Cat x y) Eps xs pr = InCat pr InEps (appendNilR xs) 132 | catOptSound (Cat x y) (Chr z) xs pr = pr 133 | catOptSound (Cat x y) (Cat z w) xs pr = pr 134 | catOptSound (Cat x y) (Alt z w) xs pr = pr 135 | catOptSound (Cat x y) (Star z) xs pr = pr 136 | catOptSound (Alt x y) Zero xs pr = void (inZeroInv pr) 137 | catOptSound (Alt x y) Eps xs pr = InCat pr InEps (appendNilR xs) 138 | catOptSound (Alt x y) (Chr z) xs pr = pr 139 | catOptSound (Alt x y) (Cat z w) xs pr = pr 140 | catOptSound (Alt x y) (Alt z w) xs pr = pr 141 | catOptSound (Alt x y) (Star z) xs pr = pr 142 | catOptSound (Star x) Zero xs pr = void (inZeroInv pr) 143 | catOptSound (Star x) Eps xs pr = InCat pr InEps (appendNilR xs) 144 | catOptSound (Star x) (Chr y) xs pr = pr 145 | catOptSound (Star x) (Cat y z) xs pr = pr 146 | catOptSound (Star x) (Alt y z) xs pr = pr 147 | catOptSound (Star x) (Star y) xs pr = pr 148 | 149 | 150 | catOptComplete : (l : RegExp) -> 151 | (r : RegExp) -> 152 | (xs : List Nat) -> 153 | InRegExp xs (Cat l r) -> 154 | InRegExp xs (l .@. r) 155 | catOptComplete Zero r xs (InCat x y prf) = void (inZeroInv x) 156 | catOptComplete Eps r xs (InCat InEps y Refl) = y 157 | catOptComplete (Chr x) Zero xs (InCat y z prf) = void (inZeroInv z) 158 | catOptComplete (Chr x) Eps xs (InCat y InEps prf) = inRegLemma y prf 159 | catOptComplete (Chr x) (Chr y) xs pr = pr 160 | catOptComplete (Chr x) (Cat y z) xs pr = pr 161 | catOptComplete (Chr x) (Alt y z) xs pr = pr 162 | catOptComplete (Chr x) (Star y) xs pr = pr 163 | catOptComplete (Cat x y) Zero xs (InCat z w prf) = void (inZeroInv w) 164 | catOptComplete (Cat x y) Eps xs (InCat z InEps prf) = inRegLemma z prf 165 | catOptComplete (Cat x y) (Chr z) xs pr = pr 166 | catOptComplete (Cat x y) (Cat z w) xs pr = pr 167 | catOptComplete (Cat x y) (Alt z w) xs pr = pr 168 | catOptComplete (Cat x y) (Star z) xs pr = pr 169 | catOptComplete (Alt x y) Zero xs (InCat z w prf) = void (inZeroInv w) 170 | catOptComplete (Alt x y) Eps xs (InCat z InEps prf) = inRegLemma z prf 171 | catOptComplete (Alt x y) (Chr z) xs pr = pr 172 | catOptComplete (Alt x y) (Cat z w) xs pr = pr 173 | catOptComplete (Alt x y) (Alt z w) xs pr = pr 174 | catOptComplete (Alt x y) (Star z) xs pr = pr 175 | catOptComplete (Star x) Zero xs (InCat y z prf) = void (inZeroInv z) 176 | catOptComplete (Star x) Eps xs (InCat y InEps prf) = inRegLemma y prf 177 | catOptComplete (Star x) (Chr y) xs pr = pr 178 | catOptComplete (Star x) (Cat y z) xs pr = pr 179 | catOptComplete (Star x) (Alt y z) xs pr = pr 180 | catOptComplete (Star x) (Star y) xs pr = pr 181 | 182 | starOptSound : (l : RegExp) -> 183 | (xs : List Nat) -> 184 | InRegExp xs (star l) -> 185 | InRegExp xs (Star l) 186 | starOptSound Zero xs pr = InStar (InAltL pr) 187 | starOptSound Eps xs pr = InStar (InAltL pr) 188 | starOptSound (Chr x) xs pr = pr 189 | starOptSound (Cat x y) xs pr = pr 190 | starOptSound (Alt x y) xs pr = pr 191 | starOptSound (Star x) xs pr = pr 192 | 193 | starOptComplete : (l : RegExp) -> 194 | (xs : List Nat) -> 195 | InRegExp xs (Star l) -> 196 | InRegExp xs (star l) 197 | starOptComplete Zero xs (InStar (InAltL x)) = x 198 | starOptComplete Zero xs (InStar (InAltR (InCat x y prf))) = void (inZeroInv x) 199 | starOptComplete Eps xs (InStar (InAltL x)) = x 200 | starOptComplete Eps xs (InStar (InAltR (InCat InEps y Refl))) = starOptComplete _ xs y 201 | starOptComplete (Chr x) xs pr = pr 202 | starOptComplete (Cat x y) xs pr = pr 203 | starOptComplete (Alt x y) xs pr = pr 204 | starOptComplete (Star x) xs pr = pr 205 | -------------------------------------------------------------------------------- /src/Substring.idr: -------------------------------------------------------------------------------- 1 | module Substring 2 | 3 | import Prefix 4 | import RegExp 5 | import Search 6 | import SmartCons 7 | 8 | %default total 9 | %access public export 10 | 11 | 12 | data Substring : (e : RegExp) -> (xs : List Nat) -> Type where 13 | MkSubstring : (ys : List Nat) -> 14 | (ts : List Nat) -> 15 | (zs : List Nat) -> 16 | (eq : xs = ys ++ ts ++ zs) -> 17 | (re : InRegExp ts e) -> 18 | Substring e xs 19 | 20 | noSubstringNil : Not (Prefix e []) -> Not (Substring e []) 21 | noSubstringNil npre (MkSubstring [] ts zs eq re) = npre (MkPrefix ts zs eq re) 22 | noSubstringNil npre (MkSubstring (y :: ys) ts zs eq re) = lemma_val_not_nil (sym eq) 23 | 24 | noSubstringCons : Not (Prefix e (x :: xs)) -> 25 | Not (Substring e xs) -> 26 | Not (Substring e (x :: xs)) 27 | noSubstringCons npre nsub (MkSubstring [] ts zs eq re) = npre (MkPrefix ts zs eq re) 28 | noSubstringCons npre nsub (MkSubstring (y :: ys) ts zs eq re) with (lemma_cons_inv eq) 29 | noSubstringCons npre nsub (MkSubstring (y :: ys) ts zs eq re) | (Refl, Refl) 30 | = nsub (MkSubstring ys ts zs Refl re) 31 | 32 | subStringDec : (e : RegExp) -> (xs : List Nat) -> Dec (Substring e xs) 33 | subStringDec e [] with (hasEmptyDec e) 34 | subStringDec e [] | (Yes prf) = Yes (MkSubstring [] [] [] Refl prf) 35 | subStringDec e [] | (No contra) = No (noSubstringNil (noPrefixNil contra)) 36 | subStringDec e (x :: xs) with (prefixDec e (x :: xs)) 37 | subStringDec e (x :: xs) | (Yes (MkPrefix ys zs eq re)) = Yes (MkSubstring [] ys zs eq re) 38 | subStringDec e (x :: xs) | (No contra) with (subStringDec e xs) 39 | subStringDec e (x :: xs) | (No contra) | (Yes (MkSubstring ys ts zs eq re)) 40 | = Yes (MkSubstring (x :: ys) ts zs (cong eq) re) 41 | subStringDec e (x :: xs) | (No contra) | (No contra1) = No (noSubstringCons contra contra1) 42 | -------------------------------------------------------------------------------- /src/makefile: -------------------------------------------------------------------------------- 1 | default: all 2 | 3 | all: clean 4 | idris -o igrep Main.idr -p effects -p lightyear 5 | 6 | clean: 7 | -rm igrep 8 | -rm *.ibc 9 | --------------------------------------------------------------------------------