-- | Utilities to turn a lexer generated by Alex into a scanner-- that can be used by Yi.{-# LANGUAGE Rank2Types #-}moduleYi.Lexer.Alex(-- * Names expected by Alex codeAlexInput,alexGetChar,alexInputPrevChar,-- * Other things closely associated with the lexerAlexState(..),unfoldLexer,lexScanner,alexCollectChar,-- * Lexer actionsactionConst,actionAndModify,actionStringAndModify,actionStringConst,-- * Data produced by the scannerTok(..),tokBegin,tokEnd,tokFromT,tokRegion,Posn(..),startPosn,moveStr,ASI,(+~),(~-),Size(..),Stroke,tokToSpan)whereimportYi.Syntaxhiding(mkHighlighter)importYi.PreludeimportPrelude()importYi.RegionimportData.Ord(comparing)importData.IxtypeIndexedStr=[(Point,Char)]typeAlexInput=(Char,IndexedStr)typeActionhlStatetoken=IndexedStr->hlState->(hlState,token)-- | Lexer statedataAlexStatelexerState=AlexState{stLexer::lexerState,-- (user defined) lexer statelookedOffset::!Point,-- Last offset looked atstPosn::!Posn}derivingShowdataTokt=Tok{tokT::t,tokLen::Size,tokPosn::Posn}instanceFunctorTokwherefmapf(Toktlp)=Tok(ft)lptokToSpan::Tokt->SpanttokToSpan(Toktlenposn)=Span(posnOfsposn)t(posnOfsposn+~len)tokFromT::forallt.t->TokttokFromTt=Tokt0startPosntokBegin::forallt.Tokt->PointtokBegin=posnOfs.tokPosntokEnd::forallt.Tokt->PointtokEndt=tokBegint+~tokLenttokRegion::Tokt->RegiontokRegiont=mkRegion(tokBegint)(tokEndt)instanceShowt=>Show(Tokt)whereshowtok=show(tokPosntok)++": "++show(tokTtok)dataPosn=Posn{posnOfs::!Point,posnLine::!Int,posnCol::!Int}deriving(Eq,Ix)-- TODO: Verify that this is right. /DenizinstanceOrdPosnwherecompare=comparingposnOfsinstanceShowPosnwhereshow(Posnolc)="L"++showl++" "++"C"++showc++"@"++showostartPosn::PosnstartPosn=Posn010moveStr::Posn->IndexedStr->PosnmoveStrposnstr=foldl'moveChposn(fmapsndstr)moveCh::Posn->Char->PosnmoveCh(Posnolc)'\t'=Posn(o+1)l(((c+8)`div`8)*8)moveCh(Posnol_)'\n'=Posn(o+1)(l+1)0moveCh(Posnolc)_=Posn(o+1)l(c+1)alexGetChar::AlexInput->Maybe(Char,AlexInput)alexGetChar(_,[])=NothingalexGetChar(_,(_,c):rest)=Just(c,(c,rest))alexCollectChar::AlexInput->[Char]alexCollectChar(_,[])=[]alexCollectChar(_,(_,c):rest)=c:(alexCollectChar(c,rest))alexInputPrevChar::AlexInput->CharalexInputPrevChar(prevChar,_)=prevChar-- | Return a constant tokenactionConst::token->ActionlexStatetokenactionConsttoken_strstate=(state,token)-- | Return a constant token, and modify the lexer stateactionAndModify::(lexState->lexState)->token->ActionlexStatetokenactionAndModifymodifierFcttoken_strstate=(modifierFctstate,token)-- | Convert the parsed string into a token,-- and also modify the lexer stateactionStringAndModify::(lexState->lexState)->(String->token)->ActionlexStatetokenactionStringAndModifymodifierFctfindexedStrstate=(modifierFctstate,f$fmapsndindexedStr)-- | Convert the parsed string into a tokenactionStringConst::(String->token)->ActionlexStatetokenactionStringConstfindexedStrstate=(state,f$fmapsndindexedStr)typeASIs=(AlexStates,AlexInput)-- | Combine a character scanner with a lexer to produce a token scanner.-- May be used together with 'mkHighlighter' to produce a 'Highlighter',-- or with 'linearSyntaxMode' to produce a 'Mode'.lexScanner::foralllexerStatetoken.((AlexStatelexerState,AlexInput)->Maybe(token,(AlexStatelexerState,AlexInput)))-- ^ A lexer->lexerState-- ^ Initial user state for the lexer->ScannerPointChar->Scanner(AlexStatelexerState)tokenlexScannerlst0src=Scanner{--stStart = posnOfs . stPosn,scanLooked=lookedOffset,scanInit=AlexStatest00startPosn,scanRun=\st->caseposnOfs$stPosnstof0->unfoldLexerl(st,('\n',scanRunsrc0))ofs->casescanRunsrc(ofs-1)of-- FIXME: if this is a non-ascii char the ofs. will be wrong.-- However, since the only thing that matters (for now) is 'is the previous char a new line', we don't really care.-- (this is to support ^,$ in regexes)[]->[]((_,ch):rest)->unfoldLexerl(st,(ch,rest))}-- | unfold lexer function into a function that returns a stream of (state x token)unfoldLexer::((AlexStatelexState,input)->Maybe(token,(AlexStatelexState,input)))->(AlexStatelexState,input)->[(AlexStatelexState,token)]unfoldLexerfb=casefbofNothing->[]Just(t,b')->(fstb,t):unfoldLexerfb'