packages feed

yi-0.5.2: Yi/Syntax/OnlineTree.hs

module Yi.Syntax.OnlineTree (Tree(..), parse, dropToIndex) where
import Prelude ()
import Yi.Prelude
import Yi.IncrementalParse
import Control.Applicative
import Data.Traversable
import Data.Foldable
import Yi.Lexer.Alex
import Yi.Buffer.Basic (Point)


data Tree a = Node a (Tree a) (Tree a)
            | Leaf
              deriving Show

instance Traversable Tree where
    traverse f (Node x l r) = Node <$> f x <*> traverse f l <*> traverse f r
    traverse _ Leaf = pure Leaf

instance Foldable Tree where
    foldMap = foldMapDefault

instance Functor Tree where
    fmap = fmapDefault

case_ :: (Maybe s -> Bool) -> P s a -> P s a -> P s a
case_ f true false = (testNext f *> true) <|> (testNext (not . f) *> false)

symbolBefore :: Point -> Maybe (Tok t) -> Bool
symbolBefore _ Nothing = False
symbolBefore p (Just x) = tokBegin x <= p

factor :: Int
factor = 2  

initialLeftSize :: Size
initialLeftSize = 2 

parse = parse' initialLeftSize 0 maxBound

-- Invariant: all symbols are after the l
-- | Parse all the symbols starting in the interval [lb, rb[
parse' :: Size -> Point -> Point -> P (Tok t) (Tree (Tok t))
parse' leftSize lB rB
   | rB <= lB = pure Leaf
   | otherwise = case_ (symbolBefore rB)
       (Node <$> symbol (const True)
             <*> parse' initialLeftSize      lB   midB
             <*> parse' (leftSize * fromIntegral factor)  midB rB)
       (pure Leaf) 
  where midB = min rB (lB +~ leftSize)
    -- NOTE: eof here is important for performance (otherwise the
    -- parser would have to keep this case until the very end of input
    -- is reached.

toEndo Leaf = id
toEndo (Node x l r) = (x :) . toEndo l . toEndo r

dropToIndex :: Point -> Tree t -> [t]
dropToIndex index t = dropHelp initialLeftSize t index []

dropHelp :: Size -> Tree a -> Point -> [a] -> [a]
dropHelp _leftsize Leaf _n = id
dropHelp leftsize (Node x l r) index
    | fromIntegral index <  leftsize = (x :) . dropHelp initialLeftSize     l index . toEndo  r
    -- the head is speculatively put in the result; but it does not matter, since we
    -- add only O(log n) elements this way.
    | otherwise         = (x :) . dropHelp (leftsize * fromIntegral factor) r  (index -~ leftsize)