```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 ``` ```{- | Author : Kai-Oliver Prott Version : August 2018 Datatype and operations to handle Spans. -} module Curry.Span ( Span(..), -- * Selectors start, end, -- * Transformer, isSpan, isNoSpan, fromPosition, stripStart, span2Pos, combineSpans, addSpan, -- * Distance management vertDist, isAfter, isBefore, isBeforeList, spanLength ) where import Curry.Position data Span = Span Position Position -- ^ Span StarPos EndPos | NoSpan deriving (Eq, Show, Read) start :: Span -> Position start NoSpan = NoPos start (Span st _) = st end :: Span -> Position end NoSpan = NoPos end (Span _ ed) = ed isSpan :: Span -> Bool isSpan (Span _ _) = True isSpan NoSpan = False isNoSpan :: Span -> Bool isNoSpan (Span _ _) = False isNoSpan NoSpan = True -- | Create a Span with the given Position as start and end fromPosition :: Position -> Span fromPosition NoPos = NoSpan fromPosition p@(Position _ _) = Span p p -- | Sets the start position of a Span to its end position stripStart :: Span -> Span stripStart = fromPosition . end -- | Computes a "vertical distance" between two spans. -- It is either the row distance of the start end end positions or -- zero, if the spans overlap. vertDist :: Span -> Span -> Int vertDist NoSpan NoSpan = 0 vertDist NoSpan (Span _ _ ) = 0 vertDist (Span _ _ ) NoSpan = 0 vertDist (Span s1 e1) (Span s2 e2) = case rowDist e1 s2 of x | x >= 0 -> x | e1 <= e2 -> 0 -- they overlap | otherwise -> - (rowDist e2 s1) -- | Checks if the first span is completely after the second span. isAfter :: Span -> Span -> Bool isAfter NoSpan NoSpan = False isAfter (Span _ _) NoSpan = False isAfter NoSpan (Span _ _) = False isAfter (Span s _) (Span _ e) = s >= e -- | Checks if the first span is completely before the second span. isBefore :: Span -> Span -> Bool isBefore NoSpan NoSpan = False isBefore (Span _ _) NoSpan = False isBefore NoSpan (Span _ _) = False isBefore (Span _ e) (Span s _) = e <= s -- | Checks if the first span is completely -- before the first span of a list. -- Reurns `True` if the list is empty isBeforeList :: Span -> [Span] -> Bool isBeforeList _ [] = True isBeforeList sp1 (sp2:_) = isBefore sp1 sp2 span2Pos :: Span -> Position span2Pos (Span p _) = p span2Pos NoSpan = NoPos combineSpans :: Span -> Span -> Span combineSpans sp1 sp2 = Span s e where s = start sp1 e = end sp2 addSpan :: Span -> (a, [Span]) -> (a, [Span]) addSpan sp (a, ss) = (a, sp:ss) spanLength :: Span -> (Int, Int) spanLength sp = case sp of Span (Position x1 y1) (Position x2 y2) -> (x2-x1, y2-y1) _ -> (0, 0) ```