Fantom

 

Grammar

Legend

Legend for Fantom BNF Grammar:

:=      is defined as
<x>     non-terminal
"x"     literal
[x]     optional
(x)     grouping
x*      zero or more times
x|x     or

Compilation Unit

<compilationUnit> :=  <podUnit> | <typeUnit>
<podUnit>         :=  <using*> <podDef>
<typeUnit>        :=  <using*> <typeDef>*
<using>           :=  <usingPod> | <usingType> | <usingAs>
<usingPod>        :=  "using" <podSpec> <eos>
<usingType>       :=  "using" <podSpec> "::" <id> <eos>
<usingAs>         :=  "using" <podSpec> "::" <id> "as" <id> <eos>
<podSpec>         :=  [ffi] <id> ("." <id>)*
<ffi>             :=  "[" <id> "]"

Pod Def

<podDef>         :=  <podHeader> "{" <symbolDefs> "}"
<podHeader>      :=  [<doc>] <facets> "pod" <id>
<symbolDefs>     :=  <symbolDef>*
<symbolDef>      :=  [<doc>] <symbolFlags> [<type>] <id> ":=" <expr> <eos>
<symbolFlags>    := ["virtual"]

Type Def

<typeDef>        :=  <classDef> | <mixinDef> | <enumDef>

<classDef>       :=  <classHeader> <classBody>
<classHeader>    :=  [<doc>] <facets> <classFlags> "class" <id> [<inheritance>]
<classFlags>     :=  [<protection>] ["abstract"] ["final"] ["const"]
<classBody>      :=  "{" <slotDefs> "}"

<enumDef>        :=  <enumHeader> <enumBody>
<enumHeader>     :=  [<doc>] <facets> [<protection>] "enum" <id> [<inheritance>]
<enumBody>       :=  "{" <enumValDefs> <slotDefs> "}"

<mixinDef>       :=  <mixinHeader> <mixinBody>
<mixinHeader>    :=  [<doc>] <facets> [<protection>] "mixin" <id> [<inheritance>]
<mixinBody>      :=  "{" <slotDefs> "}"

<protection>     :=  "public" | "protected" | "private" | "internal"
<inheritance>    :=  ":" <typeList>

Slot Def

<enumValDefs>    :=  <enumValDef> ("," <enumValDef>)* <eos>
<enumValDef>     :=  <id> ["(" <args> ")"]

<slotDefs>       :=  <slotDef>*
<slotDef>        :=  <fieldDef> | <methodDef> | <ctorDef>

<fieldDef>       :=  <facets> <fieldFlags> [<type>] <id> [":=" <expr>]
                     [ "{" [<fieldGetter>] [<fieldSetter>] "}" ] <eos>
<fieldFlags>     :=  [<protection>] ["abstract"] ["const"] ["final"] ["native"]
                     ["override"] ["readonly"] ["static"] ["virtual"] // in any order
<fieldGetter>    :=  "get" (<eos> | <block>)
<fieldSetter>    :=  <protection> "set" (<eos> | <block>)

<methodDef>      :=  <facets> <methodFlags> <type> <id> "(" <params> ")" <methodBody>
<methodFlags>    :=  [<protection>] ["abstract"] ["native"] ["once"]
                     ["override"] ["static"] ["virtual"] // in any order
<params>         :=  [<param> ("," <param>)*]
<param>          :=  <type> <id> [":=" <expr>]
<methodBody>     :=  <eos> | ( "{" <stmts> "}" )

<ctorDef>        :=  <facets> <ctorFlags> "new" <id> "(" <params> ")" [ctorChain] <methodBody>
<ctorFlags>      :=  [<protection>]
<ctorChain>      :=  <ctorChainThis> | <ctorChainSuper>
<ctorChainThis>  :=  "this" "." <id> "(" <args> ")"
<ctorChainSuper> :=  "super" ["." <id>] "(" <args> ")"

Facets

<facets>        := <facet>*
<facet>         := "@" <id> "=" <expr>

Stmt

<block>          :=  <stmt> | ( "{" <stmts> "}" )
<stmts>          :=  <stmt>*
<stmt>           :=  <break> | <continue> | <for> | <if> | <return> | <switch> |
                     <throw> | <while> | <try> | <exprStmt> | <localDef> | <itAdd>
<break>          :=  "break" <eos>
<continue>       :=  "continue" <eos>
<for>            :=  "for" "(" [<forInit>] ";" [<expr>] ";" [<expr>] ")" <block>
<forInit>        :=  <expr> | <localDef>
<if>             :=  "if" "(" <expr> ")" <block> [ "else" <block> ]
<return>         :=  "return" [<expr>] <eos>
<throw>          :=  "throw" <expr> <eos>
<while>          :=  "while" "(" <expr> ")" <block>
<exprStmt>       :=  <expr> <eos>
<localDef>       :=  [<type>] <id> [":=" <expr>] <eos>
<itAdd>          :=  <expr> ("," <expr>)* <eos>

<try>            :=  "try" <block> <catch>* [<finally>]
<catch>          :=  "catch" [<catchDef>] <block>
<catchDef>       :=  "(" <type> <id> ")"
<finally>        :=  "finally" <block>

<switch>         :=  "switch" "(" <expr> ")" "{" <case>* [<default>] "}"
<case>           :=  "case" <expr> ":" <stmts>
<default>        :=  "default" ":" <stmts>

Expr

<expr>           :=  <assignExpr>
<assignExpr>     :=  <ifExpr> [<assignOp> <assignExpr>]
<assignOp>       :=  "=" | "*=" | "/=" | "%=" | "+=" | "-="

<ifExpr>         :=  <ternaryExpr> | <elvisExpr>
<ternaryExpr>    :=  <condOrExpr> ["?" <ifExprBody> ":" <ifExprBody>]
<elvisExpr>      :=  <condOrExpr> "?:" <ifExprBody>
<ifExprBody>     :=  <condOrExpr> | <ifExprThrow>
<ifExprThrow>    :=  "throw" <expr>

<condOrExpr>     :=  <condAndExpr>  ("||" <condAndExpr>)*
<condAndExpr>    :=  <equalityExpr> ("&&" <equalityExpr>)*
<equalityExpr>   :=  <relationalExpr> (("==" | "!=" | "===" | "!==") <relationalExpr>)*
<relationalExpr> :=  <typeCheckExpr> | <compareExpr>
<typeCheckExpr>  :=  <rangeExpr> [("is" | "as" | "isnot") <type>]
<compareExpr>    :=  <rangeExpr> (("<" | "<=" | ">" | ">=" | "<=>") <rangeExpr>)*
<rangeExpr>      :=  <addExpr> ((".." | "..<") <addExpr>)*
<addExpr>        :=  <multExpr> (("+" | "-") <multExpr>)*
<multExpr>       :=  <parenExpr> (("*" | "/" | "%") <parenExpr>)*
<parenExpr>      :=  <unaryExpr> | <castExpr> | <groupedExpr>
<castExpr>       :=  "(" <type> ")" <parenExpr>
<groupedExpr>    :=  "(" <expr> ")" <termChain>*
<unaryExpr>      :=  <prefixExpr> | <termExpr> | <postfixExpr>
<prefixExpr>     :=  ("!" | "+" | "-" | "&" | "++" | "--") <parenExpr>
<postfixExpr>    :=  <termExpr> ("++" | "--")

<termExpr>       :=  <termBase> <termChain>*
<termBase>       :=  <literal> | <idExpr> | <typeBase>
<typeBase>       :=  <typeLiteral> | <slotLiteral> | <namedSuper> | <staticCall> |
                     <dsl> | <closure> | <simple> | <ctorBlock>
<typeLiteral>    :=  <type> "#"
<slotLiteral>    :=  [<type>] "#" <id>
<namedSuper>     :=  <type> "." "super"
<staticCall>     :=  <type> "." <idExpr>
<dsl>            :=  <type> "<|" <anyChar>* "|>"
<closure>        :=  <funcType> "{" <stmts> "}"
<simple>         :=  <type> "(" <expr> ")"
<ctorBlock>      :=  <type> <itBlock>
<termChain>      :=  <dotCall> | <dynCall> | <safeDotCall> | <safeDynCall> |
                     <indexExpr> | <callOp> | <itBlock>
<itBlock>        :=  "{" <stmts> "}"
<dotCall>        :=  "." <idExpr>
<dynCall>        :=  "->" <idExpr>
<safeDotCall>    :=  "?." <idExpr>
<safeDynCall>    :=  "?->" <idExpr>
<idExpr>         :=  <local> | <field> | <call>
<local>          :=  <id>
<field>          :=  ["*"] <id>
<call>           :=  <id> ["(" <args> ")"] [<closure>]
<args>           :=  [<expr> ("," <expr>)*]
<indexExpr>      :=  "[" <expr> "]"
<callOp>         :=  "(" <args> ")" [<closure>]
<literal>        :=  "null" | "this" | "super" | "it" |
                     <bool> | <int> | <float> | <decimal> | <str> |
                     <duration> | <uri> | <list> | <map> | <symbolLiteral>
<list>           :=  [<type>] "[" <listItems> "]"
<listItems>      :=  "," | (<expr> ("," <expr>)*)
<map>            :=  [<mapType>] "[" <mapItems> "]"
<mapItems>       :=  ":" | (<mapPair> ("," <mapPair>)*)
<mapPair>        :=  <expr> ":" <expr>
<symbolLiteral>  :=  "@" [<id> "::"] <id>

See Literals for grammar of the literal tokens.

Type

<type>           :=  <nullType> | <nonNullType>
<nullType>       :=  <nonNullType> "?"
<nonNullType>    :=  <simpleType> | <listType> | <mapType> | <funcType>
<typeList>       :=  <type> ("," <type>)*
<simpleType>     :=  <id> ["::" <id>]
<listType>       :=  <type> "[]"
<mapType>        :=  ["["] <type> ":" <type> ["]"]
<funcType>       :=  "|" [formals] "->" [type] "|"
<formals>        :=  [<formal> ("," <formal>)*]
<formal>         :=  <formalFull> | <formalInferred> | <formalTypeOnly>
<formalFull>     :=  <type> <id>
<formalInferred> :=  <id>
<formalTypeOnly> :=  <type>

Misc

<id>             := <idStart> (idChar)*
<idStart>        := A-Z | a-z | _
<idChar>         := A-Z | a-z | _ | 0-9
<eos>            := ; | \n | }

Keywords

abstract      for              return
as            foreach          static
assert        if               super
break         internal         switch
case          is               this
catch         isnot            throw
class         mixin            true
const         native           try
continue      new              using
default       null             virtual
do            once             volatile
else          override         void
enum          private          while
false         protected
final         public
finally       readonly