Show instances, fixed a bunch of bugs in parsing

- The case / let / indent stuff actually works
- Needed a bunch of defers
- Idris silently builds loops in immediate definitions
This commit is contained in:
2022-09-10 22:10:35 -07:00
parent 39deff1465
commit 1ed884eff9
10 changed files with 305 additions and 55 deletions

View File

@@ -4,6 +4,7 @@ module Lib.Parser
import Lib.Token
import Lib.Parser.Impl
import Syntax
import Data.List
-- There is the whole core vs surface thing here.
-- might be best to do core first/ Technically don't
@@ -19,27 +20,130 @@ import Syntax
ident = token Ident
term : Parser Term
parens : Parser a -> Parser a
parens pa = do
sym "("
t <- pa
sym ")"
pure t
lit : Parser Term
lit = do
t <- token Number
pure $ Lit (LInt (cast t))
export
term : (Parser Term)
-- ( t : ty ), (t , u) (t)
-- Or do we want (x : ty) I think we may need to annotate any term
parenThinger : Parser Term
parenThinger = do
keyword "("
t <- term
-- And now we want ) : or ,
-- we could do this with backtracing, but it'd kinda suck?
fail "todo"
-- the inside of term
atom : Parser Term
atom = lit
<|> Var <$> ident
<|> parens term
-- <|> sym "(" *> term <* sym ")"
--
-- atom is lit or ident
data Fixity = InfixL | InfixR | Infix
-- starter pack, but we'll move some to prelude
operators : List (String, Int, Fixity)
operators = [
("->", 1, InfixR),
("=", 2, InfixL), -- REVIEW
("+",4,InfixL),
("-",4,InfixL),
("*",5,InfixL),
("/",5,InfixL)
]
parseApp : Parser Term
parseApp = do
hd <- atom
rest <- many atom
pure $ foldl App hd rest
parseOp : Lazy (Parser Term)
parseOp = parseApp >>= go 0
where
go : Int -> Term -> Parser Term
go prec left =
do
op <- token Oper
let Just (p,fix) = lookup op operators
| Nothing => fail "expected operator"
-- if p >= prec then pure () else fail ""
guard $ p >= prec
-- commit
let pr = case fix of InfixR => p; _ => p + 1
-- commit?
right <- go pr !(parseApp)
go prec (App (App (Var op) left) right)
<|> pure left
export
letExpr : Parser Term
letExpr = Let <$ keyword "let" <*> ident <* keyword "=" <*> term <* keyword "in" <*> term
letExpr = do
keyword "let"
commit
alts <- startBlock $ someSame $ letAssign
keyword' "in"
scope <- term
pure $ Let alts scope
-- Let <$ keyword "let" <*> ident <* keyword "=" <*> term <* keyword "in" <*> term
pattern : Parser Pattern
where
letAssign : Parser (Name,Term)
letAssign = do
name <- ident
keyword "="
t <- term
pure (name,t)
pPattern : Parser Pattern
pPattern
= PatWild <$ keyword "_"
<|> [| PatVar ident |]
export
lamExpr : Parser Term
lamExpr = do
keyword "\\"
commit
name <- pattern
name <- pPattern
keyword "."
scope <- term
pure $ Lam name scope
caseAlt : Parser CaseAlt
caseAlt : Parser CaseAlt
caseAlt = do
pat <- pPattern -- Term and sort it out later?
keyword "=>"
commit
t <- term
pure $ MkAlt pat t
export
caseExpr : Parser Term
caseExpr = do
_ <- keyword "case"
keyword "case"
commit
sc <- term
keyword "of"
@@ -47,10 +151,10 @@ caseExpr = do
pure $ Case sc alts
-- TODO - get this up and running with a case expr to test it
term = defer $ \_ =>
caseExpr
<|> letExpr
<|> parseOp
{-
so lets say we wanted to do the indent, the hard way.