module Lang.LamIf.Parser where import FP import Lang.LamIf.Syntax data Keyword = KLambda | KIfZero | KThen | KElse | KLet | KIn makePrisms ''Keyword data KeywordPunctuation = KPDot | KPPlus | KPMinus | KPDefEqual makePrisms ''KeywordPunctuation data Punctuation = PLParen | PRParen makePrisms ''Punctuation data Token = TKeyword Keyword | TKeywordPunctuation KeywordPunctuation | TPunctuation Punctuation | TInteger โ„ค | TSymbol ๐•Š | TWhitespace ๐•Š makePrisms ''Token data SourceExp = SourceExp { sourceExpContext โˆท SourceContext Token , sourceExpRawExp โˆท PreExp ๐•Š SourceExp } stripSourceExp โˆท SourceExp โ†’ Fixed (PreExp ๐•Š) stripSourceExp (SourceExp _ e) = Fixed $ map stripSourceExp e instance Pretty SourceExp where pretty e = ppVertical [ ppHeader "Source:" , pretty $ sourceExpContext e , ppHeader "AST:" , pretty $ stripSourceExp e ] tokKeyword โˆท Parser โ„‚ Keyword tokKeyword = mconcat $ map (\ (s,k) โ†’ pWord s โ‰ซ return k) [ ("lam",KLambda) , ("if0",KIfZero) , ("then",KThen) , ("else",KElse) , ("let",KLet) , ("in",KIn) ] tokKeywordPunctuation โˆท Parser โ„‚ KeywordPunctuation tokKeywordPunctuation = mconcat $ map (\ (s,kp) โ†’ pWord s โ‰ซ return kp) [ (".",KPDot) , ("+",KPPlus) , ("-",KPMinus) , (":=",KPDefEqual) ] tokPunctuation โˆท Parser โ„‚ Punctuation tokPunctuation = mconcat $ map (\ (s,p) โ†’ pWord s โ‰ซ return p) [ ("(",PLParen) , (")",PRParen) ] tokToken โˆท Parser โ„‚ Token tokToken = mconcat [ construct tKeywordL ^$ pRender UL $ pRender (FG darkYellow) tokKeyword , construct tKeywordPunctuationL ^$ pRender (FG darkYellow) $ tokKeywordPunctuation , construct tPunctuationL ^$ pRender (FG darkGray) $ tokPunctuation , construct tIntegerL ^$ pRender (FG darkRed) $ pInteger , construct tSymbolL โˆ˜ ๐•ค ^$ id $ pOneOrMoreGreedy pLetter , construct tWhitespaceL ^$ id $ pWhitespaceGreedy ] parWhitespace โˆท Parser Token () parWhitespace = void $ pShaped "whitespace" $ view tWhitespaceL parOptionalWhitespace โˆท Parser Token () parOptionalWhitespace = void $ pOptionalGreedy parWhitespace parSurroundOptionalWhitespace โˆท Parser Token a โ†’ Parser Token a parSurroundOptionalWhitespace = pSurrounded parOptionalWhitespace parSymbol โˆท Parser Token ๐•Š parSymbol = pShaped "symbol" $ view tSymbolL parLParen โˆท Parser Token () parLParen = pShaped "lparen" $ view $ pLParenL โŒพ tPunctuationL parRParen โˆท Parser Token () parRParen = pShaped "rparen" $ view $ pRParenL โŒพ tPunctuationL parParens โˆท Parser Token a โ†’ Parser Token a parParens = pSurroundedBy parLParen parRParen โˆ˜ parSurroundOptionalWhitespace foldSourceExp โˆท FullContextAnnotated Token (PreExp ๐•Š SourceExp) โ†’ SourceExp foldSourceExp (FullContextAnnotated pc e) = SourceExp pc e unfoldSourceExp โˆท SourceExp โ†’ FullContextAnnotated Token (PreExp ๐•Š SourceExp) unfoldSourceExp (SourceExp pc e) = FullContextAnnotated pc e parMixes โˆท MixfixF Token (FullContextAnnotated Token) (PreExp ๐•Š SourceExp) parMixes = concat [ mixF $ TerminalF $ (fullContextAnnotatedValue โˆ˜ unfoldSourceExp) ^$ parParens parExp , mixF $ TerminalF $ EAtom โˆ˜ AInteger ^$ pShaped "integer" $ view tIntegerL , mixF $ TerminalF $ EAtom โˆ˜ AVar ^$ parSymbol , mixF $ PreF (๐•Ÿ 0) $ pAppendError "lambda prefix" $ do void $ pShaped "lambda" $ view $ kLambdaL โŒพ tKeywordL x โ† parSurroundOptionalWhitespace $ pRender (FG darkTeal) parSymbol void $ pShaped "dot" $ view $ kPDotL โŒพ tKeywordPunctuationL parOptionalWhitespace return $ \ (foldSourceExp โ†’ e) โ†’ EAtom $ ALam x e , mixF $ PreF (๐•Ÿ 0) $ pAppendError "let prefix" $ do void $ pShaped "let" $ view $ kLetL โŒพ tKeywordL x โ† parSurroundOptionalWhitespace $ pRender (FG darkTeal) parSymbol void $ pShaped ":=" $ view $ kPDefEqualL โŒพ tKeywordPunctuationL eโ‚ โ† parSurroundOptionalWhitespace parExp void $ pShaped "in" $ view $ kInL โŒพ tKeywordL parOptionalWhitespace return $ \ (foldSourceExp โ†’ eโ‚‚) โ†’ ELet x eโ‚ eโ‚‚ , mixF $ PreF (๐•Ÿ 0) $ pAppendError "if prefix" $ do void $ pShaped "if0" $ view $ kIfZeroL โŒพ tKeywordL eโ‚ โ† parSurroundOptionalWhitespace parExp void $ pShaped "then" $ view $ kThenL โŒพ tKeywordL eโ‚‚ โ† parSurroundOptionalWhitespace parExp void $ pShaped "else" $ view $ kElseL โŒพ tKeywordL parOptionalWhitespace return $ \ (foldSourceExp โ†’ eโ‚ƒ) โ†’ EIf eโ‚ eโ‚‚ eโ‚ƒ , mixF $ InfrF (๐•Ÿ 5) $ pAppendError "plus" $ do parSurroundOptionalWhitespace $ pShaped "+" $ view $ kPPlusL โŒพ tKeywordPunctuationL return $ \ (foldSourceExp โ†’ eโ‚) (foldSourceExp โ†’ eโ‚‚) โ†’ EOp Plus eโ‚ eโ‚‚ , mixF $ InfF (๐•Ÿ 5) $ pAppendError "minus" $ do parSurroundOptionalWhitespace $ pShaped "-" $ view $ kPMinusL โŒพ tKeywordPunctuationL return $ \ (foldSourceExp โ†’ eโ‚) (foldSourceExp โ†’ eโ‚‚) โ†’ EOp Minus eโ‚ eโ‚‚ , mixF $ InflF (๐•Ÿ 100) $ pAppendError "application" $ do parWhitespace return $ \ (foldSourceExp โ†’ eโ‚) (foldSourceExp โ†’ eโ‚‚) โ†’ EApp eโ‚ eโ‚‚ ] parExp โˆท Parser Token SourceExp parExp = foldSourceExp ^$ pError "exp" $ mixfixParserF parMixes $ \ eM โ†’ do (e,pc) โ† pCaptureFull eM return $ FullContextAnnotated pc e parseExp โˆท ๐•Š โ†’ Doc โจ„ SourceExp parseExp cs = parse parExp *$ tokenize tokToken $ tokens cs -- - Old, before I figured out how to plumb comonadic structure for context -- -- parMixes โˆท Mixfix Token ParsedExp -- parMixes = concat -- [ mix $ Terminal $ parCaptureExp $ unfoldAnnotatedExp ^$ parParens parExp -- , mix $ Terminal $ parCaptureExp $ EAtom โˆ˜ AInteger ^$ pShaped "integer" $ view tIntegerL -- , mix $ Terminal $ parCaptureExp $ EAtom โˆ˜ AVar ^$ parSymbol -- , mix $ Pre (๐•Ÿ 0) $ do -- (pc,x) โ† pAppendError "lambda prefix" $ pCaptureFull $ do -- void $ pShaped "lambda" $ view $ kLambdaL โŒพ tKeywordL -- x โ† parSurroundOptionalWhitespace $ pRender (FG darkTeal) parSymbol -- void $ parDot -- parOptionalWhitespace -- return x -- return $ \ (AnnotatedExp pc' e) โ†’ -- AnnotatedExp (pc โงบ pc') $ EAtom $ ALam x $ AnnotatedExp pc' e -- , mix $ Pre (๐•Ÿ 0) $ pAppendError "if prefix" $ do -- (pc,(eโ‚,eโ‚‚)) โ† pCaptureFull $ do -- void $ pShaped "if0" $ view $ kIfZeroL โŒพ tKeywordL -- eโ‚ โ† parSurroundOptionalWhitespace parExp -- void $ pShaped "then" $ view $ kThenL โŒพ tKeywordL -- eโ‚‚ โ† parSurroundOptionalWhitespace parExp -- void $ pShaped "else" $ view $ kElseL โŒพ tKeywordL -- parOptionalWhitespace -- return (eโ‚,eโ‚‚) -- return $ \ (AnnotatedExp pc' eโ‚ƒ) โ†’ -- AnnotatedExp (pc โงบ pc') $ EIf eโ‚ eโ‚‚ $ AnnotatedExp pc' eโ‚ƒ -- , mix $ Pre (๐•Ÿ 0) $ do -- (pc,(x,eโ‚)) โ† pAppendError "let prefix" $ pCaptureFull $ do -- void $ pShaped "let" $ view $ kLetL โŒพ tKeywordL -- x โ† parSurroundOptionalWhitespace $ pRender (FG darkTeal) parSymbol -- void $ pShaped ":=" $ view $ kPDefEqualL โŒพ tKeywordPunctuationL -- eโ‚ โ† parSurroundOptionalWhitespace parExp -- void $ pShaped "in" $ view $ kInL โŒพ tKeywordL -- parOptionalWhitespace -- return (x,eโ‚) -- return $ \ (AnnotatedExp pc' eโ‚‚) โ†’ -- AnnotatedExp (pc โงบ pc') $ ELet x eโ‚ $ AnnotatedExp pc' eโ‚‚ -- , mix $ Infr (๐•Ÿ 5) $ do -- (pc,()) โ† pCaptureFull $ -- parSurroundOptionalWhitespace $ pShaped "+" $ view $ kPPlusL โŒพ tKeywordPunctuationL -- return $ \ (AnnotatedExp pcโ‚ eโ‚) (AnnotatedExp pcโ‚‚ eโ‚‚) โ†’ -- AnnotatedExp (pcโ‚ โงบ pc โงบ pcโ‚‚) $ EOp Plus (AnnotatedExp pcโ‚ eโ‚) (AnnotatedExp pcโ‚‚ eโ‚‚) -- , mix $ Inf (๐•Ÿ 5) $ do -- (pc,()) โ† pCaptureFull $ -- parSurroundOptionalWhitespace $ pShaped "-" $ view $ kPMinusL โŒพ tKeywordPunctuationL -- return $ \ (AnnotatedExp pcโ‚ eโ‚) (AnnotatedExp pcโ‚‚ eโ‚‚) โ†’ -- AnnotatedExp (pcโ‚ โงบ pc โงบ pcโ‚‚) $ EOp Minus (AnnotatedExp pcโ‚ eโ‚) (AnnotatedExp pcโ‚‚ eโ‚‚) -- , mix $ Infl (๐•Ÿ 100) $ do -- (pc,()) โ† pCaptureFull $ parWhitespace -- return $ \ (AnnotatedExp pcโ‚ eโ‚) (AnnotatedExp pcโ‚‚ eโ‚‚) โ†’ -- AnnotatedExp (pcโ‚ โงบ pc โงบ pcโ‚‚) $ EApp (AnnotatedExp pcโ‚ eโ‚) (AnnotatedExp pcโ‚‚ eโ‚‚) -- ] -- -- parExp โˆท Parser Token ParsedExp -- parExp = pError "exp" $ mixfixParser parMixes -- parseStringExpIO โˆท ๐•Š โ†’ IO ParsedExp -- parseStringExpIO cs = parseIO parExp *$ tokenizeIO tokToken $ tokens cs