module TermFocus where
import qualified Term
import Term ( Term, Identifier )
import IO ( Output, output )
import Text.PrettyPrint.HughesPJ ( Doc, (<+>), fsep, parens, render, text )
import Data.Tuple.HT ( mapPair )
import Data.List.HT ( tails )
import Data.List ( isPrefixOf )
data TermFocus =
TermFocus { subTerm :: Term, superTerms :: [ SuperTerm ] }
deriving (Show)
data SuperTerm = Node Identifier ( List Term )
deriving (Show)
data List a = List [a] [a]
deriving (Show)
instance Output TermFocus where
output tf =
foldl (flip outputSuperTerm) (outputSubTerm (subTerm tf)) $
superTerms tf
outputSuperTerm :: SuperTerm -> Doc -> Doc
outputSuperTerm (Node nm (List leftArgs rightArgs)) focus =
output nm <+>
fsep ( map Term.protected ( reverse leftArgs ) ++
parens focus : map Term.protected rightArgs )
outputSubTerm :: Term -> Doc
outputSubTerm t = case t of
Term.Number _ n -> text $ mark $ show n
Term.StringLiteral _ s -> text $ mark $ show s
Term.Node f args ->
( text $ mark $ Term.name f ) <+> fsep ( map Term.protected args )
markStart, markStop :: String
markStart = "{{"
markStop = "}}"
mark :: String -> String
mark str = markStart ++ str ++ markStop
format :: TermFocus -> ((Int, Int), String)
format t =
let s = render $ output t
in case splitAtInfix markStart s of
(_, Nothing) -> ((0,0), s)
(prefix, Just suffix0) ->
let n = length prefix
in mapPair ((\j -> (n, n+j)), (prefix ++)) $
case splitAtInfix markStop suffix0 of
(_, Nothing) ->
(length suffix0, suffix0)
(marked, Just suffix) ->
(length marked, marked ++ suffix)
splitAtInfix :: Eq a => [a] -> [a] -> ([a], Maybe [a])
splitAtInfix infx str =
mapPair
(map head,
\suffix ->
case suffix of
[] -> Nothing
xs:_ -> Just $ drop (length infx) xs) $
break (isPrefixOf infx) $ init $ tails str
fromTerm :: Term -> TermFocus
fromTerm t = TermFocus t []