packages feed

LslPlus-0.1.2: src/Language/Lsl/QQ.hs

{-# LANGUAGE TemplateHaskell #-}
module Language.Lsl.QQ(lslm,lsl) where

import Data.Generics.Aliases(extQ)
import qualified Language.Haskell.TH as TH
import Language.Haskell.TH.Quote(QuasiQuoter(..),dataToPatQ,dataToExpQ)
import Language.Lsl.Syntax(Expr(..))
import Language.Lsl.Parse(parseModuleFromStringAQ,parseScriptFromStringAQ)
import Text.ParserCombinators.Parsec.Error(errorPos,errorMessages,showErrorMessages)
import Text.ParserCombinators.Parsec.Pos

aqe (AQString v) = Just $ TH.appE (TH.conE 'StringLit) $ TH.varE $ TH.mkName v
aqe (AQInteger v) = Just $ TH.appE (TH.conE 'IntLit) $ TH.varE $ TH.mkName v
aqe (AQKey v) = Just $ TH.appE (TH.conE 'KeyLit) $ TH.varE $ TH.mkName v
aqe (AQFloat v) = Just $ TH.appE (TH.conE 'FloatLit) $ TH.varE $ TH.mkName v
aqe _ = Nothing
aqp (AQString v) = Just $ TH.conP 'StringLit [TH.varP $ TH.mkName v]
aqp (AQInteger v) = Just $ TH.conP 'IntLit [TH.varP $ TH.mkName v]
aqp (AQKey v) = Just $ TH.conP 'KeyLit [TH.varP $ TH.mkName v]
aqp (AQFloat v) = Just $ TH.conP 'FloatLit [TH.varP $ TH.mkName v]
aqp _ = Nothing

lslModulePat :: String -> TH.Q TH.Pat
lslModulePat s = 
    case parseModuleFromStringAQ s of 
        Left err -> let (pos,msgs) = (errorPos err, errorMessages err) in do
            l <- TH.location
            let (line,col) = TH.loc_start l
            let (line1, col1) = (sourceLine pos, sourceColumn pos)
            fail $ "at " ++ show (line + line1 - 1) ++ ":" ++ show (col1) ++ ": "  ++
                   showErrorMessages "or" "unknown" "expecting" "unexpected" "end of input" msgs
        Right x -> dataToPatQ (const Nothing `extQ` aqp) x
lslModuleExp :: String -> TH.Q TH.Exp
lslModuleExp s = 
    case parseModuleFromStringAQ s of 
        Left err -> let (pos,msgs) = (errorPos err, errorMessages err) in do
            l <- TH.location
            let (line,col) = TH.loc_start l
            let (line1, col1) = (sourceLine pos, sourceColumn pos)
            fail $ "at " ++ show (line + line1 - 1) ++ ":" ++ show (col1) ++ ": "  ++
                   showErrorMessages "or" "unknown" "expecting" "unexpected" "end of input" msgs
        Right x -> dataToExpQ (const Nothing `extQ` aqe) x

-- | A quasi-quoter for an LSL (Plus) module.
lslm :: QuasiQuoter
lslm = QuasiQuoter lslModuleExp lslModulePat

lslScriptPat :: String -> TH.Q TH.Pat
lslScriptPat s = 
    case parseScriptFromStringAQ s of 
        Left err -> let (pos,msgs) = (errorPos err, errorMessages err) in do
            l <- TH.location
            let (line,col) = TH.loc_start l
            let (line1, col1) = (sourceLine pos, sourceColumn pos)
            fail $ "at " ++ show (line + line1 - 1) ++ ":" ++ show (col1) ++ ": "  ++
                   showErrorMessages "or" "unknown" "expecting" "unexpected" "end of input" msgs
        Right x -> dataToPatQ (const Nothing `extQ` aqp) x
lslScriptExp :: String -> TH.Q TH.Exp
lslScriptExp s = 
    case parseScriptFromStringAQ s of 
        Left err -> let (pos,msgs) = (errorPos err, errorMessages err) in do
            l <- TH.location
            let (line,col) = TH.loc_start l
            let (line1, col1) = (sourceLine pos, sourceColumn pos)
            fail $ "at " ++ show (line + line1 - 1) ++ ":" ++ show (col1) ++ ": "  ++
                   showErrorMessages "or" "unknown" "expecting" "unexpected" "end of input" msgs
        Right x -> dataToExpQ (const Nothing `extQ` aqe) x

-- | A quasi-quoter for an LSL script.
lsl :: QuasiQuoter
lsl = QuasiQuoter lslScriptExp lslScriptPat