Files
rlp/src/Rlp/Parse.y
crumbtoo 2e13ec2cf4 microlens -> lens
i still love you microlens..
2024-02-13 13:42:43 -07:00

313 lines
10 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
{-# LANGUAGE LambdaCase, ViewPatterns #-}
module Rlp.Parse
( parseRlpProg
, parseRlpProgR
, parseRlpExpr
, parseRlpExprR
)
where
import Compiler.RlpcError
import Compiler.RLPC
import Rlp.Lex
import Rlp.Syntax
import Rlp.Parse.Types
import Rlp.Parse.Associate
import Control.Lens hiding (snoc, (.>), (<.), (<<~))
import Data.List.Extra
import Data.Fix
import Data.Functor.Const
import Data.Functor.Apply
import Data.Functor.Bind
import Control.Comonad
import Data.Functor
import Data.Semigroup.Traversable
import Data.Text (Text)
import Data.Text qualified as T
import Data.Void
import Compiler.Types
}
%name parseRlpProg StandaloneProgram
%name parseRlpExpr StandaloneExpr
%monad { P }
%lexer { lexCont } { Located _ TokenEOF }
%error { parseError }
%errorhandlertype explist
%tokentype { Located RlpToken }
%token
varname { Located _ (TokenVarName _) }
conname { Located _ (TokenConName _) }
consym { Located _ (TokenConSym _) }
varsym { Located _ (TokenVarSym _) }
data { Located _ TokenData }
case { Located _ TokenCase }
of { Located _ TokenOf }
litint { Located _ (TokenLitInt _) }
'=' { Located _ TokenEquals }
'|' { Located _ TokenPipe }
'::' { Located _ TokenHasType }
';' { Located _ TokenSemicolon }
'(' { Located _ TokenLParen }
')' { Located _ TokenRParen }
'->' { Located _ TokenArrow }
vsemi { Located _ TokenSemicolonV }
'{' { Located _ TokenLBrace }
'}' { Located _ TokenRBrace }
vlbrace { Located _ TokenLBraceV }
vrbrace { Located _ TokenRBraceV }
infixl { Located _ TokenInfixL }
infixr { Located _ TokenInfixR }
infix { Located _ TokenInfix }
let { Located _ TokenLet }
letrec { Located _ TokenLetrec }
in { Located _ TokenIn }
%nonassoc '='
%right '->'
%right in
%%
StandaloneProgram :: { RlpProgram RlpcPs }
StandaloneProgram : '{' Decls '}' {% mkProgram $2 }
| VL DeclsV VR {% mkProgram $2 }
StandaloneExpr :: { RlpExpr RlpcPs }
: VL Expr VR { extract $2 }
VL :: { () }
VL : vlbrace { () }
VR :: { () }
VR : vrbrace { () }
| error { () }
Decls :: { [Decl' RlpcPs] }
Decls : Decl ';' Decls { $1 : $3 }
| Decl ';' { [$1] }
| Decl { [$1] }
DeclsV :: { [Decl' RlpcPs] }
DeclsV : Decl VS DeclsV { $1 : $3 }
| Decl VS { [$1] }
| Decl { [$1] }
VS :: { Located RlpToken }
VS : ';' { $1 }
| vsemi { $1 }
Decl :: { Decl' RlpcPs }
: FunDecl { $1 }
| TySigDecl { $1 }
| DataDecl { $1 }
| InfixDecl { $1 }
TySigDecl :: { Decl' RlpcPs }
: Var '::' Type { (\e -> TySigD [extract e]) <<~ $1 <~> $3 }
InfixDecl :: { Decl' RlpcPs }
: InfixWord litint InfixOp { $1 =>> \w ->
InfixD (extract $1) (extractInt $ extract $2)
(extract $3) }
InfixWord :: { Located Assoc }
: infixl { $1 \$> InfixL }
| infixr { $1 \$> InfixR }
| infix { $1 \$> Infix }
DataDecl :: { Decl' RlpcPs }
: data Con TyParams '=' DataCons { $1 \$> DataD (extract $2) $3 $5 }
TyParams :: { [PsName] }
: {- epsilon -} { [] }
| TyParams varname { $1 `snoc` (extractName . extract $ $2) }
DataCons :: { [ConAlt RlpcPs] }
: DataCons '|' DataCon { $1 `snoc` $3 }
| DataCon { [$1] }
DataCon :: { ConAlt RlpcPs }
: Con Type1s { ConAlt (extract $1) $2 }
Type1s :: { [RlpType' RlpcPs] }
: {- epsilon -} { [] }
| Type1s Type1 { $1 `snoc` $2 }
Type1 :: { RlpType' RlpcPs }
: '(' Type ')' { $2 }
| conname { fmap ConT (mkPsName $1) }
| varname { fmap VarT (mkPsName $1) }
Type :: { RlpType' RlpcPs }
: Type '->' Type { FunT <<~ $1 <~> $3 }
| TypeApp { $1 }
TypeApp :: { RlpType' RlpcPs }
: Type1 { $1 }
| TypeApp Type1 { AppT <<~ $1 <~> $2 }
FunDecl :: { Decl' RlpcPs }
FunDecl : Var Params '=' Expr { $4 =>> \e ->
FunD (extract $1) $2 e Nothing }
Params :: { [Pat' RlpcPs] }
Params : {- epsilon -} { [] }
| Params Pat1 { $1 `snoc` $2 }
Pat :: { Pat' RlpcPs }
: Con Pat1s { $1 =>> \cn ->
ConP (extract $1) $2 }
| Pat1 { $1 }
Pat1s :: { [Pat' RlpcPs] }
: Pat1s Pat1 { $1 `snoc` $2 }
| Pat1 { [$1] }
Pat1 :: { Pat' RlpcPs }
: Con { fmap (`ConP` []) $1 }
| Var { fmap VarP $1 }
| Lit { LitP <<= $1 }
| '(' Pat ')' { $1 .> $2 <. $3 }
Expr :: { RlpExpr' RlpcPs }
-- infixities delayed till next release :(
-- : Expr1 InfixOp Expr { $2 =>> \o ->
-- OAppE (extract o) $1 $3 }
: TempInfixExpr { $1 }
| LetExpr { $1 }
| CaseExpr { $1 }
| AppExpr { $1 }
TempInfixExpr :: { RlpExpr' RlpcPs }
TempInfixExpr : Expr1 InfixOp TempInfixExpr {% tempInfixExprErr $1 $3 }
| Expr1 InfixOp Expr1 { $2 =>> \o ->
OAppE (extract o) $1 $3 }
AppExpr :: { RlpExpr' RlpcPs }
: Expr1 { $1 }
| AppExpr Expr1 { AppE <<~ $1 <~> $2 }
LetExpr :: { RlpExpr' RlpcPs }
: let layout1(Binding) in Expr { $1 \$> LetE $2 $4 }
| letrec layout1(Binding) in Expr { $1 \$> LetrecE $2 $4 }
CaseExpr :: { RlpExpr' RlpcPs }
: case Expr of layout0(CaseAlt)
{ CaseE <<~ $2 <#> $4 }
-- TODO: where-binds
CaseAlt :: { (Alt RlpcPs, Where RlpcPs) }
: Alt { ($1, []) }
Alt :: { Alt RlpcPs }
: Pat '->' Expr { AltA $1 $3 }
-- layout0(p : β) :: [β]
layout0(p) : '{' layout_list0(';',p) '}' { $2 }
| VL layout_list0(VS,p) VR { $2 }
-- layout_list0(sep : α, p : β) :: [β]
layout_list0(sep,p) : p { [$1] }
| layout_list1(sep,p) sep p { $1 `snoc` $3 }
| {- epsilon -} { [] }
-- layout1(p : β) :: [β]
layout1(p) : '{' layout_list1(';',p) '}' { $2 }
| VL layout_list1(VS,p) VR { $2 }
-- layout_list1(sep : α, p : β) :: [β]
layout_list1(sep,p) : p { [$1] }
| layout_list1(sep,p) sep p { $1 `snoc` $3 }
Binding :: { Binding' RlpcPs }
: Pat '=' Expr { PatB <<~ $1 <~> $3 }
Expr1 :: { RlpExpr' RlpcPs }
: '(' Expr ')' { $1 .> $2 <. $3 }
| Lit { fmap LitE $1 }
| Var { fmap VarE $1 }
| Con { fmap VarE $1 }
InfixOp :: { Located PsName }
: consym { mkPsName $1 }
| varsym { mkPsName $1 }
-- TODO: microlens-pro save me microlens-pro (rewrite this with prisms)
Lit :: { Lit' RlpcPs }
: litint { $1 <&> (IntL . (\ (TokenLitInt n) -> n)) }
Var :: { Located PsName }
Var : varname { mkPsName $1 }
| varsym { mkPsName $1 }
Con :: { Located PsName }
: conname { mkPsName $1 }
{
parseRlpExprR :: (Monad m) => Text -> RLPCT m (RlpExpr RlpcPs)
parseRlpExprR s = liftErrorful $ pToErrorful parseRlpExpr st
where
st = programInitState s
parseRlpProgR :: (Monad m) => Text -> RLPCT m (RlpProgram RlpcPs)
parseRlpProgR s = do
a <- liftErrorful $ pToErrorful parseRlpProg st
addDebugMsg @_ @String "dump-parsed" $ show a
pure a
where
st = programInitState s
mkPsName :: Located RlpToken -> Located PsName
mkPsName = fmap extractName
extractName :: RlpToken -> PsName
extractName = \case
TokenVarName n -> n
TokenConName n -> n
TokenConSym n -> n
TokenVarSym n -> n
_ -> error "mkPsName: not an identifier"
extractInt :: RlpToken -> Int
extractInt (TokenLitInt n) = n
extractInt _ = error "extractInt: ugh"
mkProgram :: [Decl' RlpcPs] -> P (RlpProgram RlpcPs)
mkProgram ds = do
pt <- use psOpTable
pure $ RlpProgram (associate pt <$> ds)
parseError :: (Located RlpToken, [String]) -> P a
parseError ((Located ss t), exp) = addFatal $
errorMsg ss (RlpParErrUnexpectedToken t exp)
mkInfixD :: Assoc -> Int -> PsName -> P (Decl' RlpcPs)
mkInfixD a p n = do
let opl :: Lens' ParseState (Maybe OpInfo)
opl = psOpTable . at n
opl <~ (use opl >>= \case
Just o -> addWoundHere l e >> pure (Just o) where
e = RlpParErrDuplicateInfixD n
l = T.length n
Nothing -> pure (Just (a,p))
)
pos <- use (psInput . aiPos)
pure $ Located (spanFromPos pos 0) (InfixD a p n)
intOfToken :: Located RlpToken -> Int
intOfToken (Located _ (TokenLitInt n)) = n
tempInfixExprErr :: RlpExpr' RlpcPs -> RlpExpr' RlpcPs -> P a
tempInfixExprErr (Located a _) (Located b _) =
addFatal $ errorMsg (a <> b) $ RlpParErrOther
[ "The rl' frontend is currently in beta. Support for infix expressions is minimal, sorry! :("
, "In the mean time, don't mix any infix operators."
]
}