-- | A Parsec parser type that parses 'Symbol's and keeps track of the -- position within the input stream. Unlike Parsec's default position -- tracking, this parser keeps track of the range of whitespace between two -- tokens.moduleAnnotations.BoundsParser(-- * SymbolsSymbol(..),collapse,-- * ParsingP,satisfy,pToken,getPos)whereimportAnnotations.BoundsimportqualifiedText.ParsecasPimportqualifiedText.Parsec.PosasP-- | Symbols form input for parsers. Minimal complete definition: 'unparse'.classSymbolswhere-- | Unparses a symbol, converting it back to text.unparse::s->String-- | Yields the size of a symbol. Default implementation is @length . unparse@.symbolSize::s->IntsymbolSize=length.unparseinstanceSymbols=>Symbol[s]whereunparse=concatMapunparsesymbolSize=sum.fmapsymbolSize-- | Given a predicate that tells what tokens to discard, keeps only the meaningful tokens and couples them with position information.collapse::Symbols=>(s->Bool)->[s]->[(s,Bounds)]collapsespacets=collapse'(0,symbolSizelefts)spacerestwhere(lefts,rest)=spanspacetscollapse'::Symbols=>Range->(s->Bool)->[s]->[(s,Bounds)]collapse'__[]=[]collapse'leftspace(t:ts)=new:collapse'rightspacerestwhere(_,leftInner)=leftrightInner=leftInner+symbolSizetrightOuter=rightInner+symbolSizerightsright=(rightInner,rightOuter)(rights,rest)=spanspacetsnew=(t,Boundsleftright)-- | A parser that works on symbols coupled with token information. The state maintains the current position in the stream. This position is the range of whitespace between two tokens.typePs=P.ParsecT[(s,Bounds)]Range-- | Yield the current position in the input.getPos::Monadm=>PsmRangegetPos=P.getState-- | Recognise a symbol matching a predicate.satisfy::(Monadm,Symbols)=>(s->Bool)->Psmssatisfyok=doletpos_(_,bounds)_=P.newPos""0(fst(rightMarginbounds)+1)letmatchx@(tok,_)|oktok=Justx|otherwise=Nothing(tok,bounds)<-P.tokenPrim(unparse.fst)posmatchP.setState(rightMarginbounds)returntok-- | Recognise a specific symbol.pToken::(Monadm,Symbols,Eqs)=>s->PsmspToken=satisfy.(==)