more parser goodness

This commit is contained in:
William Ball 2024-11-30 21:05:07 -08:00
parent b236bb1753
commit 6ab03dd6c6
4 changed files with 43 additions and 31 deletions

View file

@ -33,7 +33,6 @@ findType g (Var x n) = do
validateType g t validateType g t
pure t pure t
findType _ (Free n) = envLookupTy n findType _ (Free n) = envLookupTy n
findType _ (Axiom n) = envLookupTy n
findType g e@(App m n) = do findType g e@(App m n) = do
(a, b) <- findType g m >>= matchPi m (a, b) <- findType g m >>= matchPi m
a' <- findType g n a' <- findType g n

View file

@ -3,7 +3,6 @@ module Expr where
data Expr where data Expr where
Var :: Text -> Integer -> Expr Var :: Text -> Integer -> Expr
Free :: Text -> Expr Free :: Text -> Expr
Axiom :: Text -> Expr
Level :: Integer -> Expr Level :: Integer -> Expr
App :: Expr -> Expr -> Expr App :: Expr -> Expr -> Expr
Abs :: Text -> Expr -> Expr -> Expr Abs :: Text -> Expr -> Expr -> Expr
@ -14,7 +13,6 @@ data Expr where
instance Eq Expr where instance Eq Expr where
(Var _ n) == (Var _ m) = n == m (Var _ n) == (Var _ m) = n == m
(Free s) == (Free t) = s == t (Free s) == (Free t) = s == t
(Axiom a) == (Axiom b) = a == b
(Level i) == (Level j) = i == j (Level i) == (Level j) = i == j
(App e1 e2) == (App f1 f2) = e1 == f1 && e2 == f2 (App e1 e2) == (App f1 f2) = e1 == f1 && e2 == f2
(Abs _ t1 b1) == (Abs _ t2 b2) = t1 == t2 && b1 == b2 (Abs _ t1 b1) == (Abs _ t2 b2) = t1 == t2 && b1 == b2
@ -25,7 +23,6 @@ instance Eq Expr where
occursFree :: Integer -> Expr -> Bool occursFree :: Integer -> Expr -> Bool
occursFree n (Var _ k) = n == k occursFree n (Var _ k) = n == k
occursFree _ (Free _) = False occursFree _ (Free _) = False
occursFree _ (Axiom _) = False
occursFree _ (Level _) = False occursFree _ (Level _) = False
occursFree n (App a b) = on (||) (occursFree n) a b occursFree n (App a b) = on (||) (occursFree n) a b
occursFree n (Abs _ a b) = occursFree n a || occursFree (n + 1) b occursFree n (Abs _ a b) = occursFree n a || occursFree (n + 1) b
@ -37,7 +34,6 @@ shiftIndices d c (Var x k)
| k >= c = Var x (k + d) | k >= c = Var x (k + d)
| otherwise = Var x k | otherwise = Var x k
shiftIndices _ _ (Free s) = Free s shiftIndices _ _ (Free s) = Free s
shiftIndices _ _ (Axiom s) = Axiom s
shiftIndices _ _ (Level i) = Level i shiftIndices _ _ (Level i) = Level i
shiftIndices d c (App m n) = App (shiftIndices d c m) (shiftIndices d c n) shiftIndices d c (App m n) = App (shiftIndices d c m) (shiftIndices d c n)
shiftIndices d c (Abs x m n) = Abs x (shiftIndices d c m) (shiftIndices d (c + 1) n) shiftIndices d c (Abs x m n) = Abs x (shiftIndices d c m) (shiftIndices d (c + 1) n)
@ -109,7 +105,6 @@ showBinding (ident, params, val) =
helper :: Integer -> Expr -> Text helper :: Integer -> Expr -> Text
helper _ (Var s _) = s helper _ (Var s _) = s
helper _ (Free s) = s helper _ (Free s) = s
helper _ (Axiom s) = s
helper _ (Level i) helper _ (Level i)
| i == 0 = "*" | i == 0 = "*"
| otherwise = "*" <> show i | otherwise = "*" <> show i

View file

@ -8,7 +8,6 @@ type Param = (Text, IRExpr)
data IRExpr data IRExpr
= Var {_varName :: Text} = Var {_varName :: Text}
| Axiom
| Level {_level :: Integer} | Level {_level :: Integer}
| App | App
{ _appFunc :: IRExpr { _appFunc :: IRExpr
@ -34,11 +33,17 @@ data IRExpr
makeLenses ''IRExpr makeLenses ''IRExpr
data IRDef = Def data IRDef
= Def
{ _defName :: Text { _defName :: Text
, _defParams :: [Param] , _defParams :: [Param]
, _defAscription :: Maybe IRExpr , _defAscription :: Maybe IRExpr
, _defBody :: IRExpr , _defBody :: IRExpr
} }
| Axiom
{ _axiomName :: Text
, _axiomParams :: [Param]
, _axiomAscription :: IRExpr
}
type IRProgram = [IRDef] type IRProgram = [IRDef]

View file

@ -3,12 +3,13 @@
module Parser where module Parser where
import Control.Monad.Except import Control.Monad.Except
import Data.Char
import Data.List (foldl1) import Data.List (foldl1)
import qualified Data.Text as T import qualified Data.Text as T
import Errors (Error (..)) import Errors (Error (..))
import IR import IR
import Preprocessor import Preprocessor
import Text.Megaparsec (Parsec, ShowErrorComponent (..), between, choice, chunk, errorBundlePretty, label, runParser, try) import Text.Megaparsec (Parsec, ShowErrorComponent (..), between, choice, chunk, errorBundlePretty, label, runParser, satisfy, try)
import Text.Megaparsec.Char import Text.Megaparsec.Char
import qualified Text.Megaparsec.Char.Lexer as L import qualified Text.Megaparsec.Char.Lexer as L
@ -34,17 +35,19 @@ eat :: Text -> Parser ()
eat = void . lexeme . chunk eat = void . lexeme . chunk
keywords :: [Text] keywords :: [Text]
keywords = ["forall", "let", "in", "end", "fun"] keywords = ["forall", "let", "in", "end", "fun", "def", "axiom"]
reservedChars :: [Char]
reservedChars = "();:"
pIdentifier :: Parser Text pIdentifier :: Parser Text
pIdentifier = try $ label "identifier" $ lexeme $ do pIdentifier = try $ label "identifier" $ lexeme $ do
firstChar <- letterChar <|> char '_' chars <- many $ satisfy isAllowed
rest <- many $ alphaNumChar <|> char '_' let ident = T.pack chars
let ident = T.pack (firstChar : rest) when (ident `elem` keywords) $ fail $ "Reserved word: " ++ T.unpack ident
when (ident `elem` keywords) $
fail $
"Reserved word: " ++ T.unpack ident
pure ident pure ident
where
isAllowed c = isLetter c || isNumber c || c == '_' || isSymbol c && c `notElem` reservedChars
pVar :: Parser IRExpr pVar :: Parser IRExpr
pVar = label "variable" $ lexeme $ Var <$> pIdentifier pVar = label "variable" $ lexeme $ Var <$> pIdentifier
@ -86,7 +89,7 @@ pBinding = lexeme $ label "binding" $ do
eat "(" eat "("
ident <- pIdentifier ident <- pIdentifier
params <- pManyParams params <- pManyParams
ascription <- pAscription ascription <- optional pAscription
eat ":=" eat ":="
value <- pIRExpr value <- pIRExpr
eat ")" eat ")"
@ -126,20 +129,31 @@ pNumSort = lexeme $ label "sort" $ eat "*" >> Level <$> L.decimal
pSort :: Parser IRExpr pSort :: Parser IRExpr
pSort = try pNumSort <|> pStar pSort = try pNumSort <|> pStar
pAxiom :: Parser IRExpr pAxiom :: Parser IRDef
pAxiom = Axiom <$ eat "axiom" pAxiom = lexeme $ label "axiom" $ do
pIRDef :: Parser IRDef
pIRDef = lexeme $ label "definition" $ do
skipSpace skipSpace
eat "def"
ident <- pIdentifier ident <- pIdentifier
params <- pManyParams params <- pManyParams
ascription <- fmap (flip (foldr (uncurry Pi)) params) <$> pAscription ascription <- fmap (flip (foldr (uncurry Pi)) params) pAscription
eat ";"
pure $ Axiom ident params ascription
pDef :: Parser IRDef
pDef = lexeme $ label "definition" $ do
skipSpace
eat "def"
ident <- pIdentifier
params <- pManyParams
ascription <- fmap (flip (foldr (uncurry Pi)) params) <$> optional pAscription
eat ":=" eat ":="
body <- pIRExpr body <- pIRExpr
eat ";" eat ";"
pure $ Def ident params ascription body pure $ Def ident params ascription body
pIRDef :: Parser IRDef
pIRDef = pDef <|> pAxiom
pTerm :: Parser IRExpr pTerm :: Parser IRExpr
pTerm = pTerm =
lexeme $ lexeme $
@ -147,7 +161,6 @@ pTerm =
choice choice
[ between (char '(') (char ')') pIRExpr [ between (char '(') (char ')') pIRExpr
, pSort , pSort
, pAxiom
, pVar , pVar
] ]
@ -164,8 +177,8 @@ pAppTerm =
pIRExpr :: Parser IRExpr pIRExpr :: Parser IRExpr
pIRExpr = lexeme $ try pArrow <|> pAppTerm pIRExpr = lexeme $ try pArrow <|> pAppTerm
pAscription :: Parser (Maybe IRExpr) pAscription :: Parser IRExpr
pAscription = lexeme $ optional $ try $ eat ":" >> label "type" pIRExpr pAscription = lexeme $ try $ eat ":" >> label "type" pIRExpr
pIRProgram :: Parser IRProgram pIRProgram :: Parser IRProgram
pIRProgram = many pIRDef pIRProgram = many pIRDef