-- | Part of this code is from "Report on the Programming Language Haskell",-- version 1.2, appendix C.moduleLanguage.Preprocessor.Unlit(unlit)whereimportData.CharimportData.List(isPrefixOf)dataClassified=ProgramString|Blank|Comment|IncludeIntString|PreStringclassify::[String]->[Classified]classify[]=[]classify(('\\':x):xs)|x=="begin{code}"=Blank:allProgxswhereallProg[]=[]-- Should give an error message,-- but I have no good position information.allProg(('\\':x):xs)|"end{code}"`isPrefixOf`x=Blank:classifyxsallProg(x:xs)=Programx:allProgxsclassify(('>':x):xs)=Program(' ':x):classifyxsclassify(('#':x):xs)=(casewordsxof(line:rest)|allisDigitline->Include(readline)(unwordsrest)_->Prex):classifyxsclassify(x:xs)|allisSpacex=Blank:classifyxsclassify(x:xs)=Comment:classifyxsunclassify::Classified->Stringunclassify(Programs)=sunclassify(Pres)='#':sunclassify(Includeif)='#':' ':showi++' ':funclassifyBlank=""unclassifyComment=""-- | 'unlit' takes a filename (for error reports), and transforms the-- given string, to eliminate the literate comments from the program text.unlit::FilePath->String->Stringunlitfilelhs=(unlines.mapunclassify.adjacentfile(0::Int)Blank.classify)(inlineslhs)adjacent::FilePath->Int->Classified->[Classified]->[Classified]adjacentfile0_(x:xs)=x:adjacentfile1xxs-- force evaluation of line numberadjacentfileny@(Program_)(x@Comment:xs)=error(messagefilen"program""comment")adjacentfileny@(Program_)(x@(Includeif):xs)=x:adjacentfiyxsadjacentfileny@(Program_)(x@(Pre_):xs)=x:adjacentfile(n+1)yxsadjacentfileny@Comment(x@(Program_):xs)=error(messagefilen"comment""program")adjacentfileny@Comment(x@(Includeif):xs)=x:adjacentfiyxsadjacentfileny@Comment(x@(Pre_):xs)=x:adjacentfile(n+1)yxsadjacentfileny@Blank(x@(Includeif):xs)=x:adjacentfiyxsadjacentfileny@Blank(x@(Pre_):xs)=x:adjacentfile(n+1)yxsadjacentfilen_(x@next:xs)=x:adjacentfile(n+1)xxsadjacentfilen_[]=[]message::String->Int->String->String->Stringmessage"\"\""npc="Line "++shown++": "++p++" line before "++c++" line.\n"message[]npc="Line "++shown++": "++p++" line before "++c++" line.\n"messagefilenpc="In file "++file++" at line "++shown++": "++p++" line before "++c++" line.\n"-- Re-implementation of 'lines', for better efficiency (but decreased laziness).-- Also, importantly, accepts non-standard DOS and Mac line ending characters.inlines::String->[String]inliness=lines'sidwherelines'[]acc=[acc[]]lines'('\^M':'\n':s)acc=acc[]:lines'sid-- DOSlines'('\^M':s)acc=acc[]:lines'sid-- MacOSlines'('\n':s)acc=acc[]:lines'sid-- Unixlines'(c:s)acc=lines's(acc.(c:))