X-Git-Url: http://git.tomasm.cz/fp.git/blobdiff_plain/880eb9d73e5ea9239698d8f6d294032b6e339310..28fcab78ad1b6c3f56708f38fbc74457ae36479a:/src/HM/Parser.hs?ds=inline diff --git a/src/HM/Parser.hs b/src/HM/Parser.hs index f02a7cc..47c4649 100644 --- a/src/HM/Parser.hs +++ b/src/HM/Parser.hs @@ -23,6 +23,16 @@ import Control.Applicative import HM.Term +-- $setup +-- >>> import Test.QuickCheck +-- >>> import Test.HM.Term + +-- | +-- >>> print $ Lam "x" (Var "x") +-- (λx.x) + + + braced :: String -> String braced t = "(" ++ t ++ ")" @@ -58,39 +68,34 @@ parseTerm = parseLet <|> parseVar <|> parseLambda -parseTermNA :: Parser Term -parseTermNA = parseLet <|> +parseTermNoApp :: Parser Term +parseTermNoApp = parseLet <|> parseVar <|> parseLambda -parseTypeAndTermNA :: Parser TypedTerm -parseTypeAndTermNA = do - term <- parseTermNA +parseTypeAndTerm :: Parser Term -> Parser TypedTerm +parseTypeAndTerm p = do + term <- p string " :: " tp <- parseTypeScheme return $! TTerm term tp -parseTypeAndTerm :: Parser TypedTerm -parseTypeAndTerm = do - term <- parseTerm - string " :: " - tp <- parseTypeScheme - return $! TTerm term tp -parseTypedTermNA :: Parser TypedTerm -parseTypedTermNA = parseBraces <|> - parseTypeAndTermNA <|> - (NTTerm <$> parseTerm) +parseTypedTermNoApp :: Parser TypedTerm +parseTypedTermNoApp = parseBraces parseTypedTerm <|> + parseTypeAndTerm parseTermNoApp <|> + (NTTerm <$> parseTermNoApp) parseTypedTerm :: Parser TypedTerm -parseTypedTerm = parseBraces <|> - parseTypeAndTerm <|> - (NTTerm <$> parseTerm) +parseTypedTerm = parseBraces parseTypedTerm <|> + parseTypeAndTerm parseTerm <|> + (NTTerm <$> parseTerm) parseType :: Parser Type -parseType = parsePrimitive <|> - parseTypeVar <|> - parseTypeFunction +parseType = parseBraces parseType <|> + parseTypeFunction <|> + parsePrimitive <|> + parseTypeVar parsePrimitive :: Parser Type parsePrimitive = do @@ -99,32 +104,33 @@ parsePrimitive = do parseTypeVar :: Parser Type parseTypeVar = do - x <- many1 $ satisfy isAsciiLower + x <- many1 $ satisfy isAsciiLower return $! TypeVar x parseTypeFunction :: Parser Type parseTypeFunction = do - a <- parseType + a <- parseBraces parseType <|> parsePrimitive <|> parseTypeVar string " -> " b <- parseType return $! TypeFunction a b parseTypeScheme :: Parser TypeScheme -parseTypeScheme = parseForAll <|> +parseTypeScheme = parseBraces parseTypeScheme <|> + parseForAll <|> (TScheme <$> parseType) parseForAll :: Parser TypeScheme parseForAll = do string "FORALL " (TypeVar x) <- parseTypeVar - string "." + string ": " t <- parseTypeScheme return $! TSForAll x t -parseBraces :: Parser TypedTerm -parseBraces = do +parseBraces :: Parser a -> Parser a +parseBraces p = do char '(' - t <- parseTypedTerm + t <- p char ')' return t @@ -154,18 +160,18 @@ parseLambda = do parseApp :: Parser Term parseApp = do - aps <- sepBy1 parseTypedTermNA (char ' ') - return $! createApp aps + aps <- sepBy1 parseTypedTermNoApp (char ' ') + createApp aps createLambda :: [Term] -> TypedTerm -> TypedTerm createLambda (Var x : vs) t = NTTerm . Lam x $ createLambda vs t createLambda [] t = t createLambda _ _ = error "createLambda failed" -createApp :: [TypedTerm] -> Term -createApp [t,ts] = App t ts +createApp :: [TypedTerm] -> Parser Term +createApp [t,ts] = return $ App t ts createApp (t:ts:tss) = createApp (NTTerm (App t ts) : tss) -createApp [] = error "empty createApp" +createApp _ = fail "not App" -- |