gdritter repos s-cargot / v0.1.0.0 Data / SCargot / Comments.hs
v0.1.0.0

Tree @v0.1.0.0 (Download .tar.gz)

Comments.hs @v0.1.0.0

c843acc
 
 
69205b4
 
 
352b374
69205b4
c843acc
 
 
 
 
69205b4
c843acc
 
 
 
69205b4
c843acc
 
 
 
 
 
 
 
 
7b791ad
 
 
 
 
 
 
c843acc
352b374
 
 
 
c843acc
 
 
 
a4ea47a
 
c843acc
 
 
 
 
 
 
 
 
 
 
 
 
36be3ea
 
c843acc
 
 
 
a4ea47a
c843acc
 
 
 
 
 
 
 
352b374
c843acc
 
 
 
352b374
c843acc
 
 
 
352b374
c843acc
 
 
 
 
352b374
c843acc
 
 
 
 
352b374
c843acc
 
 
 
352b374
c843acc
 
 
 
352b374
c843acc
 
 
 
 
352b374
c843acc
 
 
 
 
352b374
c843acc
 
352b374
c843acc
 
 
352b374
 
c843acc
352b374
c843acc
 
352b374
c843acc
 
 
 
 
352b374
 
 
 
 
 
 
 
c843acc
 
 
69205b4
 
 
 
 
 
c843acc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
{-# LANGUAGE OverloadedStrings #-}

module Data.SCargot.Comments
  ( -- $intro

    -- * Lisp-Style Syntax

    -- $lisp
    withLispComments
    -- * Other Existing Comment Syntaxes
    -- ** Scripting Language Syntax
    -- $script
  , withOctothorpeComments
    -- ** C-Style Syntax
    -- $clike
  , withCLikeLineComments
  , withCLikeBlockComments
  , withCLikeComments
    -- ** Haskell-Style Syntax
    -- $haskell
  , withHaskellLineComments
  , withHaskellBlockComments
  , withHaskellComments
    -- * Comment Syntax Helper Functions
  , lineComment
  , simpleBlockComment
  ) where

import           Text.Parsec ( (<|>)
                             , anyChar
                             , manyTill
                             , noneOf
                             , skipMany
                             , string
                             )

import            Data.SCargot.Parse ( Comment
                                     , SExprParser
                                     , setComment
                                     )

-- | Given a string, produce a comment parser that matches that
--   initial string and ignores everything until the end of the
--   line.
lineComment :: String -> Comment
lineComment s = string s >> skipMany (noneOf "\n") >> return ()

-- | Given two strings, a begin and an end delimeter, produce a
--   parser that matches the beginning delimeter and then ignores
--   everything until it finds the end delimiter. This does not
--   consider nesting, so, for example, a comment created with
--
-- > curlyComment :: Comment
-- > curlyComment = simpleBlockComment "{" "}"
--
-- will consider
--
-- > { this { comment }
--
-- to be a complete comment, despite the apparent improper nesting.
-- This is analogous to standard C-style comments in which
--
-- > /* this /* comment */
--
-- is a complete comment.
simpleBlockComment :: String -> String -> Comment
simpleBlockComment begin end =
  string begin >>
  manyTill anyChar (string end) >>
  return ()

-- | Lisp-style line-oriented comments start with @;@ and last
--   until the end of the line. This is usually the comment
--   syntax you want.
withLispComments :: SExprParser t a -> SExprParser t a
withLispComments = setComment (lineComment ";")

-- | C++-like line-oriented comment start with @//@ and last
--   until the end of the line.
withCLikeLineComments :: SExprParser t a -> SExprParser t a
withCLikeLineComments = setComment (lineComment "//")

-- | C-like block comments start with @/*@ and end with @*/@.
--   They do not nest.
withCLikeBlockComments :: SExprParser t a -> SExprParser t a
withCLikeBlockComments = setComment (simpleBlockComment "/*" "*/")

-- | C-like comments include both line- and block-comments, the
--   former starting with @//@ and the latter contained within
--   @//* ... *//@.
withCLikeComments :: SExprParser t a -> SExprParser t a
withCLikeComments = setComment (lineComment "//" <|>
                                simpleBlockComment "/*" "*/")

-- | Haskell line-oriented comments start with @--@ and last
--   until the end of the line.
withHaskellLineComments :: SExprParser t a -> SExprParser t a
withHaskellLineComments = setComment (lineComment "--")

-- | Haskell block comments start with @{-@ and end with @-}@.
--   They do not nest.
withHaskellBlockComments :: SExprParser t a -> SExprParser t a
withHaskellBlockComments = setComment (simpleBlockComment "{-" "-}")

-- | Haskell comments include both the line-oriented @--@ comments
--   and the block-oriented @{- ... -}@ comments
withHaskellComments :: SExprParser t a -> SExprParser t a
withHaskellComments = setComment (lineComment "--" <|>
                                  simpleBlockComment "{-" "-}")

-- | Many scripting and shell languages use these, which begin with
--   @#@ and last until the end of the line.
withOctothorpeComments :: SExprParser t a -> SExprParser t a
withOctothorpeComments = setComment (lineComment "#")


{- $intro

By default a 'SExprParser' will not understand any kind of comment
syntax. Most varieties of s-expression will, however, want some kind
of commenting capability, so the below functions will produce a new
'SExprParser' which understands various kinds of comment syntaxes.

For example:

> mySpec :: SExprParser Text (SExpr Text)
> mySpec = asWellFormed $ mkParser (pack <$> many1 alphaNum)
>
> myLispySpec :: SExprParser Text (SExpr Text)
> myLispySpec = withLispComments mySpec
>
> myCLikeSpec :: SExprParser Text (SExpr Text)
> myCLikeSpec = withCLikeComment mySpec

We can then use these to parse s-expressions with different kinds of
comment syntaxes:

>>> decode mySpec "(foo ; a lisp comment\n  bar)\n"
Left "(line 1, column 6):\nunexpected \";\"\nexpecting space or atom"
>>> decode myLispySpec "(foo ; a lisp comment\n  bar)\n"
Right [WFSList [WFSAtom "foo", WFSAtom "bar"]]
>>> decode mySpec "(foo /* a c-like\n   comment */ bar)\n"
Left "(line 1, column 6):\nunexpected \"/\"\nexpecting space or atom"
>>> decode myCLikeSpec "(foo /* a c-like\n   comment */ bar)\n"
Right [WFSList [WFSAtom "foo", WFSAtom "bar"]]

-}

{- $lisp
> (one   ; a comment
>   two  ; another one
>   three)
-}

{- $script
> (one   # a comment
>   two  # another one
>   three)
-}

{- $clike
> (one // a comment
>   two /* another
>          one */
>   three)
-}

-- $haskell
-- > (one -- a comment
-- >   two {- another
-- >          one -}
-- >   three)