module Paper.Haskell2.Stage1(stage1) where import Data.Char import Data.List import Paper.Util.String import Paper.Util.Error import Paper.Haskell2.Type import Paper.Haskell2.Haskell defs = [("\\hsdef{\\begin{comment}","\\end{comment}}") ,("\\begin{hsdef}","\\end{hsdef}") ,("\\hsdef\\begin{comment}","\\end{comment}") ,("\\hsdef{","}") ] stage1 :: FilePath -> String -> [HsLow] stage1 file = f 1 "" where pos = Pos file f i cmd xs | match /= [] = map (HsDef (pos i)) (lines a) ++ f (i + newlines a) "" b where match = filter ((`isPrefixOf` xs) . fst) defs (start,end):_ = match (a,b) = breakStr end $ drop (length start) xs f i cmd xs | "\\ignore" `isPrefixOf` xs = f i "ignore" $ drop 7 xs f i cmd xs | "\\h{" `isPrefixOf` xs = f (i + newlines a) a $ drop 1 b where (a,b) = break (== '}') $ drop 3 xs f i cmd ('|':'|':xs) = f i "" xs f i cmd ('|':xs) | '\n' `elem` a = errorDie file i "Failed to parse | lines" a | otherwise = hsCheck (pos i) Expr cmd a ++ f i "" b where (a,b) = spanExpr xs f i cmd xs | "\\begin{code}" `isPrefixOf` xs = hsCheck (pos i) Stmt cmd a ++ concatMap (f i "") (comments a) ++ f (i + newlines a) "" b where (a,b) = breakStr "\\end{code}" $ drop 12 xs f i cmd xs | "%if 0" `isPrefixOf` xs = f (i + newlines a) "" b where (a,b) = breakStr "%endif" xs f i cmd ('%':xs) = f i "" $ dropWhile (/= '\n') xs f i cmd (x:xs) | x == '\n' = f (i+1) cmd xs | isSpace x = f i cmd xs | otherwise = f i "" xs f i cmd [] = [] comments :: String -> [String] comments = concatMap f . lines where f xs = [drop 2 b | not $ null b] where (_,b) = breakStr "--" xs spanExpr :: String -> (String, String) spanExpr ('|':'|':xs) = ('|':a, b) where (a,b) = spanExpr xs spanExpr ('|':xs) = ("", xs) spanExpr (x:xs) = (x:a,b) where (a,b) = spanExpr xs spanExpr [] = ("","") newlines :: String -> Int newlines = length . filter (== '\n') readCmd :: String -> ([String], String) readCmd ('.':xs) = (a:c,d) where (a,b) = break (== ' ') xs (c,d) = readCmd $ drop 1 b readCmd xs = ([], xs) hsCheck pos typ cmd x | b == "ignore" = [] | b == "" = cont [(typ,x)] | otherwise = cont $ hsCustom b x where cont tx = [HsCheck pos t (parseWhere a) x | (t,x) <- tx] (a,b) = readCmd cmd -- @ foo = bar -- @ = def -- implicitly insert foo before each = hsCustom "deflist" x = [(Stmt,unlines $ map f ls)] where ls = lines x prefix = takeWhile (/= '=') $ head $ dropWhile (all isSpace) ls f x | "=" `isPrefixOf` dropWhile isSpace x = prefix ++ x | otherwise = x -- each line started at column 1 is a new expr hsCustom "exprlist" x = map ((,) Expr) $ f $ lines x where f (x:(y:ys):z) | isSpace y = f ((x ++ '\n':y:ys) : z) f (x:xs) = x : f xs f [] = [] -- a piece of context hsCustom "ctxt" x = [(Stmt,"context_expression :: " ++ x ++ " => " ++ free ++ "()\ncontext_expression = undefined")] where free = concat [x:xs ++ " -> " | x:xs <- lexer x, isLower x] -- a type expression hsCustom "type" x = [(Stmt,"type TypeType " ++ free ++ " = " ++ x)] where free = unwords [x | x <- lexer x, isLower $ head x] hsCustom "do" x = [(Expr,unlines $ "do" : map (' ':) (lines x))] hsCustom "stmt" x = [(Stmt,x)] hsCustom "expr" x = [(Expr,unlines $ map (' ':) $ lines x)] hsCustom name _ = error $ "Stage1 todo: " ++ show name