Grammar

Here is the grammar used to parse FunL presented in EBNF.

Syntactic Grammar

The syntactic grammar productions:

source ::= Newline | statements

declaration ::= imports | natives | constants | variables | data | definitions

imports ::=
    'import' importModule
  | 'import' Indent importModule+ Dedent Newline

importModule ::= name

natives ::=
    'native' name
  | 'native' Indent name+ Dedent Newline
  | 'function' name
  | 'function' Indent name+ Dedent Newline

dottedName ::= ident ('.' ident)*

qualifier ::= ident ('=>' ident)?

name ::=
    dottedName ('=>' ident)? Newline
  | dottedName '.' '{' qualifier (',' qualifier)* '}' Newline
  | dottedName '.' '*' Newline

identifiers ::= ident (',' ident)*

constants ::=
    'val' constant
  | 'val' Indent constant+ Dedent Newline

constant ::=
    pattern '=' expressionOrBlock Newline

variables ::=
    'var' variable
  | 'var' Indent variable+ Dedent Newline

variable ::=
    ident ('=' expressionOrBlock)? Newline

data ::=
    'data' datatype
  | 'data' Indent datatype+ Dedent Newline

datatype ::=
    ident '=' constructor ('|' constructor)* Newline
  | constructor Newline

constructor ::=
    ident '(' identifiers ')'
  | ident

definitions ::=
    'def' definition
  | 'def' Indent definition+ Dedent Newline

definition ::=
    ident ('(' (pattern (',' pattern)*)? ')')? (optionallyGuardedPart | guardedParts)

optionallyGuardedPart ::=
    ('|' booleanExpression)? '=' expressionOrBlock Newline

guardedPart ::=
  '|' ('otherwise' | booleanExpression) '=' expressionOrBlock Newline

guardedParts ::= Indent guardedPart+ Dedent Newline

statements ::= statement+

optionalNewline ::= Newline?

expressionStatement ::= expression Newline

statement ::=
    expressionStatement
  | declaration

blockExpression ::=
    Indent statements Dedent

assignment ::= '=' | '+=' | '-=' | '*=' | '/=' | '\=' | '^='

expression ::=
    lvalueExpression (',' lvalueExpression)* assignment nonAssignmentExpression (',' nonAssignmentExpression)*
  | nonAssignmentExpression

lambdaExpression ::=
  ('(' pattern (',' pattern)* ')' | pattern) ('|' booleanExpression)? '->' expression

caseFunctionExpression ::=
    Indent lambdaExpression (Newline lambdaExpression)* Dedent

functionExpression ::=
    lambdaExpression | caseFunctionExpression

nonAssignmentExpression ::=
    functionExpression | controlExpression

elif ::=
    optionalNewline 'elif' booleanExpression ('then' expressionOrBlock | blockExpression)

generator ::=
    pattern '<-' expression ('if' expression)?

generators ::= generator (',' generator)*

expressionOrBlock ::= expression | blockExpression

elif ::= optionalNewline 'elif' booleanExpression ('then' expressionOrBlock | blockExpression)

elsePart ::= (optionalNewline 'else' expressionOrBlock)?

controlExpression ::=
    'if' booleanExpression ('then' expressionOrBlock | blockExpression) elif* elsePart
  | 'for' generators ('do' expressionOrBlock | blockExpression) elsePart
  | 'for' expressionOrBlock
  | 'while' expression ('do' expressionOrBlock | blockExpression) elsePart
  | 'do' expression optionalNewline 'while' expression elsePart
  | 'do' expression optionalNewline 'until' expression elsePart
  | 'break'
  | 'continue'
  | 'return' expression?
  | 'case' expression ('of' functionExpression | caseFunctionExpression)
  | orExpression

booleanExpression ::= orExpression

orExpression ::=
    orExpression ('or' | 'xor') andExpression
  | andExpression

andExpression ::=
    andExpression ('and' | 'rotateright' | 'rotateleft' | 'shiftright' | 'shiftleft') notExpression
  | notExpression

notExpression ::=
    'not' notExpression
  | comparisonExpression

comparisonExpression ::=
    iteratorExpression ('==' | '!=' | '<' | '>' | '<=' | '>=' | 'in' | 'not' 'in'^ 'notin' | '|' | '/|') iteratorExpression
  | iteratorExpression 'is' ident
  | iteratorExpression

iteratorExpression ::=
    (consExpression '|') generators
  | consExpression

consExpression ::=
    rangeExpression (':' consExpression)
  | rangeExpression ('#' consExpression)
  | rangeExpression

keyExpression ::= rangeExpression

rangeExpression ::=
    additiveExpression ('..' | 'until') additiveExpression ('by' additiveExpression)?
  | (additiveExpression '..') ('by' additiveExpression)?
  | additiveExpression

additiveExpression ::=
    additiveExpression ('+' | '-') multiplicativeExpression
  | multiplicativeExpression

multiplicativeExpression ::=
    multiplicativeExpression ('*' | '/' | '\' | '%') exponentialExpression
  | multiplicativeExpression applyExpression
  | exponentialExpression

exponentialExpression ::=
    exponentialExpression '^' negationExpression
  | negationExpression

negationExpression ::=
    '-' incrementExpression
  | incrementExpression

incrementExpression ::=
    ('++' | '--') applyExpression
  | applyExpression ('++' | '--')
  | applyExpression

lvalueExpression ::= applyExpression

applyExpression ::=
    applyExpression ('(' (expression (',' expression)*)? ')')
  | applyExpression ('.' | '.>') ident
  | primaryExpression

MapEntry ::=
    keyExpression ':' expression

comprehensionExpression ::=
    consExpression '|' generators

primaryExpression ::=
    numericLit
  | stringLit
  | '(' infix ')'
  | '(' expression infix ')'
  | '(' infixNoMinus expression ')'
  | '(' expression ')'
  | ident
  | ('true' | 'false')
  | '(' ')'
  | ('(' nonAssignmentExpression ',') nonAssignmentExpression (',' nonAssignmentExpression)* ')'
  | '[' comprehensionExpression ']'
  | '[' (nonAssignmentExpression (',' nonAssignmentExpression)*)? ']'
  | 'null'
  | '{' (keyExpression (',' keyExpression)*)? '}'
  | '{' MapEntry (',' MapEntry)* '}'
  | '$' ident
  | '?' ident

infixNoMinus ::= '+' | '*' | '/' | '\' | '^' | '%' | '==' | '!=' | '<' | '>' | '<=' | '>=' | ':' | '#' | 'and' | 'or' | 'xor'

infix ::= infixNoMinus | '-'

pattern ::=
    ident '@' typePattern
  | typePattern

typePattern ::=
    consPattern '::' ident
  | consPattern

consPattern ::=
    primaryPattern ':' consPattern
  | primaryPattern

primaryPattern ::=
    numericLit
  | stringLit
  | 'true' | 'false'
  | '(' ')'
  | 'null'
  | ident '(' pattern (',' pattern)* ')'
  | ident
  | '(' pattern ',' pattern (',' pattern)* ')'
  | '[' (pattern (',' pattern)*)? ']'
  | '{' '}'
  | '(' pattern '|' pattern ('|' pattern)* ')'
  | '(' pattern ')'

Lexical Grammar

The reserved words in the language are: and, break, by, case, class, continue, data, def, do, elif, else, false, for, forever, function, if, import, in, is, mod, native, not, null, of, or, otherwise, repeat, return, then, true, until, val, var, while, xor, yield.

The special delimiters are: +, *, -, /, ^, (, ), [, ], |, {, }, ,, =, ==, !=, <, $, >, <-, <=, >=, --, ++, ., .., <-, ->, =>, +=, -=, *=, /=, ^=, :, \\, ::, @, ?.

The lexical grammar productions:

decimalParser =
        rep1(digit) ~ optFraction ~ optExponent |
        fraction ~ optExponent

sign = '+' | '-'

optSign = opt( sign )

fraction = '.' ~ rep1(digit)

optFraction = opt( fraction )

exponent = ('e' | 'E') ~ optSign ~ rep1(digit)

optExponent = opt(exponent)