All pastes #362275 Raw Edit

Miscellany

public text v1 · immutable
·published 2007-02-18 18:15 UTC
rendered paste body
import Data.List
import Data.Char

doSubst :: (String, String) -> String -> (Bool, String, String)
doSubst subst str = doSubst' subst str

doSubst' :: (String, String) -> String -> (Bool, String, String)
doSubst' _ [] = (False, "", [])
doSubst' (from, to) target@(t:ts) = if from `isPrefixOf` target
	then if head to == '~'
		then (True, tail to, drop (length from) target)
		else (True, "", to ++ drop (length from) target)
	else let (b, o, s) = doSubst' (from, to) ts in (b, o, t:s)

runThue :: [(String, String)] -> String -> ([String], String)
runThue substs init = runThue' substs init []

runThue' :: [(String, String)] -> String -> [String] -> ([String], String)
runThue' substs init out = case runThue'' substs init [] False of
	(False, _, _) -> (out, init)
	(True, newout, newinit) -> runThue' substs newinit (out++newout)

runThue'' :: [(String, String)] -> String -> [String] -> Bool -> (Bool, [String], String)
runThue'' [] init out sure = (sure, out, init)
runThue'' (subst:substs) init out sure = case doSubst subst init of
	(False, _, _) -> runThue'' substs init out sure
	(True, outinc, newinit) -> if outinc == ""
		then runThue'' substs newinit out True
		else runThue'' substs newinit (out ++ [outinc]) True

dropAllWS :: [String] -> [String]
dropAllWS strs = filter (\str -> str /= "") $ map (\str -> filter (\chr -> and [chr /= ' ', chr /= '\n']) str) strs

pairUp :: [String] -> [(String, String)]
pairUp str = pairUp' str []

pairUp' :: [String] -> [(String, String)] -> [(String, String)]
pairUp' (a:b:str) pairs = pairUp' str ((a, b):pairs)
pairUp' [] pairs = pairs

removeRedundantLfs :: String -> String
removeRedundantLfs str = removeRedundantLfs' str "" True

removeRedundantLfs' :: String -> String -> Bool -> String
removeRedundantLfs' "" acc _ = acc
removeRedundantLfs' (fst:rst) acc lastwaslf =
	if and [fst=='\n', lastwaslf]
		then removeRedundantLfs' rst acc True
		else removeRedundantLfs' rst (acc++[fst]) (fst=='\n')

toTokens :: String -> [String]
toTokens str = toTokens' str [] ""

toTokens' :: String -> [String] -> String -> [String]
toTokens' [] tokens lasttoken = tokens ++ [lasttoken]
toTokens' (fst:rest) tokens lasttoken = if "::=" `isPrefixOf` rest
	then toTokens' (drop 3 rest) (tokens ++ [lasttoken ++ [fst]]) ""
	else if "\n" `isPrefixOf` rest
		then toTokens' (drop 1 rest) (tokens ++ [lasttoken ++ [fst]]) ""
		else toTokens' rest tokens (lasttoken ++ [fst])

finalize :: [(String, String)] -> ([(String, String)], String)
finalize strs = let clean = strs in
	((tail clean), snd $ head clean) -- first rule should be ("::=", initial string)

main = do
	putStr "Input file: "
	ifile <- getLine
	s <- readFile ifile
	let parsed =finalize $ pairUp $ dropAllWS $ toTokens $ removeRedundantLfs s in
		let result = runThue (fst parsed) (snd parsed) in
			print result