astview-0.1: data/ExprParser.hs
{-# LANGUAGE DeriveDataTypeable #-}
module ExprParser where
-- container
import Data.Tree (Tree(Node,rootLabel))
-- syb
import Data.Generics (Data)
-- base
import Unsafe.Coerce (unsafeCoerce)
-- local imports
import Language.Astview.Parser as Astview
import Language.Astview.DataTree
-- Parsec (CSV Parser)
import Text.ParserCombinators.Parsec as Parsec
import Data.Generics hiding (Infix)
import Text.ParserCombinators.Parsec
import qualified Text.ParserCombinators.Parsec.Token as P
import Text.ParserCombinators.Parsec.Language (javaStyle)
import Text.ParserCombinators.Parsec.Expr
expr = Parser "Expr" [".expr"] buildTreeExpr
-- Expr
buildTreeExpr :: String -> Tree String
buildTreeExpr s = case parseExpr s of
Right ast -> flat $ data2tree (ast::Expr)
Left ParseError -> Node "ParseError" []
parseExpr :: (Data a) => String -> Either Astview.ParseError a
parseExpr s = case parse lexedExpr "unknown" s of
Right p -> unsafeCoerce $ Right p
_ -> Left ParseError
-- ------------ a parsec parser ----------------------
-- a very tiny expr language deriving data
data Expr = Add Expr Expr | Sub Expr Expr | I Integer deriving (Show,Data,Typeable)
runLex :: Show a => Parsec.Parser a -> String -> IO ()
runLex p input
= parseTest (do{ whiteSpace
; x <- p
; eof
; return x
}) input
lexedExpr = do { whiteSpace
; x <- expr'
; eof
; return x
}
expr' :: Parsec.Parser Expr
expr' = buildExpressionParser table subexpr <?> "expression"
subexpr = parens expr'
<|> myint
<?> "subexpr"
myint = do {n <- natural; return (I n) }
table = [[op "+" Add AssocLeft, op "-" Sub AssocLeft]]
where
op s f assoc
= Infix (do{ reservedOp s; return f}) assoc
lexer :: P.TokenParser ()
lexer = P.makeTokenParser
(javaStyle { P.reservedOpNames = ["+","-"] })
whiteSpace = P.whiteSpace lexer
lexeme = P.lexeme lexer
symbol = P.symbol lexer
natural = P.natural lexer
parens = P.parens lexer
semi = P.semi lexer
identifier= P.identifier lexer
reserved = P.reserved lexer
reservedOp= P.reservedOp lexer