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