------------------------------------------------------------------------------- |-- Module : Text.Parser.Token.Style-- Copyright : (c) Edward Kmett 2011-2012-- License : BSD3---- Maintainer : ekmett@gmail.com-- Stability : provisional-- Portability : non-portable---- A toolbox for specifying comment and identifier styles---- This must be imported directly as it is not re-exported elsewhere-------------------------------------------------------------------------------moduleText.Parser.Token.Style(-- * Comment and white space stylesCommentStyle(..)-- ** Lenses,commentStart,commentEnd,commentLine,commentNesting-- ** Common Comment Styles,emptyCommentStyle,javaCommentStyle,haskellCommentStyle,buildSomeSpaceParser-- * Identifier Styles,emptyIdents,haskellIdents,haskell98Idents-- * Operator Styles,emptyOps,haskellOps,haskell98Ops)whereimportControl.ApplicativeimportqualifiedData.HashSetasHashSetimportData.HashSet(HashSet)importData.MonoidimportText.Parser.CombinatorsimportText.Parser.CharimportText.Parser.TokenimportText.Parser.Token.HighlightimportData.List(nub)-- | How to deal with comments.dataCommentStyle=CommentStyle{_commentStart::String-- ^ String that starts a multiline comment,_commentEnd::String-- ^ String that ends a multiline comment,_commentLine::String-- ^ String that starts a single line comment,_commentNesting::Bool-- ^ Can we nest multiline comments?}-- | This is a lens that can edit the string that starts a multiline comment.---- @'commentStart' :: Lens' 'CommentStyle' 'String'@commentStart::Functorf=>(String->fString)->CommentStyle->fCommentStylecommentStartf(CommentStyleseln)=(\s'->CommentStyles'eln)<$>fs{-# INLINE commentStart #-}-- | This is a lens that can edit the string that ends a multiline comment.---- @'commentEnd' :: Lens' 'CommentStyle' 'String'@commentEnd::Functorf=>(String->fString)->CommentStyle->fCommentStylecommentEndf(CommentStyleseln)=(\e'->CommentStylese'ln)<$>fe{-# INLINE commentEnd #-}-- | This is a lens that can edit the string that starts a single line comment.---- @'commentLine' :: Lens' 'CommentStyle' 'String'@commentLine::Functorf=>(String->fString)->CommentStyle->fCommentStylecommentLinef(CommentStyleseln)=(\l'->CommentStylesel'n)<$>fl{-# INLINE commentLine #-}-- | This is a lens that can edit whether we can nest multiline comments.---- @'commentNesting' :: Lens' 'CommentStyle' 'Bool'@commentNesting::Functorf=>(Bool->fBool)->CommentStyle->fCommentStylecommentNestingf(CommentStyleseln)=CommentStylesel<$>fn{-# INLINE commentNesting #-}-- | No comments at allemptyCommentStyle::CommentStyleemptyCommentStyle=CommentStyle""""""True-- | Use java-style commentsjavaCommentStyle::CommentStylejavaCommentStyle=CommentStyle"/*""*/""//"True-- | Use haskell-style commentshaskellCommentStyle::CommentStylehaskellCommentStyle=CommentStyle"{-""-}""--"True-- | Use this to easily build the definition of whiteSpace for your MonadParser-- given a comment style and an underlying someWhiteSpace parserbuildSomeSpaceParser::CharParsingm=>m()->CommentStyle->m()buildSomeSpaceParsersimpleSpace(CommentStylestartStyleendStylelineStylenestingStyle)|noLine&&noMulti=skipSome(simpleSpace<?>"")|noLine=skipSome(simpleSpace<|>multiLineComment<?>"")|noMulti=skipSome(simpleSpace<|>oneLineComment<?>"")|otherwise=skipSome(simpleSpace<|>oneLineComment<|>multiLineComment<?>"")wherenoLine=nulllineStylenoMulti=nullstartStyleoneLineComment=try(stringlineStyle)*>skipMany(satisfy(/='\n'))multiLineComment=try(stringstartStyle)*>inCommentinComment=ifnestingStyletheninCommentMultielseinCommentSingleinCommentMulti=()<$try(stringendStyle)<|>multiLineComment*>inCommentMulti<|>skipSome(noneOfstartEnd)*>inCommentMulti<|>oneOfstartEnd*>inCommentMulti<?>"end of comment"startEnd=nub(endStyle++startStyle)inCommentSingle=()<$try(stringendStyle)<|>skipSome(noneOfstartEnd)*>inCommentSingle<|>oneOfstartEnd*>inCommentSingle<?>"end of comment"set::[String]->HashSetStringset=HashSet.fromList-- | A simple operator style based on haskell with no reserved operatorsemptyOps::TokenParsingm=>IdentifierStylememptyOps=IdentifierStyle{_styleName="operator",_styleStart=_styleLetteremptyOps,_styleLetter=oneOf":!#$%&*+./<=>?@\\^|-~",_styleReserved=mempty,_styleHighlight=Operator,_styleReservedHighlight=ReservedOperator}-- | A simple operator style based on haskell with the operators from Haskell 98.haskell98Ops,haskellOps::TokenParsingm=>IdentifierStylemhaskell98Ops=emptyOps{_styleReserved=set["::","..","=","\\","|","<-","->","@","~","=>"]}haskellOps=haskell98Ops-- | A simple identifier style based on haskell with no reserve wordsemptyIdents::TokenParsingm=>IdentifierStylememptyIdents=IdentifierStyle{_styleName="identifier",_styleStart=letter<|>char'_',_styleLetter=alphaNum<|>oneOf"_'",_styleReserved=set[],_styleHighlight=Identifier,_styleReservedHighlight=ReservedIdentifier}-- | A simple identifier style based on haskell with only the reserved words from Haskell 98.haskell98Idents::TokenParsingm=>IdentifierStylemhaskell98Idents=emptyIdents{_styleReserved=sethaskell98ReservedIdents}-- | A simple identifier style based on haskell with the reserved words from Haskell 98 and some common extensions.haskellIdents::TokenParsingm=>IdentifierStylemhaskellIdents=haskell98Idents{_styleLetter=_styleLetterhaskell98Idents<|>char'#',_styleReserved=set$haskell98ReservedIdents++["foreign","import","export","primitive","_ccall_","_casm_","forall"]}haskell98ReservedIdents::[String]haskell98ReservedIdents=["let","in","case","of","if","then","else","data","type","class","default","deriving","do","import","infix","infixl","infixr","instance","module","newtype","where","primitive"-- "as","qualified","hiding"]