packages feed

haskell-exp-parser (empty) → 0.1

raw patch · 5 files changed

+243/−0 lines, 5 filesdep +basedep +haskell-exp-parserdep +template-haskellsetup-changed

Dependencies added: base, haskell-exp-parser, template-haskell

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2015, Emil Axelsson++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Emil Axelsson nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ haskell-exp-parser.cabal view
@@ -0,0 +1,58 @@+name:           haskell-exp-parser+version:        0.1+synopsis:       Simple parser parser from Haskell to TemplateHaskell expressions+description:    This package defines a simple parser for a subset of Haskell expressions and patterns to the TemplateHaskell AST.+                .+                It provides a very lightweight alternative to the functions @parseExp@ and @parsePat@ from <http://hackage.haskell.org/package/haskell-src-meta>.+                .+                The following expressions are currently supported:+                .+                * Variables+                * Integer and string literals+                * Prefix function application+                * Lists and tuples+                .+                The following patterns are currently supported:+                .+                * Variables+license:        BSD3+license-file:   LICENSE+author:         Emil Axelsson+maintainer:     emax@chalmers.se+copyright:      Copyright (c) 2015, Emil Axelsson+homepage:       https://github.com/emilaxelsson/haskell-exp-parser+bug-reports:    https://github.com/emilaxelsson/haskell-exp-parser/issues+category:       Language+build-type:     Simple+cabal-version:  >=1.10++source-repository head+  type:     git+  location: git@github.com:emilaxelsson/haskell-exp-parser.git++library+  exposed-modules:+    Language.Haskell.ParseExp++  build-depends:+      base >=4 && <5,+      template-haskell++  hs-source-dirs: src++  default-language: Haskell2010++test-suite Tests+  type: exitcode-stdio-1.0++  hs-source-dirs: tests++  main-is: Splice.hs++  default-language: Haskell2010++  build-depends:+    base,+    haskell-exp-parser,+    template-haskell+
+ src/Language/Haskell/ParseExp.hs view
@@ -0,0 +1,129 @@+-- | Simple parser for a subset of Haskell expressions and patterns to the+-- TemplateHaskell AST+--+-- The following expressions are currently supported:+--+-- * Variables+-- * Integer and string literals+-- * Prefix function application+-- * Lists and tuples+--+-- The following patterns are currently supported:+--+-- * Variables++module Language.Haskell.ParseExp+  ( parseExp+  , parsePat+  ) where++++import Control.Monad+import Data.Char+import Language.Haskell.TH+import Text.ParserCombinators.ReadP++++-- | Skip any amount of whitespace+skipSpace :: ReadP ()+skipSpace = void $ munch isSpace++-- | Check if a character is a valid non-initial character in a name (variable+-- or constructor)+nameChar :: Char -> Bool+nameChar c = isAlphaNum c || elem c ['\'','_']++-- | Parse a Haskell variable name+name :: ReadP Name+name = do+    skipSpace+    h <- get+    guard ('a' <= h && h <= 'z')+    rest <- munch nameChar+    return $ mkName (h:rest)++-- | Parse a Haskell variable+variable :: ReadP Exp+variable = fmap VarE name++-- | Parse a Haskell Constructor+constructor :: ReadP Exp+constructor = do+    skipSpace+    h <- get+    guard ('A' <= h && h <= 'Z')+    rest <- munch nameChar+    return $ ConE $ mkName (h:rest)++-- | Parse an integer+integer :: Bool -> ReadP Integer+integer first = do+    c:_ <- look+    guard (first || isNumber c)+    readS_to_P reads++-- | Parse a Haskell literal+literal :: Bool -> ReadP Exp+literal first+    =   fmap (LitE . IntegerL) (integer first)+    <++ fmap (LitE . CharL) (readS_to_P reads)+    <++ fmap (LitE . StringL) (readS_to_P reads)++-- | Parse a comma-separated list of expressions+expressionList :: ReadP [Exp]+expressionList = expression `sepBy` char ','++-- | Parse a list expression+list :: ReadP Exp+list = fmap ListE $ between (char '[') (char ']') expressionList++-- | Parse a tuple expression+--+-- This also handles empty tuples ('()') and parenthesized expressions+tuple :: ReadP Exp+tuple = do+    es <- between (char '(') (char ')') (skipSpace >> expressionList)+      -- skipSpace needed to parse empty tuples with space inside+    case es of+        []  -> return $ ConE $ mkName "()"+        [e] -> return e+        _   -> return $ TupE es++-- | Parse an expression that is not an application+expPart :: Bool -> ReadP Exp+expPart first = do+    skipSpace+    pfail <++ variable+          <++ constructor+          <++ list+          <++ literal first+          <++ tuple+  -- Must handle lists before literals, because the "['a']" is accepted as a+  -- String literal++-- | Expression parser+expression :: ReadP Exp+expression = do+    skipSpace+    f    <- expPart True+    args <- many (expPart False)+    let expr = foldl AppE f args+    skipSpace+    return expr++-- | Parse a Haskell expression (the supported subset is given above)+parseExp :: String -> Either String Exp+parseExp str = case [expr | (expr,"") <- readP_to_S expression str] of+    [expr] -> return expr+    _ -> fail $ "parseExp: cannot parse '" ++ str ++ "'"+             ++ " (parseExp only supports a limited subset of Haskell)"++-- | Parse a Haskell pattern (the supported subset is given above)+parsePat :: String -> Either String Pat+parsePat str = case [pat | (pat,"") <- readP_to_S name str] of+    [pat] -> return (VarP pat)+    _ -> fail $ "parsePat: cannot parse '" ++ str ++ "'"+             ++ " (parsePat only supports a limited subset of Haskell)"+
+ tests/Splice.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE TemplateHaskell #-}++import System.Exit++import ParseExp++++tests =+    [ (show ($exp1), show "sdf")+    , (show ($exp2), show (sum [1,2,3]))+    , (show ($exp3), show (min (max (negate (-34)) 888) (signum (-45))))+    , (show ($exp4), show (  min   (  max   (  negate   (  -  34  )  )   888  )   (   signum    (  - 45   )   )  ))+    , (show ($exp5), show ([(1,'a'),(2,'b'),(3,'c')]))+    ]++main = if and oks+    then putStrLn "All tests passed"+    else do+      putStrLn $ "Tests " ++ show [i | (i,False) <- zip [1..] oks] ++ " failed"+      exitFailure+  where+    oks = map (uncurry (==)) tests+