{-# OPTIONS_GHC -Wwarn #-}
module Language.Preprocessor.Unlit (unlit) where
import Data.Char
import Data.List (isPrefixOf)
data Classified = Program String | Blank |
| Include Int String | Pre String
classify :: [String] -> [Classified]
classify :: [String] -> [Classified]
classify [] = []
classify (('\\':x :: String
x):xs :: [String]
xs) | String
x String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== "begin{code}" = Classified
Blank Classified -> [Classified] -> [Classified]
forall a. a -> [a] -> [a]
: [String] -> [Classified]
allProg [String]
xs
where allProg :: [String] -> [Classified]
allProg [] = []
allProg (('\\':x :: String
x):xs :: [String]
xs) | "end{code}"String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf`String
x = Classified
Blank Classified -> [Classified] -> [Classified]
forall a. a -> [a] -> [a]
: [String] -> [Classified]
classify [String]
xs
allProg (x :: String
x:xs :: [String]
xs) = String -> Classified
Program String
xClassified -> [Classified] -> [Classified]
forall a. a -> [a] -> [a]
:[String] -> [Classified]
allProg [String]
xs
classify (('>':x :: String
x):xs :: [String]
xs) = String -> Classified
Program (' 'Char -> String -> String
forall a. a -> [a] -> [a]
:String
x) Classified -> [Classified] -> [Classified]
forall a. a -> [a] -> [a]
: [String] -> [Classified]
classify [String]
xs
classify (('#':x :: String
x):xs :: [String]
xs) = (case String -> [String]
words String
x of
(line :: String
line:rest :: [String]
rest) | (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
isDigit String
line
-> Int -> String -> Classified
Include (String -> Int
forall a. Read a => String -> a
read String
line) ([String] -> String
unwords [String]
rest)
_ -> String -> Classified
Pre String
x
) Classified -> [Classified] -> [Classified]
forall a. a -> [a] -> [a]
: [String] -> [Classified]
classify [String]
xs
classify (x :: String
x:xs :: [String]
xs) | (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
isSpace String
x = Classified
BlankClassified -> [Classified] -> [Classified]
forall a. a -> [a] -> [a]
:[String] -> [Classified]
classify [String]
xs
classify (x :: String
x:xs :: [String]
xs) = Classified
CommentClassified -> [Classified] -> [Classified]
forall a. a -> [a] -> [a]
:[String] -> [Classified]
classify [String]
xs
unclassify :: Classified -> String
unclassify :: Classified -> String
unclassify (Program s :: String
s) = String
s
unclassify (Pre s :: String
s) = '#'Char -> String -> String
forall a. a -> [a] -> [a]
:String
s
unclassify (Include i :: Int
i f :: String
f) = '#'Char -> String -> String
forall a. a -> [a] -> [a]
:' 'Char -> String -> String
forall a. a -> [a] -> [a]
:Int -> String
forall a. Show a => a -> String
show Int
i String -> String -> String
forall a. [a] -> [a] -> [a]
++ ' 'Char -> String -> String
forall a. a -> [a] -> [a]
:String
f
unclassify Blank = ""
unclassify Comment = ""
unlit :: FilePath -> String -> String
unlit :: String -> String -> String
unlit file :: String
file lhs :: String
lhs = ([String] -> String
unlines
([String] -> String)
-> ([String] -> [String]) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Classified -> String) -> [Classified] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Classified -> String
unclassify
([Classified] -> [String])
-> ([String] -> [Classified]) -> [String] -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Int -> Classified -> [Classified] -> [Classified]
adjacent String
file (0::Int) Classified
Blank
([Classified] -> [Classified])
-> ([String] -> [Classified]) -> [String] -> [Classified]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> [Classified]
classify) (String -> [String]
inlines String
lhs)
adjacent :: FilePath -> Int -> Classified -> [Classified] -> [Classified]
adjacent :: String -> Int -> Classified -> [Classified] -> [Classified]
adjacent file :: String
file 0 _ (x :: Classified
x :xs :: [Classified]
xs) = Classified
x Classified -> [Classified] -> [Classified]
forall a. a -> [a] -> [a]
: String -> Int -> Classified -> [Classified] -> [Classified]
adjacent String
file 1 Classified
x [Classified]
xs
adjacent file :: String
file n :: Int
n y :: Classified
y@(Program _) (x :: Classified
x@Classified
Comment :xs :: [Classified]
xs) = String -> [Classified]
forall a. HasCallStack => String -> a
error (String -> Int -> String -> String -> String
message String
file Int
n "program" "comment")
adjacent file :: String
file n :: Int
n y :: Classified
y@(Program _) (x :: Classified
x@(Include i :: Int
i f :: String
f):xs :: [Classified]
xs) = Classified
xClassified -> [Classified] -> [Classified]
forall a. a -> [a] -> [a]
: String -> Int -> Classified -> [Classified] -> [Classified]
adjacent String
f Int
i Classified
y [Classified]
xs
adjacent file :: String
file n :: Int
n y :: Classified
y@(Program _) (x :: Classified
x@(Pre _) :xs :: [Classified]
xs) = Classified
xClassified -> [Classified] -> [Classified]
forall a. a -> [a] -> [a]
: String -> Int -> Classified -> [Classified] -> [Classified]
adjacent String
file (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) Classified
y [Classified]
xs
adjacent file :: String
file n :: Int
n y :: Classified
y@Classified
Comment (x :: Classified
x@(Program _) :xs :: [Classified]
xs) = String -> [Classified]
forall a. HasCallStack => String -> a
error (String -> Int -> String -> String -> String
message String
file Int
n "comment" "program")
adjacent file :: String
file n :: Int
n y :: Classified
y@Classified
Comment (x :: Classified
x@(Include i :: Int
i f :: String
f):xs :: [Classified]
xs) = Classified
xClassified -> [Classified] -> [Classified]
forall a. a -> [a] -> [a]
: String -> Int -> Classified -> [Classified] -> [Classified]
adjacent String
f Int
i Classified
y [Classified]
xs
adjacent file :: String
file n :: Int
n y :: Classified
y@Classified
Comment (x :: Classified
x@(Pre _) :xs :: [Classified]
xs) = Classified
xClassified -> [Classified] -> [Classified]
forall a. a -> [a] -> [a]
: String -> Int -> Classified -> [Classified] -> [Classified]
adjacent String
file (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) Classified
y [Classified]
xs
adjacent file :: String
file n :: Int
n y :: Classified
y@Classified
Blank (x :: Classified
x@(Include i :: Int
i f :: String
f):xs :: [Classified]
xs) = Classified
xClassified -> [Classified] -> [Classified]
forall a. a -> [a] -> [a]
: String -> Int -> Classified -> [Classified] -> [Classified]
adjacent String
f Int
i Classified
y [Classified]
xs
adjacent file :: String
file n :: Int
n y :: Classified
y@Classified
Blank (x :: Classified
x@(Pre _) :xs :: [Classified]
xs) = Classified
xClassified -> [Classified] -> [Classified]
forall a. a -> [a] -> [a]
: String -> Int -> Classified -> [Classified] -> [Classified]
adjacent String
file (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) Classified
y [Classified]
xs
adjacent file :: String
file n :: Int
n _ (x :: Classified
x@Classified
next :xs :: [Classified]
xs) = Classified
xClassified -> [Classified] -> [Classified]
forall a. a -> [a] -> [a]
: String -> Int -> Classified -> [Classified] -> [Classified]
adjacent String
file (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) Classified
x [Classified]
xs
adjacent file :: String
file n :: Int
n _ [] = []
message :: String -> Int -> String -> String -> String
message :: String -> Int -> String -> String -> String
message "\"\"" n :: Int
n p :: String
p c :: String
c = "Line "String -> String -> String
forall a. [a] -> [a] -> [a]
++Int -> String
forall a. Show a => a -> String
show Int
nString -> String -> String
forall a. [a] -> [a] -> [a]
++": "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
pString -> String -> String
forall a. [a] -> [a] -> [a]
++ " line before "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
cString -> String -> String
forall a. [a] -> [a] -> [a]
++" line.\n"
message [] n :: Int
n p :: String
p c :: String
c = "Line "String -> String -> String
forall a. [a] -> [a] -> [a]
++Int -> String
forall a. Show a => a -> String
show Int
nString -> String -> String
forall a. [a] -> [a] -> [a]
++": "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
pString -> String -> String
forall a. [a] -> [a] -> [a]
++ " line before "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
cString -> String -> String
forall a. [a] -> [a] -> [a]
++" line.\n"
message file :: String
file n :: Int
n p :: String
p c :: String
c = "In file " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
file String -> String -> String
forall a. [a] -> [a] -> [a]
++ " at line "String -> String -> String
forall a. [a] -> [a] -> [a]
++Int -> String
forall a. Show a => a -> String
show Int
nString -> String -> String
forall a. [a] -> [a] -> [a]
++": "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
pString -> String -> String
forall a. [a] -> [a] -> [a]
++ " line before "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
cString -> String -> String
forall a. [a] -> [a] -> [a]
++" line.\n"
inlines :: String -> [String]
inlines :: String -> [String]
inlines s :: String
s = String -> (String -> String) -> [String]
lines' String
s String -> String
forall a. a -> a
id
where
lines' :: String -> (String -> String) -> [String]
lines' [] acc :: String -> String
acc = [String -> String
acc []]
lines' ('\^M':'\n':s :: String
s) acc :: String -> String
acc = String -> String
acc [] String -> [String] -> [String]
forall a. a -> [a] -> [a]
: String -> (String -> String) -> [String]
lines' String
s String -> String
forall a. a -> a
id
lines' ('\^M':s :: String
s) acc :: String -> String
acc = String -> String
acc [] String -> [String] -> [String]
forall a. a -> [a] -> [a]
: String -> (String -> String) -> [String]
lines' String
s String -> String
forall a. a -> a
id
lines' ('\n':s :: String
s) acc :: String -> String
acc = String -> String
acc [] String -> [String] -> [String]
forall a. a -> [a] -> [a]
: String -> (String -> String) -> [String]
lines' String
s String -> String
forall a. a -> a
id
lines' (c :: Char
c:s :: String
s) acc :: String -> String
acc = String -> (String -> String) -> [String]
lines' String
s (String -> String
acc (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char
cChar -> String -> String
forall a. a -> [a] -> [a]
:))