------------------------------------------------------------------------------ --- Library for converting ground terms to strings and vice versa. --- --- @author Michael Hanus --- @version April 2005 ------------------------------------------------------------------------------ module ReadShowTerm {-(showTerm,showQTerm,readQTerm,readsQTerm, readsUnqualifiedTerm,readUnqualifiedTerm,readsTerm,readTerm, readQTermFile,readQTermListFile, writeQTermFile,writeQTermListFile)-} where import Char(isSpace) --- Transforms a ground(!) term into a string representation --- in standard prefix notation. --- Thus, showTerm suspends until its argument is ground. --- This function is similar to the prelude function show --- but can read the string back with readUnqualifiedTerm --- (provided that the constructor names are unique without the module --- qualifier). showTerm :: _ -> String showTerm x = prim_showTerm $## x prim_showTerm :: _ -> String prim_showTerm external --- Transforms a ground(!) term into a string representation --- in standard prefix notation. --- Thus, showTerm suspends until its argument is ground. --- Note that this function differs from the prelude function show --- since it prefixes constructors with their module name --- in order to read them back with readQTerm. showQTerm :: _ -> String showQTerm x = prim_showQTerm $## x prim_showQTerm :: _ -> String prim_showQTerm external --- Transform a string containing a term in standard prefix notation --- without module qualifiers into the corresponding data term. --- The first argument is a non-empty list of module qualifiers that are tried to --- prefix the constructor in the string in order to get the qualified constructors --- (that must be defined in the current program!). --- In case of a successful parse, the result is a one element list --- containing a pair of the data term and the remaining unparsed string. readsUnqualifiedTerm :: [String] -> String -> [(_,String)] readsUnqualifiedTerm [] _ = error "ReadShowTerm.readsUnqualifiedTerm: list of module prefixes is empty" readsUnqualifiedTerm (prefix:prefixes) s = readsUnqualifiedTermWithPrefixes (prefix:prefixes) s readsUnqualifiedTermWithPrefixes :: [String] -> String -> [(_,String)] readsUnqualifiedTermWithPrefixes prefixes s = (prim_readsUnqualifiedTerm $## prefixes) $## s prim_readsUnqualifiedTerm :: [String] -> String -> [(_,String)] prim_readsUnqualifiedTerm external --- Transforms a string containing a term in standard prefix notation --- without module qualifiers into the corresponding data term. --- The first argument is a non-empty list of module qualifiers that are tried to --- prefix the constructor in the string in order to get the qualified constructors --- (that must be defined in the current program!). --- --- Example: readUnqualifiedTerm ["prelude"] "Just 3" --- evaluates to (Just 3) readUnqualifiedTerm :: [String] -> String -> _ readUnqualifiedTerm prefixes s = case readsUnqualifiedTerm prefixes s of [(term,tail)] -> if all isSpace tail then term else error ("ReadShowTerm.readUnqualifiedTerm: no parse, unmatched string after term: "++tail) [] -> error "ReadShowTerm.readUnqualifiedTerm: no parse" _ -> error "ReadShowTerm.readUnqualifiedTerm: ambiguous parse" --- For backward compatibility. Should not be used since their use can be problematic --- in case of constructors with identical names in different modules. readsTerm :: String -> [(_,String)] readsTerm s = prim_readsUnqualifiedTerm [] $## s --- For backward compatibility. Should not be used since their use can be problematic --- in case of constructors with identical names in different modules. readTerm :: String -> _ readTerm s = case result of [(term,tail)] -> if all isSpace tail then term else error ("ReadShowTerm.readTerm: no parse, unmatched string after term: "++tail) [] -> error $ "ReadShowTerm.readTerm: no parse of string beginning with " ++ take 20 s _ -> error "ReadShowTerm.readTerm: ambiguous parse" where result = prim_readsUnqualifiedTerm [] $## s --- Transforms a string containing a term in standard prefix notation --- with qualified constructor names into the corresponding data term. --- In case of a successful parse, the result is a one element list --- containing a pair of the data term and the remaining unparsed string. readsQTerm :: String -> [(_,String)] readsQTerm s = prim_readsQTerm $## s prim_readsQTerm :: String -> [(_,String)] prim_readsQTerm external --- Transforms a string containing a term in standard prefix notation --- with qualified constructor names into the corresponding data term. readQTerm :: String -> _ readQTerm s = case result of [(term,tail)] -> if all isSpace tail then term else error "ReadShowTerm.readQTerm: no parse" [] -> error "ReadShowTerm.readQTerm: no parse" _ -> error "ReadShowTerm.readQTerm: ambiguous parse" where result = readsQTerm s --- Reads a file containing a string representation of a term --- in standard prefix notation and returns the corresponding data term. readQTermFile :: String -> IO _ readQTermFile file = readFile file >>= return . readQTerm --- Reads a file containing lines with string representations of terms --- of the same type and returns the corresponding list of data terms. readQTermListFile :: String -> IO [_] readQTermListFile file = readFile file >>= return . map readQTerm . lines --- Writes a ground term into a file in standard prefix notation. --- @param filename - The name of the file to be written. --- @param term - The term to be written to the file as a string. writeQTermFile :: String -> _ -> IO () writeQTermFile filename term = writeFile filename (showQTerm term) --- Writes a list of ground terms into a file. --- Each term is written into a separate line which might be useful --- to modify the file with a standard text editor. --- @param filename - The name of the file to be written. --- @param terms - The list of terms to be written to the file. writeQTermListFile :: String -> [_] -> IO () writeQTermListFile filename terms = writeFile filename (unlines (map showQTerm terms))