-
Notifications
You must be signed in to change notification settings - Fork 0
EK Formal Grammar
The full formal grammar of the EK Programming Language can be found here. We use a flavour of BNF that is inspired by the one Swift uses.
Nonterminal symbols are in italic, terminal ones are enclosed in double quotes or described in English in bold. We use an equals symbol for definitions.
A question mark (?) after a symbol means it is optional, an asterisk (*) means it is repeated 0 or more times, and a plus sign (+) means it is repeated 1 or more times.
Alternatives use pipes (|) and composition uses juxtaposition. Note that there is implicit whitespace allowed in juxtaposition.
whitespace = whitespace-item+
whitespace-item = line-break | space | comment
line-break = Line Feed (LF, U+000A) | Carriage Return (CR, U+000D)
space = Any Unicode character in the Space general category
comment = "//" comment-text line-break
comment-text = Any character except U+000A or U+000D *
identifier = text-identifier | identifier-operator | "[" | "]"
text-identifier = identifier-head identifier-char+
identifier-head = Any Unicode character in the UppercaseLetter, LowercaseLetter, TitlecaseLetter, ModifierLetter or OtherLetter unicode general category
identifier-char = identifier-head | Digits 0 through 9 | "'"
identifier-operator = identifier-operator-char+
identifier-operator-char = "/" | "-" | "+" | "*" | "!" | "?" | "%" | "<" | ">" | "&" | "|" | "^" | "~" | "=" | "." | "$"
literal = float-literal | int-literal | string-literal
int-literal = decimal-literal
decimal-literal = decimal-digit+
decimal-digit = Digits 0 through 9
float-literal = decimal-digit+ "." decimal-digit+
quote = The double quote character (")
string-literal = quote quoted-text* quote
quoted-text = escape-sequence | Any Unicode character except double quotes and backslash
escape-sequence = "\" escape-char
escape-char = "0" | "\" | "t" | "n" | "r" | quote
definition = atom-definition | type-definition | struct-definition | function-definition | import-definition
atom-definition = "atom" text-identifier
type-definition = "type" text-identifier "=" type
struct-definition = "struct" text-identifier "{" struct-elems? "}"
struct-elems = struct-elem | struct-elem "," struct-elems?
struct-elem = text-identifier typed
import-definition = "import" text-identifier
function-definition = "fn" function-pattern "=" expression | "extern" "fn" function-pattern
function-pattern = function-pattern-item+ typed? precedence-clause?
function-pattern-item = identifier | placeholder | argument-pattern
placeholder = "_"
argument-pattern = "(" argument ")"
argument = "lazy"? text-identifier typed?
precedence-clause = "precedence" precedence
precedence = int-literal
typed = ":" type
type = paren-type | text-identifier | int-range | union-type | fn-type
paren-type = "(" type ")"
union-type = type "|" type
fn-type = type "->" type
int-range = int-literal | "[" int-literal? ".." int-literal? "]"
expression = primary-expr | call | struct-constructor | lambda | type-check | arr-lit
struct-expr = expression | expression "," struct-expr
struct-constructor = text-identifier "{" struct-expr? "}"
primary-expr = paren-expr | literal
paren-expr = "(" expression ")"
arr-lit = "[" struct-expr? "]"
call = call-item+
call-item = identifier | expression | placeholder
lambda = "" lambda-args "=" expression
lambda-args = identifier+
type-check = expression "is" type