Generalize type of expression parser

This commit is contained in:
Thomas Tuegel 2017-01-29 13:48:57 -06:00
parent fe4a9596ce
commit 4d176b52e7
No known key found for this signature in database
GPG Key ID: 22CBF5249D4B4D59

View File

@ -9,7 +9,7 @@ module Dhall.Parser (
exprFromText
-- * Parsers
, expr
, expr, exprA
-- * Types
, Src(..)
@ -254,23 +254,25 @@ label = Text.Parser.Token.ident identifierStyle <?> "label"
-- | Parser for a top-level Dhall expression
expr :: Parser (Expr Src Path)
expr = exprA
expr = exprA import_
exprA :: Parser (Expr Src Path)
exprA = noted (do
a <- exprB
-- | Parser for a top-level Dhall expression. The expression is parameterized
-- over any parseable type, allowing the language to be extended as needed.
exprA :: Show a => Parser a -> Parser (Expr Src a)
exprA embedded = noted (do
a <- exprB embedded
let exprA0 = do
symbol ":"
b <- exprA
b <- exprA embedded
return (Annot a b)
let exprA1 = pure a
exprA0 <|> exprA1 )
exprB :: Parser (Expr Src Path)
exprB = choice
exprB :: Show a => Parser a -> Parser (Expr Src a)
exprB embedded = choice
[ noted exprB0
, noted exprB1
, noted exprB3
@ -286,25 +288,25 @@ exprB = choice
symbol "("
a <- label
symbol ":"
b <- exprA
b <- exprA embedded
symbol ")"
arrow
c <- exprB
c <- exprB embedded
return (Lam a b c)
exprB1 = do
reserve "if"
a <- exprA
a <- exprA embedded
reserve "then"
b <- exprB
b <- exprB embedded
reserve "else"
c <- exprC
c <- exprC embedded
return (BoolIf a b c)
exprB2 = do
a <- exprC
a <- exprC embedded
arrow
b <- exprB
b <- exprB embedded
return (Pi "_" a b)
exprB3 = do
@ -312,10 +314,10 @@ exprB = choice
symbol "("
a <- label
symbol ":"
b <- exprA
b <- exprA embedded
symbol ")"
arrow
c <- exprB
c <- exprB embedded
return (Pi a b c)
exprB5 = do
@ -323,33 +325,33 @@ exprB = choice
a <- label
b <- optional (do
symbol ":"
exprA )
exprA embedded )
symbol "="
c <- exprA
c <- exprA embedded
reserve "in"
d <- exprB
d <- exprB embedded
return (Let a b c d)
exprB6 = do
symbol "["
a <- elems
a <- elems embedded
symbol "]"
symbol ":"
b <- listLike
c <- exprE
c <- exprE embedded
return (b c a)
exprB7 = do
reserve "merge"
a <- exprE
b <- exprE
a <- exprE embedded
b <- exprE embedded
symbol ":"
c <- exprD
c <- exprD embedded
return (Merge a b c)
exprB8 = exprC
exprB8 = exprC embedded
listLike :: Parser (Expr Src Path -> Vector (Expr Src Path) -> Expr Src Path)
listLike :: Parser (Expr Src a -> Vector (Expr Src a) -> Expr Src a)
listLike =
( listLike0
<|> listLike1
@ -363,8 +365,8 @@ listLike =
reserve "Optional"
return OptionalLit
exprC :: Parser (Expr Src Path)
exprC = exprC0
exprC :: Show a => Parser a -> Parser (Expr Src a)
exprC embedded = exprC0
where
chain pA pOp op pB = noted (do
a <- pA
@ -377,7 +379,7 @@ exprC = exprC0
exprC4 = chain exprC5 combine Combine exprC4
exprC5 = chain exprC6 (symbol "*" ) NaturalTimes exprC5
exprC6 = chain exprC7 (symbol "==") BoolEQ exprC6
exprC7 = chain exprD (symbol "!=") BoolNE exprC7
exprC7 = chain (exprD embedded) (symbol "!=") BoolNE exprC7
-- We can't use left-recursion to define `exprD` otherwise the parser will
-- loop infinitely. However, I'd still like to use left-recursion in the
@ -387,25 +389,25 @@ exprC = exprC0
-- * First, parse to count how many arguments the function is applied to
-- * Second, restart the parse using left recursion bounded by the number of
-- arguments
exprD :: Parser (Expr Src Path)
exprD = do
es <- some (noted (try exprE))
exprD :: Show a => Parser a -> Parser (Expr Src a)
exprD embedded = do
es <- some (noted (try (exprE embedded)))
let app nL@(Note (Src before _ bytesL) _) nR@(Note (Src _ after bytesR) _) =
Note (Src before after (bytesL <> bytesR)) (App nL nR)
app _ _ = Dhall.Core.internalError
("Dhall.Parser.exprD: foldl1 app (" <> Data.Text.pack (show es) <> ")")
return (Data.List.foldl1 app es)
exprE :: Parser (Expr Src Path)
exprE = noted (do
a <- exprF
exprE :: Show a => Parser a -> Parser (Expr Src a)
exprE embedded = noted (do
a <- exprF embedded
b <- many (try (do
symbol "."
label ))
return (Data.List.foldl Field a b) )
exprF :: Parser (Expr Src Path)
exprF = choice
exprF :: Show a => Parser a -> Parser (Expr Src a)
exprF embedded = choice
[ noted (try exprF26)
, noted (try exprF25)
, noted exprF24
@ -562,23 +564,23 @@ exprF = choice
a <- stringLiteral
return (TextLit a)
exprF28 = record <?> "record type"
exprF28 = record embedded <?> "record type"
exprF29 = recordLit <?> "record literal"
exprF29 = recordLit embedded <?> "record literal"
exprF30 = union <?> "union type"
exprF30 = union embedded <?> "union type"
exprF31 = unionLit <?> "union literal"
exprF31 = unionLit embedded <?> "union literal"
exprF32 = listLit <?> "list literal"
exprF32 = listLit embedded <?> "list literal"
exprF33 = do
a <- import_ <?> "import"
a <- embedded <?> "import"
return (Embed a)
exprF34 = do
symbol "("
a <- exprA
a <- exprA embedded
symbol ")"
return a
@ -605,13 +607,13 @@ var = do
Nothing -> 0
return (V a b)
elems :: Parser (Vector (Expr Src Path))
elems = do
a <- Text.Parser.Combinators.sepBy exprA (symbol ",")
elems :: Show a => Parser a -> Parser (Vector (Expr Src a))
elems embedded = do
a <- Text.Parser.Combinators.sepBy (exprA embedded) (symbol ",")
return (Data.Vector.fromList a)
recordLit :: Parser (Expr Src Path)
recordLit =
recordLit :: Show a => Parser a -> Parser (Expr Src a)
recordLit embedded =
recordLit0
<|> recordLit1
where
@ -621,62 +623,62 @@ recordLit =
recordLit1 = do
symbol "{"
a <- fieldValues
a <- fieldValues embedded
b <- toMap a
symbol "}"
return (RecordLit b)
fieldValues :: Parser [(Text, Expr Src Path)]
fieldValues =
Text.Parser.Combinators.sepBy1 fieldValue (symbol ",")
fieldValues :: Show a => Parser a -> Parser [(Text, Expr Src a)]
fieldValues embedded =
Text.Parser.Combinators.sepBy1 (fieldValue embedded) (symbol ",")
fieldValue :: Parser (Text, Expr Src Path)
fieldValue = do
fieldValue :: Show a => Parser a -> Parser (Text, Expr Src a)
fieldValue embedded = do
a <- label
symbol "="
b <- exprA
b <- exprA embedded
return (a, b)
record :: Parser (Expr Src Path)
record = do
record :: Show a => Parser a -> Parser (Expr Src a)
record embedded = do
symbol "{"
a <- fieldTypes
a <- fieldTypes embedded
b <- toMap a
symbol "}"
return (Record b)
fieldTypes :: Parser [(Text, Expr Src Path)]
fieldTypes =
Text.Parser.Combinators.sepBy fieldType (symbol ",")
fieldTypes :: Show a => Parser a -> Parser [(Text, Expr Src a)]
fieldTypes embedded =
Text.Parser.Combinators.sepBy (fieldType embedded) (symbol ",")
fieldType :: Parser (Text, Expr Src Path)
fieldType = do
fieldType :: Show a => Parser a -> Parser (Text, Expr Src a)
fieldType embedded = do
a <- label
symbol ":"
b <- exprA
b <- exprA embedded
return (a, b)
union :: Parser (Expr Src Path)
union = do
union :: Show a => Parser a -> Parser (Expr Src a)
union embedded = do
symbol "<"
a <- alternativeTypes
a <- alternativeTypes embedded
b <- toMap a
symbol ">"
return (Union b)
alternativeTypes :: Parser [(Text, Expr Src Path)]
alternativeTypes =
Text.Parser.Combinators.sepBy alternativeType (symbol "|")
alternativeTypes :: Show a => Parser a -> Parser [(Text, Expr Src a)]
alternativeTypes embedded =
Text.Parser.Combinators.sepBy (alternativeType embedded) (symbol "|")
alternativeType :: Parser (Text, Expr Src Path)
alternativeType = do
alternativeType :: Show a => Parser a -> Parser (Text, Expr Src a)
alternativeType embedded = do
a <- label
symbol ":"
b <- exprA
b <- exprA embedded
return (a, b)
unionLit :: Parser (Expr Src Path)
unionLit =
unionLit :: Show a => Parser a -> Parser (Expr Src a)
unionLit embedded =
try unionLit0
<|> unionLit1
where
@ -684,7 +686,7 @@ unionLit =
symbol "<"
a <- label
symbol "="
b <- exprA
b <- exprA embedded
symbol ">"
return (UnionLit a b Data.Map.empty)
@ -692,17 +694,17 @@ unionLit =
symbol "<"
a <- label
symbol "="
b <- exprA
b <- exprA embedded
symbol "|"
c <- alternativeTypes
c <- alternativeTypes embedded
d <- toMap c
symbol ">"
return (UnionLit a b d)
listLit :: Parser (Expr Src Path)
listLit = do
listLit :: Show a => Parser a -> Parser (Expr Src a)
listLit embedded = do
symbol "["
a <- elems
a <- elems embedded
symbol "]"
return (ListLit Nothing a)
@ -775,7 +777,7 @@ exprFromText delta text = case result of
parser = unParser (do
Text.Parser.Token.whiteSpace
r <- exprA
r <- exprA import_
Text.Parser.Combinators.eof
return r )