packages feed

hesql-0.7: HESQL/Parser.hs

module HESQL.Parser (hesqlModule) where

import HESQL.Syntax
import Text.Parsec.String
import Text.Parsec
import Text.Parsec.Language (haskellDef)

import qualified Text.Parsec.Token as P
import Data.List (intercalate)

import Database.HsSqlPpp.Parsing.Parser


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

decls :: Parser [HesqlDecls]
decls = many decl

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

queryOpt :: Parser QueryOpt
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' :: Parser String
sqlStatement' = do
    r <- sqlQuoted "\"" <|> sqlQuoted "'"  <|> sqlTerminator
    if (r == ";") 
       then return r
       else do
          s <- sqlStatement
          return $ r++s 
    



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

sqlTerminator :: Parser String
sqlTerminator = string ";" 


funName :: Parser String
funName = identifier
parameter = identifier


   
moduleName = sepBy1 identifier (char '.')

moduleHeader = do
  reserved "module"
  m <- moduleName
  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