module Yi.Syntax.Fractal (parse, getStrokes) where
import Yi.Lexer.Alex (Tok(..), tokBegin)
import qualified Yi.IncrementalParse as P
import qualified Data.Tree as S
import Control.Applicative
import Yi.Prelude
import Prelude ()
import Yi.Buffer.Basic
import Data.List (splitAt)
data Tree a = Node a (Tree a) (Tree a)
| Leaf
deriving Show
factor :: Int
factor = 2
toTree :: [a] -> Tree a
toTree = tt factor
where tt _ [] = Leaf
tt level (x:xs) = let (l,r) = splitAt level xs
in Node x (toTree l) (tt (level * factor) r)
fromTree :: Tree a -> [a]
fromTree (Node a l r) = a : fromTree l ++ fromTree r
fromTree Leaf = []
shape :: Show a => Tree a -> [S.Tree String]
shape Leaf = [] -- [S.Node "o"[]]
shape (Node x l r) = [S.Node (show x) (shape l ++ shape r)]
parse = parse' initSize maxBound
where initSize = 1
parse' :: Int -> Int -> P.P (Tok a) (Tree (Tok a))
parse' leftSize maxSize
| maxSize <= 0 = pure Leaf
| otherwise
= (Node <$> P.symbol (const True)
<*> parse' (initSize * factor) (min leftSize (maxSize - 1))
<*> parse' (leftSize * factor) (maxSize - leftSize - 1))
<|> (P.eof *> pure Leaf)
-- NOTE: eof here is important for performance (otherwise the
-- parser would have to keep this case until the very end of input
-- is reached.
getStrokes begin end t = getStrokes' begin end t []
where getStrokes' :: Point -> Point -> Tree (Tok token) -> Endom [Tok token]
getStrokes' _ _ Leaf = id
getStrokes' _ end (Node t _ _)
| end < tokBegin t = id
getStrokes' begin end (Node s lc Leaf)
= (s :) . getStrokes' begin end lc
getStrokes' begin end (Node s _ rc@(Node t _ _))
| tokBegin t < begin = (s :) . getStrokes' begin end rc
getStrokes' begin end (Node s lc rc)
= (s :) . getStrokes' begin end lc . getStrokes' begin end rc