packages feed

hesql-0.6: HESQL/Parser.hs

module HESQL.Parser (hesqlModule) where

import HESQL.Syntax
import Text.Parsec.String
import Text.Parsec
import Text.Parsec.Language (haskellDef)
import Text.Parsec.Expr
import qualified Text.Parsec.Token as P
import Data.List (intercalate)
import Database.HDBC
import Control.Monad (forM_)

import Database.HsSqlPpp.Parsing.Parser


hesqlModule :: Parser HesqlModule
hesqlModule = do
  whiteSpace
  modName <- moduleHeader
  decls <- decls
  whiteSpace
  eof
  return $ HesqlModule modName decls

decls = many decl

decl = do
   fn <- funName
   p <- many parameter
   whiteSpace
   char '='
   whiteSpace
   queryOpt <- queryOpt
   stmtStr <- sqlStatement
   whiteSpace
   stmt <- 
     case parseSql stmtStr of
       Right [stmt] -> return stmt
       Left e -> error $ show e -- TODO proper error message, handle other Right cases
   return $ HesqlDecls fn p queryOpt stmt

queryOpt = 
   (reserved "maybe" >> return MaybeQuery) <|>
   (reserved "lazy" >> return LazyQuery) <|> 
   return StrictQuery

sqlStatement :: Parser String
sqlStatement = do
    s <- many (noneOf "\"';")
    r <- sqlStatement'
    return $ s ++ r 

sqlStatement' = do
    r <- sqlQuoted "\"" <|> sqlQuoted "'"  <|> sqlTerminator
    if (r == ";") 
       then return r
       else do
          s <- sqlStatement
          return $ r++s 
    



 
sqlQuoted s = do
  l <- between (string s) (string s) $ many qchars
  return $ s ++ concat l ++ s
 where qchars = many1 (noneOf ('\\':s)) <|> do 
                  c <- char '\\' 
                  q <- anyChar
                  return ['\\',  q]

sqlTerminator = string ";" 



funName = identifier
parameter = identifier


   
modName = sepBy1 identifier (char '.')

moduleHeader = do
  reserved "module"
  m <- modName
  reserved "where"
  return $ intercalate "." m 

lexer       = P.makeTokenParser haskellDef    
      
parens         = P.parens lexer
braces         = P.braces lexer
identifier     = P.identifier lexer
reserved       = P.reserved lexer
reservedOp     = P.reservedOp lexer
whiteSpace     = P.whiteSpace lexer
symbol         = P.symbol lexer
naturalOrFloat = P.naturalOrFloat lexer