{-# LANGUAGE TupleSections #-} {-# LANGUAGE BlockArguments #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE DerivingVia #-} module Presyntax.Parser where import Control.Applicative import Control.Monad.State import qualified Data.Text as T import Data.Text (Text) import Presyntax.Lexer import Presyntax import Syntax data ParseError = UnexpectedEof Int Int | Unexpected Token | Empty | AltError ParseError ParseError deriving (Show) data ParseState = ParseState { ptTs :: [Token] , ptLine :: !Int , ptCol :: !Int } newtype Parser a = Parser { runParser :: ParseState -> Either ParseError (a, ParseState) } deriving ( Functor , Applicative , Monad , MonadState ParseState ) via (StateT ParseState (Either ParseError)) parseString :: Parser a -> String -> Either (Either LexError ParseError) a parseString (Parser k) s = case lexString s of Left e -> Left (Left e) Right xs -> case k (ParseState xs 0 0) of Left e -> Left (pure e) Right (x, _) -> Right x selectToken :: (Token -> Maybe a) -> Parser a selectToken k = Parser \case ParseState [] l c -> Left (UnexpectedEof l c) ParseState (x:xs) _ _ -> case k x of Just p -> pure (p, ParseState xs (tokLine x) (tokCol x)) Nothing -> Left (Unexpected x) expect :: TokenClass -> Parser () expect t = selectToken (\x -> if tokClass x == t then Just () else Nothing) var :: Parser Text var = selectToken \case Token _ _ _ _ (Tok_var v) -> pure v _ -> Nothing optionally :: Parser a -> Parser (Maybe a) optionally p = fmap Just p <|> pure Nothing braces :: Parser a -> Parser a braces k = do expect Tok_obrace x <- k expect Tok_cbrace pure x parens :: Parser a -> Parser a parens k = do expect Tok_oparen x <- k expect Tok_cparen pure x instance Alternative Parser where empty = Parser \_ -> Left Empty Parser kx <|> Parser ky = Parser \x -> case kx x of Right x -> Right x Left e -> case ky x of Left _ -> Left e Right y -> Right y attachPos :: Parser RawExpr -> Parser RawExpr attachPos k = do start <- gets (\(ParseState ~(x:_) _ _) -> (tokLine x, tokCol x - (tokOff x - tokSOff x))) x <- k end <- gets (\(ParseState _ l c) -> (l, c)) pure (RSrcPos start end x) body :: Parser RawExpr body = attachPos letExpr <|> attachPos lamExpr <|> attachPos exprPi where letExpr = do expect Tok_let n <- var expect Tok_colon t <- body letSmol n t <|> letBig n t letSmol n t = do expect Tok_equal d <- body expect Tok_semi Rlet n t d <$> body letBig n t = do expect Tok_semi selectToken \case Token _ _ _ _ (Tok_var n') | n' == n -> Just () _ -> Nothing args <- many arg expect Tok_equal d <- body expect Tok_semi Rlet n t (foldr lam d args) <$> body lamExpr = do expect Tok_lambda vs <- some arg expect Tok_arrow e <- body pure (foldr lam e vs) arg = fmap (Ex,) var <|> fmap (Im,) (braces var) lam (p, v) b = Rlam p v b exprPi :: Parser RawExpr exprPi = attachPos $ do bs <- optionally binder case bs of Just k -> foldl (.) id k <$> attachPos exprPi Nothing -> attachPos exprArr where binder = (some (parens (bind Ex) <|> braces (bind Im)) <* expect Tok_arrow) <|> (fmap pure (parens sigma) <* expect Tok_times) bind p = do names <- some var expect Tok_colon t <- exprPi pure (foldr (\n k -> Rpi p n t . k) id names) sigma = do n <- var expect Tok_colon Rsigma n <$> exprPi exprArr :: Parser RawExpr exprArr = attachPos $ do t <- attachPos exprApp c <- optionally (fmap (const True) (expect Tok_arrow) <|> fmap (const False) (expect Tok_times)) case c of Just True -> Rpi Ex (T.singleton '_') t <$> exprPi Just False -> Rsigma (T.singleton '_') t <$> exprPi Nothing -> pure t exprEq0 :: Parser RawExpr exprEq0 = attachPos $ do head <- atom spine <- many spineEntry pure (foldl app head spine) where spineEntry = fmap (Ex,) atom <|> fmap (Im,) (braces exprPi) app f (x, s) = Rapp x f s exprApp :: Parser RawExpr exprApp = attachPos $ do t <- exprEq0 c <- optionally (expect Tok_equiv) case c of Just () -> Req t <$> exprEq0 Nothing -> pure t atom0 :: Parser RawExpr atom0 = attachPos $ fmap Rvar var <|> fmap (const Rtype) (expect Tok_type) <|> fmap (const Rhole) (expect Tok_under) <|> fmap (const Rtop) (expect Tok_top) <|> fmap (const Rrefl) (expect Tok_refl) <|> fmap (const Rcoe) (expect Tok_coe) <|> fmap (const Rcong) (expect Tok_cong) <|> fmap (const Rsym) (expect Tok_sym) <|> fmap (const Runit) (parens (pure ())) <|> parens pair pair :: Parser RawExpr pair = attachPos $ do t <- body c <- optionally (expect Tok_comma) case c of Just () -> Rpair t <$> pair Nothing -> pure t atom :: Parser RawExpr atom = attachPos $ do e <- atom0 c <- many (selectToken (projection . tokClass)) pure $ case c of [] -> e sls -> foldl (flip ($)) e sls where projection Tok_proj1 = pure Rproj1 projection Tok_proj2 = pure Rproj2 projection _ = Nothing