bricks-0.0.0.2: Bricks is a lazy functional language based on Nix.

Safe HaskellNone
LanguageHaskell2010

Bricks.Parsing

Contents

Description

Parsec Parsers for the Bricks language.

Most parsers consume trailing whitespace, except ones that operate within quoted string environments where whitespace is significant.

Synopsis

Expressions

parse'expression :: Parser Expression Source #

The primary, top-level expression parser. This is what you use to parse a .nix file.

>>> parseTest parse'expression ""
parse error at (line 1, column 1):
unexpected end of input
expecting expression

parse'expression'paren :: Parser Expression Source #

Parser for a parenthesized expression, from opening parenthesis to closing parenthesis.

parse'expression'dictKey :: Parser Expression Source #

Parser for an expression in a context that is expecting a dict key.

One of:

  • an unquoted string
  • a quoted dynamic string
  • an arbitrary expression wrapped in antiquotes (${...})

Expression lists

parse'expressionList :: Parser [Expression] Source #

Parser for a list of expressions in a list literal ([ x y z ]) or in a chain of function arguments (f x y z).

>>> parseTest parse'expressionList ""
[]
>>> parseTest (length <$> parse'expressionList) "x \"one two\" (a: b) (c d)"
4
>>> parseTest (length <$> parse'expressionList) "(x \"one two\" (a: b) (c d))"
1

parse'expressionList'1 :: Parser Expression Source #

Parser for a single item within an expression list (expressionListP). This expression is not a lambda, a function application, a let-in expression, or a with expression.

>>> parseTest parse'expressionList'1 "ab.xy"
dot (var "ab") (str ["xy"])
>>> parseTest parse'expressionList'1 "(x: f x x) y z"
lambda (param "x") (apply (apply (var "f") (var "x")) (var "x"))
>>> parseTest parse'expressionList'1 "{ a = b; }.a y"
dot (dict [binding (str ["a"]) (var "b")]) (str ["a"])

parse'expressionList'1'noDot :: Parser Expression Source #

Like parse'expressionList'1, but with the further restriction that the expression may not be a Dot.

>>> parseTest parse'expressionList'1'noDot "ab.xy"
var "ab"
>>> parseTest parse'expressionList'1'noDot "(x: f x x) y z"
lambda (param "x") (apply (apply (var "f") (var "x")) (var "x"))
>>> parseTest parse'expressionList'1'noDot "{ a = b; }.a y"
dict [binding (str ["a"]) (var "b")]

Strings

parse'strUnquoted :: Parser Str'Unquoted Source #

Parser for an unquoted string. Unquoted strings are restricted to a conservative set of characters, and they may not be any of the keywords.

>>> parseTest parse'strUnquoted "abc"
unquoted "abc"
>>> parseTest parse'strUnquoted "x{y"
unquoted "x"
>>> parseTest parse'strUnquoted "let"
parse error at (line 1, column 4):
unexpected end of input

parse'strStatic :: Parser Str'Static Source #

Parser for a static string which may be either quoted or unquoted.

>>> parseTest parse'strStatic "\"hello\""
"hello"
>>> parseTest parse'strStatic "hello"
"hello"
>>> parseTest parse'strStatic "\"a b\""
"a b"
>>> parseTest parse'strStatic "a b"
"a"

By "static," we mean that the string may not contain antiquotation.

>>> parseTest parse'strStatic "\"a${x}b\" xyz"
parse error at (line 1, column 5):
antiquotation is not allowed in this context

parse'strStatic'quoted :: Parser Str'Static Source #

Parser for a static string that is quoted.

parse'strStatic'unquoted :: Parser Str'Static Source #

Parser for an unquoted static string.

parse'strDynamic'quoted :: Parser Str'Dynamic Source #

Parser for a dynamic string that is quoted. It may be a "normal" quoted string delimited by one double-quote "..." (parse'strDynamic'normalQ) or an "indented" string delimited by two single-quotes ''...'' (parse'strDynamic'indentedQ).

parse'strDynamic'normalQ :: Parser Str'Dynamic Source #

Parser for a dynamic string enclosed in "normal" quotes ("...").

parse'strDynamic'indentedQ :: Parser Str'Dynamic Source #

Parser for a dynamic string enclosed in "indented string" format, delimited by two single-quotes ''...''. This form of string does not have any escape sequences.

parse'str'within'normalQ :: Parser Text Source #

Parser for at least one normal character, within a normally-quoted string context, up to but not including the end of the string or the start of an antiquotation.

parse'inStr :: Parser InStr Source #

Parser for an indented string. This parser produces a representation of the lines from the source as-is, before the whitespace is cleaned up.

parse'inStr'1 :: Parser InStr'1 Source #

Parser for a single line of an InStr.

Lists

parse'list :: Parser List Source #

Parser for a list expression ([ ... ]).

>>> parseTest parse'list "[]"
list []
>>> parseTest parse'list "[x \"one\" (a: b) (c d)]"
list [var "x", str ["one"], lambda (param "a") (var "b"), apply (var "c") (var "d")]

Dicts

parse'dict :: Parser Dict Source #

Parser for a dict expression, either recursive (rec keyword) or not.

>>> parseTest parse'dict "{}"
dict []
>>> parseTest parse'dict "rec {  }"
rec'dict []
>>> parseTest parse'dict "{ a = b; inherit (x) y z \"s t\"; }"
dict [binding (str ["a"]) (var "b"), inherit'from (var "x") ["y", "z", "s t"]]

parse'dict'rec :: Parser (Seq DictBinding) Source #

Parser for a recursive (rec keyword) dict.

>>> parseTest parse'dict "rec {  }"
rec'dict []
>>> parseTest parse'dict "rec { a = \"1\"; b = \"${a}2\"; }"
rec'dict [binding (str ["a"]) (str ["1"]), binding (str ["b"]) (str [antiquote (var "a"), "2"])]

parse'dict'noRec :: Parser (Seq DictBinding) Source #

Parser for a non-recursive (no rec keyword) dict.

>>> parseTest parse'dict "{  }"
dict []
>>> parseTest parse'dict "{ a = \"1\"; b = \"${a}2\"; }"
dict [binding (str ["a"]) (str ["1"]), binding (str ["b"]) (str [antiquote (var "a"), "2"])]

Dict lookup

parse'dot'rhs'chain :: Parser [Expression] Source #

Parser for a chain of dict lookups (like .a.b.c) on the right-hand side of a Dot expression.

>>> parseTest parse'dot'rhs'chain ""
[]
>>> parseTest parse'dot'rhs'chain ".abc"
[str ["abc"]]
>>> parseTest parse'dot'rhs'chain ".a.${b}.\"c\".\"d${e}\""
[str ["a"],var "b",str ["c"],str ["d", antiquote (var "e")]]

Lambdas

parse'lambda :: Parser Lambda Source #

Parser for a lambda expression (x: y).

>>> parseTest parse'lambda "x: [x x \"a\"]"
lambda (param "x") (list [var "x", var "x", str ["a"]])
>>> parseTest parse'lambda "{a,b}:a"
lambda (pattern [param "a", param "b"]) (var "a")
>>> parseTest parse'lambda "{ ... }: \"x\""
lambda (pattern [] <> ellipsis) (str ["x"])
>>> parseTest parse'lambda "a@{ f, b ? g x, ... }: f b"
lambda (param "a" <> pattern [param "f", param "b" & def (apply (var "g") (var "x"))] <> ellipsis) (apply (var "f") (var "b"))
>>> parseTest parse'lambda "a: b: \"x\""
lambda (param "a") (lambda (param "b") (str ["x"]))

Function parameters

parse'param :: Parser Param Source #

Parser for a function parameter (the beginning of a Lambda), including the colon. This forms part of parse'expression, so it backtracks in places where it has overlap with other types of expressions.

parse'param'var :: Parser Param Source #

Parser for a parameter that starts with a variable. This could be a simple param that consists only of only the variable, or the variable may be followed by a dict pattern.

parse'param'noVar :: Parser Param Source #

Parser for a param that has no variable, only a a dict pattern. This parser backtracks because the beginning of a dict pattern looks like the beginning of a dict expression.

parse'dictPattern :: Parser DictPattern Source #

Parser for a dict pattern (the type of lambda parameter that does dict destructuring. This parser does not backtrack.

parse'dictPattern'start :: Parser () Source #

This is used in a lookahead by parse'param to determine whether we're about to start parsing a DictPattern.

let

with

inherit

Comments and whitespace

Keywords

parse'keyword :: Keyword -> Parser () Source #

Backtracking parser for a particular keyword.

Antiquotation