summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJed Barber <jjbarber@y7mail.com>2012-05-07 18:07:08 +1000
committerJed Barber <jjbarber@y7mail.com>2012-05-07 18:07:08 +1000
commit5fb30184c733023f20578fa81077e7a7727a410d (patch)
tree974dddf260c25b15439e65b355cc08a54dd8d609
parent2a59df3e6ea1adcbf7fac96be4ec280869132896 (diff)
Initial source
-rw-r--r--Semantic.hs510
-rw-r--r--Syntactic.hs87
2 files changed, 597 insertions, 0 deletions
diff --git a/Semantic.hs b/Semantic.hs
new file mode 100644
index 0000000..79b03d0
--- /dev/null
+++ b/Semantic.hs
@@ -0,0 +1,510 @@
+import Control.Monad( liftM )
+import System( getArgs )
+import Data.List
+
+
+data Object = ObjNum { objNum :: Number }
+ | ObjName { objName :: Name }
+ | ObjList { objList :: List }
+ | ObjTyOp { objTyOp :: TypeOp }
+ | ObjType { objType :: Type }
+ | ObjConst { objConst :: Const }
+ | ObjVar { objVar :: Var }
+ | ObjTerm { objTerm :: Term }
+ | ObjThm { objThm :: Theorem }
+ | ObjSub { objSub :: Substitution } deriving (Eq)
+
+type Number = Int
+
+data Name = Name { nameSpace :: [String]
+ , nameId :: String } deriving (Eq)
+
+type List = [Object]
+
+data TypeOp = TypeOp { tyOp :: Name } deriving (Eq)
+
+data Type = TypeVar { typeVar :: Name }
+ | AType { aType :: [Type]
+ , aTypeOp :: TypeOp } deriving (Eq)
+
+data Const = Const { constName :: Name } deriving (Eq)
+
+data Var = Var { varName :: Name
+ , varTy :: Type } deriving (Eq)
+
+data Term = TVar { tVar :: Var }
+ | TConst { tConst :: Const
+ , tConstType :: Type }
+ | TApp { tAppLeft :: Term
+ , tAppRight :: Term }
+ | TAbs { tAbsVar :: Term
+ , tAbsTerm :: Term }
+
+data Theorem = Theorem { thmHyp :: [Term]
+ , thmCon :: Term } deriving (Eq)
+
+
+instance Eq Term where
+ a == b = a `alphaEquiv` b
+
+
+type Stack = [Object]
+type Dictionary = [(Int,Object)]
+type Assumptions = [Object]
+type Theorems = [Object]
+
+
+type Substitution = ([(Type,Type)],[(Var,Term)])
+
+
+data ArticleLine = Comment { commentString :: String }
+ | Command { commandFunc :: ((Stack,Dictionary,Assumptions,Theorems)->(Stack,Dictionary,Assumptions,Theorems)) }
+
+
+
+parse :: String -> ArticleLine
+parse "absTerm" = Command absTerm
+parse "absThm" = Command absThm
+parse "appTerm" = Command appTerm
+parse "appThm" = Command appThm
+parse "assume" = Command assume
+parse "axiom" = Command axiom
+parse "betaConv" = Command betaConv
+parse "cons" = Command cons
+parse "const" = Command constant
+parse "constTerm" = Command constTerm
+parse "deductAntisym" = Command deductAntisym
+parse "def" = Command def
+parse "defineConst" = Command defineConst
+parse "defineTypeOp" = Command defineTypeOp
+parse "eqMp" = Command eqMp
+parse "nil" = Command nil
+parse "opType" = Command opType
+parse "pop" = Command pop
+parse "ref" = Command ref
+parse "refl" = Command refl
+parse "remove" = Command remove
+parse "subst" = Command subst
+parse "thm" = Command thm
+parse "typeOp" = Command typeOp
+parse "var" = Command var
+parse "varTerm" = Command varTerm
+parse "varType" = Command varType
+parse s@('#':rest) = Comment s
+parse s@('"':rest) = Command (name s)
+parse n = Command (number n)
+
+
+
+name :: String -> ((Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems))
+name str = \(stack,d,a,t) -> (ObjName (Name [] str) : stack, d, a, t)
+
+
+number :: String -> ((Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems))
+number n = \(stack,d,a,t) -> (ObjNum (read n) : stack, d, a, t)
+
+
+absTerm :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+absTerm (stack,d,a,t) =
+ let op = (\x y -> TAbs (TVar y) x)
+ newTerm = ObjTerm $ op (objTerm $ stack!!0) (objVar $ stack!!1)
+ stack' = newTerm : (drop 2 stack)
+ in (stack',d,a,t)
+
+
+-- need to add guards to check that the variable is not free in the hypothesis
+absThm :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+absThm (stack,d,a,t) =
+ let op = (\x y -> Theorem (thmHyp x)
+ (mkEquals (TAbs (TVar y) (getlhs . thmCon $ x))
+ (TAbs (TVar y) (getrhs . thmCon $ x))))
+ theorem = ObjThm (op (objThm $ stack!!0) (objVar $ stack!!1))
+ stack' = theorem : (drop 2 stack)
+ in (stack',d,a,t)
+
+
+appTerm :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+appTerm (stack,d,a,t) =
+ let op = (\x y -> TApp y x)
+ newTerm = ObjTerm $ op (objTerm $ stack!!0) (objTerm $ stack!!1)
+ stack' = newTerm : (drop 2 stack)
+ in (stack',d,a,t)
+
+
+appThm :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+appThm (stack,d,a,t) =
+ let op = (\x y -> Theorem (union (thmHyp x) (thmHyp y))
+ (mkEquals (TApp (getlhs . thmCon $ y) (getlhs . thmCon $ x))
+ (TApp (getrhs . thmCon $ y) (getrhs . thmCon $ x))))
+ theorem = ObjThm $ op (objThm $ stack!!0) (objThm $ stack!!1)
+ stack' = theorem : (drop 2 stack)
+ in (stack',d,a,t)
+
+
+assume :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+assume (stack,d,a,t) =
+ let op = (\x -> Theorem [x] x)
+ theorem = ObjThm $ op (objTerm $ stack!!0)
+ stack' = theorem : (tail stack)
+ in (stack',d,a,t)
+
+
+-- need to add guarding for all terms being of type bool
+axiom :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+axiom (stack,d,assumptions,t) =
+ let op = (\x y -> Theorem y x)
+ theorem = ObjThm $ op (objTerm $ stack!!0) (map (objTerm) . objList $ stack!!1)
+ stack' = theorem : (drop 2 stack)
+ assumptions' = theorem : assumptions
+ in (stack', d, assumptions', t)
+
+
+betaConv :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+betaConv (stack,d,a,t) =
+ let op = (\x -> Theorem [] (mkEquals x
+ (substitute ([], [(tVar . tAbsVar . tAppLeft $ x, tAppRight $ x)])
+ (tAbsTerm . tAppLeft $ x))))
+ theorem = ObjThm $ op (objTerm $ stack!!0)
+ stack' = theorem : (tail stack)
+ in (stack',d,a,t)
+
+
+cons :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+cons (stack,d,a,t) =
+ let op = (\x y -> y : x)
+ newList = ObjList $ op (objList $ stack!!0) (stack!!1)
+ stack' = newList : (drop 2 stack)
+ in (stack',d,a,t)
+
+
+constant :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+constant (stack,d,a,t) =
+ let op = (\x -> Const x)
+ constant = ObjConst $ op (objName $ stack!!0)
+ stack' = constant : (tail stack)
+ in (stack',d,a,t)
+
+
+constTerm :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+constTerm (stack,d,a,t) =
+ let op = (\x y -> TConst y x)
+ newType = ObjTerm $ op (objType $ stack!!0) (objConst $ stack!!1)
+ stack' = newType : (drop 2 stack)
+ in (stack',d,a,t)
+
+
+deductAntisym :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+deductAntisym (stack,d,a,t) =
+ let op = (\x y -> Theorem (union ((thmHyp $ y) \\ [(thmCon $ x)])
+ ((thmHyp $ x) \\ [(thmCon $ y)]))
+ (mkEquals (thmCon $ y) (thmCon $ x)))
+ theorem = ObjThm $ op (objThm $ stack!!0) (objThm $ stack!!1)
+ stack' = theorem : (drop 2 stack)
+ in (stack',d,a,t)
+
+
+def :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+def (stack,dictionary,a,t) =
+ let newEntry = ((objNum $ stack!!0), (stack!!1))
+ cleanDict = filter ((/=) (objNum $ stack!!0) . fst) dictionary
+ dictionary' = newEntry : cleanDict
+ stack' = tail stack
+ in (stack',dictionary',a,t)
+
+
+defineConst :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+defineConst (stack,d,a,t) =
+ let op1 = (\x -> Const x)
+ op2 = (\x y -> Theorem [] (mkEquals x y))
+ constant = ObjConst $ op1 (objName $ stack!!1)
+ constTerm = TConst (objConst $ constant) (typeOf (objTerm $ stack!!0))
+ theorem = ObjThm $ op2 constTerm (objTerm $ stack!!0)
+ stack' = theorem : constant : (drop 2 stack)
+ in (stack',d,a,t)
+
+
+defineTypeOp :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+defineTypeOp (stack,d,a,t) =
+ let oldthm = objThm $ stack!!0
+ namelist = map (objName) . objList $ stack!!1
+ rep = Const . objName $ stack!!2
+ abst = Const . objName $ stack!!3
+ n = TypeOp . objName $ stack!!4
+ rtype = typeOf . tAppRight . thmCon $ oldthm
+ atype = AType (map (\x -> TypeVar x) namelist) n
+ r' = TVar (Var (Name [] "r'") rtype)
+ a' = TVar (Var (Name [] "a'") atype)
+ reptype = typeFunc atype rtype
+ abstype = typeFunc rtype atype
+ repTerm = TConst rep reptype
+ absTerm = TConst abst abstype
+ rthm = Theorem [] (mkEquals (TApp (tAppLeft . thmCon $ oldthm) r')
+ (mkEquals (TApp repTerm (TApp absTerm r')) r'))
+ athm = Theorem [] (mkEquals (TApp absTerm (TApp repTerm a')) a')
+ stack' = (ObjThm rthm) : (ObjThm athm) : (ObjConst rep) : (ObjConst abst) : (ObjTyOp n) : (drop 5 stack)
+ in (stack',d,a,t)
+
+
+eqMp :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+eqMp (stack,d,a,t) =
+ let op = (\x y -> if (thmCon x == (getlhs (thmCon y))) then
+ Theorem (union (thmHyp x) (thmHyp y))
+ (getrhs (thmCon y))
+ else error "Theorem consequents not alpha equivalent in eqMp")
+ theorem = ObjThm $ op (objThm $ stack!!0) (objThm $ stack!!1)
+ stack' = theorem : (drop 2 stack)
+ in (stack',d,a,t)
+
+
+nil :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+nil (stack,d,a,t) = (ObjList [] : stack, d, a, t)
+
+
+opType :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+opType (stack,d,a,t) =
+ let op = (\x y -> AType x y)
+ newType = ObjType $ op (map (objType) . objList $ stack!!0) (objTyOp $ stack!!1)
+ stack' = newType : (drop 2 stack)
+ in (stack',d,a,t)
+
+
+pop :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+pop (stack,d,a,t) = (tail stack,d,a,t)
+
+
+ref :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+ref (stack,dictionary,a,t) =
+ let entry = filter (((==) (objNum $ stack!!0)) . fst) $ dictionary
+ object = snd . head $ entry
+ stack' = object : tail stack
+ in (stack',dictionary,a,t)
+
+
+refl :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+refl (stack,d,a,t) =
+ let op = (\x -> Theorem [] (mkEquals x x))
+ theorem = ObjThm $ op (objTerm $ stack!!0)
+ stack' = theorem : (tail stack)
+ in (stack',d,a,t)
+
+
+remove :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+remove (stack,dictionary,a,t) =
+ let entry = filter (((==) (objNum $ stack!!0)) . fst) $ dictionary
+ object = snd . head $ entry
+ stack' = object : tail stack
+ dictionary' = dictionary \\ entry
+ in (stack',dictionary',a,t)
+
+
+subst :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+subst (stack,d,a,t) =
+ let op = (\x y -> Theorem (map (substitute y) (thmHyp x))
+ (substitute y (thmCon x)))
+ theorem = ObjThm $ op (objThm $ stack!!0) (objSub $ stack!!1)
+ stack' = theorem : (drop 2 stack)
+ in (stack',d,a,t)
+
+
+thm :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+thm (stack,d,a,theorems) =
+ let op = (\x y z -> Theorem (alphaConvertList (thmHyp z) y)
+ (alphaConvert (thmCon z) x))
+ theorem = ObjThm $ op (objTerm $ stack!!0) (map (objTerm) . objList $ stack!!1) (objThm $ stack!!2)
+ stack' = drop 3 stack
+ theorems' = union theorems [theorem]
+ in (stack', d, a, theorems')
+
+
+typeOp :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+typeOp (stack,d,a,t) =
+ let op = (\x -> TypeOp x)
+ typeOp = ObjTyOp $ op (objName $ stack!!0)
+ stack' = typeOp : (tail stack)
+ in (stack',d,a,t)
+
+
+var :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+var (stack,d,a,t) =
+ let op = (\x y -> Var y x)
+ var = ObjVar $ op (objType $ stack!!0) (objName $ stack!!1)
+ stack' = var : (drop 2 stack)
+ in (stack',d,a,t)
+
+
+varTerm :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+varTerm (stack,d,a,t) =
+ let op = (\x -> TVar x)
+ term = ObjTerm $ op (objVar $ stack!!0)
+ stack' = term : (tail stack)
+ in (stack',d,a,t)
+
+
+varType :: (Stack,Dictionary,Assumptions,Theorems) -> (Stack,Dictionary,Assumptions,Theorems)
+varType (stack,d,a,t) =
+ let op = (\x -> TypeVar x)
+ newType = ObjType $ op (objName $ stack!!0)
+ stack' = newType : (tail stack)
+ in (stack',d,a,t)
+
+
+
+
+alphaEquiv :: Term -> Term -> Bool
+alphaEquiv a b =
+ let equiv = \term1 term2 var1 var2 ->
+ case (term1,term2,var1,var2) of
+ (TConst a1 b1, TConst a2 b2, _, _) ->
+ a1 == a2 &&
+ b1 == b2
+ (TApp a1 b1, TApp a2 b2, v1, v2) ->
+ equiv a1 a2 v1 v2 &&
+ equiv b1 b2 v1 v2
+ (TAbs (TVar (Var n1 t1)) b1, TAbs (TVar (Var n2 t2)) b2, v1, v2) ->
+ t1 == t2 &&
+ equiv b1 b2 (Var n1 t1) (Var n2 t2) &&
+ equiv b1 b2 v1 v2
+ (TVar a1, TVar a2, v1, v2) ->
+ a1 == a2 ||
+ (a1 == v1 && a2 == v2)
+ (_, _, _, _) ->
+ False
+ dummy = Var (Name [] "") (TypeVar (Name [] ""))
+ in equiv a b dummy dummy
+
+
+alphaConvert :: Term -> Term -> Term
+alphaConvert (TConst a ty) (TConst _ _) = TConst a ty
+alphaConvert (TApp a1 b1) (TApp a2 b2) = TApp (alphaConvert a1 a2) (alphaConvert b1 b2)
+alphaConvert (TVar v) (TVar _) = TVar v
+alphaConvert (TAbs v1 a) (TAbs v2 b) = substitute ([],[(tVar v1,v2)]) (TAbs v1 (alphaConvert a b))
+
+
+alphaConvertList :: [Term] -> [Term] -> [Term]
+alphaConvertList a b = map (\x -> alphaConvert (fst x) (snd x)) (zip a b)
+
+
+substitute :: Substitution -> Term -> Term
+substitute (tymap,vmap) term =
+ let typesub =
+ (\x y ->
+ case y of
+ (TConst a ty) -> if (ty == fst x)
+ then TConst a (snd x)
+ else TConst a ty
+ (TApp a b) -> TApp (typesub x a) (typesub x b)
+ (TAbs v a) -> TAbs v (typesub x a)
+ (TVar v) -> TVar v)
+ varsub =
+ (\x y ->
+ case y of
+ (TConst a ty) -> TConst a ty
+ (TApp a b) -> TApp (varsub x a) (varsub x b)
+ (TVar v) -> if (v == fst x)
+ then snd x
+ else TVar v
+ (TAbs v a) -> let safe = rename (TAbs v a) (union [(fst x)] (containsVars (snd x)))
+ in case safe of
+ (TAbs m n) -> TAbs m (varsub x n))
+ tydone = foldl' (\x y -> typesub y x) term tymap
+ vdone = foldl' (\x y -> varsub y x) tydone vmap
+ in vdone
+
+
+containsVars :: Term -> [Var]
+containsVars t =
+ let f = (\term list ->
+ case term of
+ (TConst a b) -> list
+ (TApp a b) -> union list ((f a list) ++ (f b list))
+ (TVar a) -> union list [a]
+ (TAbs a b) -> union list ([tVar a] ++ (f b list)))
+ in f t []
+
+
+rename :: Term -> [Var] -> Term
+rename (TAbs (TVar v) t) varlist =
+ let doRename =
+ (\x y z -> case x of
+ (TAbs (TVar a) b) -> if (a == y)
+ then TAbs (TVar z) (doRename b y z)
+ else TAbs (TVar a) (doRename b y z)
+ (TConst a b) -> TConst a b
+ (TApp a b) -> TApp (doRename a y z) (doRename b y z)
+ (TVar a) -> if (a == y)
+ then TVar z
+ else TVar a)
+ findSafe =
+ (\x y -> if (x `elem` y)
+ then case x of
+ (Var a b) ->
+ case a of
+ (Name c d) -> findSafe (Var (Name c (d ++ "'")) b) y
+ else x)
+ in if (v `elem` varlist)
+ then doRename (TAbs (TVar v) t) v (findSafe v varlist)
+ else TAbs (TVar v) t
+
+
+
+
+typeOf :: Term -> Type
+typeOf (TConst c ty) = ty
+
+
+mkEquals :: Term -> Term -> Term
+mkEquals lhs rhs =
+ let eqConst = TConst (Const (Name [] "=")) (mkEqualsType (typeOf lhs))
+ in TApp (TApp eqConst lhs) rhs
+
+
+mkEqualsType :: Type -> Type
+mkEqualsType ty = typeFunc (AType [] (TypeOp (Name [] "bool"))) (typeFunc ty ty)
+
+
+getlhs :: Term -> Term
+getlhs (TApp (TApp eq lhs) _) =
+ if (isEq eq) then lhs else error "Tried to get lhs from a non-eq term"
+
+
+getrhs :: Term -> Term
+getrhs (TApp (TApp eq _) rhs) =
+ if (isEq eq) then rhs else error "Tried to get rhs from a non-eq term"
+
+
+isEq :: Term -> Bool
+isEq (TApp (TApp (TConst (Const (Name [] "=")) _) _) _) = True
+isEq _ = False
+
+
+typeFunc :: Type -> Type -> Type
+typeFunc ty1 ty2 = AType [ty1,ty2] (TypeOp (Name [] "->"))
+
+
+
+
+doSemanticCheck :: [String] -> (Stack,Dictionary,Assumptions,Theorems)
+doSemanticCheck =
+ let s = [] :: Stack
+ d = [] :: Dictionary
+ a = [] :: Assumptions
+ t = [] :: Theorems
+ op = (\x y -> case y of (Comment _) -> x
+ (Command z) -> z x)
+ in (foldl' (op) (s,d,a,t)) . (map (parse))
+ -- important to use foldl here so commands get applied in the correct order
+
+
+getLines :: FilePath -> IO [String]
+getLines = liftM lines . readFile
+
+
+stripReturn :: String -> String
+stripReturn s = if (last s == '\r') then init s else s
+
+
+main = do
+ args <- getArgs
+ list <- getLines $ head args
+ result <- return $ doSemanticCheck (map (stripReturn) list)
+ print $ "Result OK"
diff --git a/Syntactic.hs b/Syntactic.hs
new file mode 100644
index 0000000..0abff0f
--- /dev/null
+++ b/Syntactic.hs
@@ -0,0 +1,87 @@
+import Control.Monad( liftM )
+import System( getArgs )
+import Text.Printf
+
+
+getLines :: FilePath -> IO [String]
+getLines = liftM lines . readFile
+
+
+stripReturn :: String -> String
+stripReturn s = if (last s == '\r') then init s else s
+
+
+isComment :: String -> Bool
+isComment = (==) '#' . head
+
+
+isNumber :: String -> Bool
+isNumber ('0':[]) = True
+isNumber ('-':ns)
+ | ns /= [] && head ns /= '0' = isNumber ns
+isNumber n = null . filter (not . isDigit) $ n
+
+
+isDigit :: Char -> Bool
+isDigit '0' = True
+isDigit '1' = True
+isDigit '2' = True
+isDigit '3' = True
+isDigit '4' = True
+isDigit '5' = True
+isDigit '6' = True
+isDigit '7' = True
+isDigit '8' = True
+isDigit '9' = True
+isDigit _ = False
+
+
+isName :: String -> Bool
+isName s = foldr (&&) True $ map ((==) '"') $ [head s, last s]
+
+
+scan :: String -> String
+scan s = if (s == "absTerm" ||
+ s == "absThm" ||
+ s == "appTerm" ||
+ s == "appThm" ||
+ s == "assume" ||
+ s == "axiom" ||
+ s == "betaConv" ||
+ s == "cons" ||
+ s == "const" ||
+ s == "constTerm" ||
+ s == "deductAntisym" ||
+ s == "def" ||
+ s == "defineConst" ||
+ s == "defineTypeOp" ||
+ s == "eqMp" ||
+ s == "nil" ||
+ s == "opType" ||
+ s == "pop" ||
+ s == "ref" ||
+ s == "refl" ||
+ s == "remove" ||
+ s == "subst" ||
+ s == "thm" ||
+ s == "typeOp" ||
+ s == "var" ||
+ s == "varTerm" ||
+ s == "varType" ||
+ isComment(s) ||
+ isNumber(s) ||
+ isName(s))
+ then s
+ else error $ "Invalid input " ++ s
+
+
+doScan :: [String] -> [String]
+doScan = map (scan . stripReturn)
+
+
+main = do
+ args <- getArgs
+ list <- getLines $ head args
+ plist <- return $ doScan list
+ printf $ if (list == plist) then "Scan OK\n" else "Syntax error\n"
+