// Starting point of the program
ProgramImport = import stringLiteral ";"
Primitive = "primitive" Type ";"
StaticFunction = Function
NativeFunction = nameAttribute "(" funcId ")" FunctionAttribute* native id "(" ListOf<FunctionArg,","> ")" ";" --withVoid
| nameAttribute "(" funcId ")" FunctionAttribute* native id "(" ListOf<FunctionArg,","> ")" ":" Type ";" --withType
Type = typeLiteral "?" --optional
| "map" "<" typeLiteral (as id)? "," typeLiteral (as id)? ">" --map
| "bounced" "<" typeLiteral ">" --bounced
Field = id ":" Type ";" --default
| id ":" Type "=" Expression ";" --defaultWithInit
| id ":" Type as id ";" --withSerialization
| id ":" Type as id "=" Expression ";" --withSerializationAndInit
ConstantAttribute = virtual --virtual
Constant = ConstantAttribute* ~fun const id ":" Type "=" Expression ";" --withValue
| ConstantAttribute* ~fun const id ":" Type ";" --withEmpty
Struct = "struct" typeLiteral "{" StructBody* "}" --originary
| "message" typeLiteral "{" StructBody* "}" --message
| "message" "(" integerLiteral ")" typeLiteral "{" StructBody* "}" --messageWithId
Contract = ContractAttribute* contract id "{" ContractBody* "}" --simple
| ContractAttribute* contract id with ListOf<id,","> "{" ContractBody* "}" --withTraits
ContractInit = "init" "(" ListOf<FunctionArg,","> ")" "{" Statement* "}"
Trait = ContractAttribute* trait id "{" TraitBody* "}" --originary
| ContractAttribute* trait id with ListOf<id,","> "{" TraitBody* "}" --withTraits
ContractAttribute = "@interface" "(" stringLiteral ")" --interface
FunctionAttribute = "get" --getter
Function = FunctionAttribute* fun id "(" ListOf<FunctionArg,","> ")" "{" Statement* "}" --withVoid
| FunctionAttribute* fun id "(" ListOf<FunctionArg,","> ")" ":" Type "{" Statement* "}" --withType
| FunctionAttribute* fun id "(" ListOf<FunctionArg,","> ")" ";" --abstractVoid
| FunctionAttribute* fun id "(" ListOf<FunctionArg,","> ")" ":" Type ";" --abstractType
FunctionArg = id ":" Type
ReceiveFunction = "receive" "(" FunctionArg ")" "{" Statement* "}" --simple
| "receive" "(" ")" "{" Statement* "}" --empty
| "receive" "(" stringLiteral ")" "{" Statement* "}" --comment
| "bounced" "(" FunctionArg ")" "{" Statement* "}" --bounced
| "external" "(" FunctionArg ")" "{" Statement* "}" --externalSimple
| "external" "(" stringLiteral ")" "{" Statement* "}" --externalComment
| "external" "(" ")" "{" Statement* "}" --externalEmpty
| StatementAugmentedAssign
StatementBlock = "{" Statement* "}"
StatementLet = let id ":" Type "=" Expression ";"
StatementReturn = return Expression ";" --withExpression
| return ";" --withoutExpression
StatementExpression = Expression ";"
StatementAssign = LValue "=" Expression ";"
StatementAugmentedAssign = StatementAugmentedAssignAdd
| StatementAugmentedAssignSub
| StatementAugmentedAssignMul
| StatementAugmentedAssignDiv
| StatementAugmentedAssignRem
StatementAugmentedAssignAdd = LValue "+=" Expression ";"
StatementAugmentedAssignSub = LValue "-=" Expression ";"
StatementAugmentedAssignMul = LValue "*=" Expression ";"
StatementAugmentedAssignDiv = LValue "/=" Expression ";"
StatementAugmentedAssignRem = LValue "%=" Expression ";"
StatementCondition = if Expression "{" Statement* "}" ~else --simple
| if Expression "{" Statement* "}" else "{" Statement* "}" --withElse
| if Expression "{" Statement* "}" else StatementCondition --withElseIf
StatementWhile = while "(" Expression ")" "{" Statement* "}"
StatementRepeat = repeat "(" Expression ")" "{" Statement* "}"
StatementUntil = do "{" Statement* "}" until "(" Expression ")" ";"
LValue = id "." LValue --more
Expression = ExpressionConditional
ExpressionConditional = ExpressionOr "?" ExpressionOr ":" ExpressionConditional --ternary
ExpressionOr = ExpressionOr "||" ExpressionAnd --or
ExpressionAnd = ExpressionAnd "&&" ExpressionCompare --and
ExpressionCompare = ExpressionCompare "!=" ExpressionBinary --not
| ExpressionCompare "==" ExpressionBinary --eq
| ExpressionCompare ">" ExpressionBinary --gt
| ExpressionCompare ">=" ExpressionBinary --gte
| ExpressionCompare "<" ExpressionBinary --lt
| ExpressionCompare "<=" ExpressionBinary --lte
ExpressionBinary = ExpressionBinary ">>" ExpressionAdd --shr
| ExpressionBinary "<<" ExpressionAdd --shl
| ExpressionBinary "&" ExpressionAdd --bin_and
| ExpressionBinary "|" ExpressionAdd --bin_or
ExpressionAdd = ExpressionAdd "+" ~"+" ExpressionMul --add
| ExpressionAdd "-" ~"-" ExpressionMul --sub
ExpressionMul = ExpressionMul "*" ExpressionUnary --mul
| ExpressionMul "/" ExpressionUnary --div
| ExpressionMul "%" ExpressionUnary --rem
ExpressionUnary = "-" ExpressionUnarySuffix --neg
| "+" ExpressionUnarySuffix --add
| "!" ExpressionUnarySuffix --not
ExpressionUnarySuffix = ExpressionValue "!!" --notNull
ExpressionBracket = "(" Expression ")"
ExpressionValue = ExpressionCall
ExpressionString = stringLiteral
ExpressionField = ExpressionValue "." id ~"("
ExpressionCall = ExpressionValue "." id "(" ListOf<Expression, ","> ")"
ExpressionNew = id "{" ListOf<NewParameter, ","> "}"
NewParameter = id ":" Expression
ExpressionStaticCall = id "(" ListOf<Expression, ","> ")"
ExpressionInitOf = initOf id "(" ListOf<Expression, ","> ")"
typeLiteral = letterAsciiUC typeLiteralPart*
typeLiteralPart = letterAscii | digit | "_"
// hexDigit defined in Ohm's built-in rules (otherwise: hexDigit = "0".."9" | "a".."f" | "A".."F")
// digit defined in Ohm's built-in rules (otherwise: digit = "0".."9")
integerLiteral = integerLiteralHex | integerLiteralBin | integerLiteralOct | integerLiteralDec // Order is important
integerLiteralDec = nonZeroDigit ("_"? digit)* --nonZeroIntegerLiteralDec
| "0" digit* --integerLiteralWithLeadingZero
integerLiteralHex = ("0x" | "0X") hexDigit ("_"? hexDigit)*
integerLiteralBin = ("0b" | "0B") binDigit ("_"? binDigit)*
integerLiteralOct = ("0o" | "0O") octDigit ("_"? octDigit)*
letterAscii = letterAsciiLC | letterAsciiUC
letterComment = letterAsciiLC | letterAsciiUC | digit | "_"
idStart = letterAscii | "_"
idPart = letterAscii | digit | "_"
id = ~reservedWord #idStart #(idPart*)
funcLetter = letterAscii | "_" | "'" | "?" | "!" | "::" | "&"
funcId = funcLetter #(funcLetter | digit)*
boolLiteral = ("true" | "false") ~idPart
stringLiteralCharacter = ~("\"" | "\\" | lineTerminator) any
stringLiteral = "\"" stringLiteralCharacter* "\""
// NOTE Order is important
contract = "contract" ~idPart
return = "return" ~idPart
extend = "extend" ~idPart
native = "native" ~idPart
public = "public" ~idPart
repeat = "repeat" ~idPart
mutates = "mutates" ~idPart
extends = "extends" ~idPart
import = "import" ~idPart
initOf = "initOf" ~idPart
virtual = "virtual" ~idPart
override = "override" ~idPart
inline = "inline" ~idPart
abstract = "abstract" ~idPart
space += comment | lineTerminator
comment = multiLineComment | singleLineComment
lineTerminator = "\n" | "\r" | "\u2028" | "\u2029"
multiLineComment = "/*" (~"*/" any)* "*/"
singleLineComment = "//" (~lineTerminator any)*