a type theory with equality based on setoids
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

219 lines
5.2 KiB

{-# 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