{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RelaxedPolyRec #-} -- | A parser for 'Expr's. module ExprParser (parseExpr) where import Reify import Token import qualified ExprLexer as L import Expr import Annotations import qualified SavePos as S import Control.Monad import Control.Applicative import Control.Monad.Either import qualified Text.Parsec as P type ExprParser a = S.SatisfyA (Token L.ExprToken) ExprFam a pExpr :: ExprParser Expr pExpr = S.chainl pTerm (Add <$ tSymbol L.Plus <|> Sub <$ tSymbol L.Minus) pTerm :: ExprParser Expr pTerm = S.chainl pFactor (Mul <$ tSymbol L.Star <|> Div <$ tSymbol L.Slash) pFactor :: ExprParser Expr pFactor = pNum <|> tSymbol L.POpen *> pExpr <* tSymbol L.PClose pNum :: ExprParser Expr pNum = S.savePos $ (\(L.Num n) -> Num n) <$> tSatisfy L.isNum -- | Parses an expression, yielding the raw expression and annotated expression upon success. parseExpr :: String -> Either P.ParseError (Expr, WithBounds ExprFam Expr) parseExpr = P.runParser (L.pTokens <* P.eof) () "" >=> P.runParser (reify pExpr <* P.eof) () ""