Tact Specification
Tact grammar used in its compiler is written in an Ohm language, which is based on parsing expression grammars (PEGs), which are a formal way of describing syntax, similar to regular expressions and context-free grammars.
Tact {
// Starting point of the program Program = ProgramItem* ProgramItem = Struct | Contract | Primitive | StaticFunction | NativeFunction | ProgramImport | Trait | Constant ProgramImport = import stringLiteral ";"
// Built-in declarations Primitive = "primitive" Type ";"
// Static function StaticFunction = Function NativeFunction = nameAttribute "(" funcId ")" FunctionAttribute* native id "(" ListOf<FunctionArg,","> ")" ";" --withVoid | nameAttribute "(" funcId ")" FunctionAttribute* native id "(" ListOf<FunctionArg,","> ")" ":" Type ";" --withType
// Field declarations Type = typeLiteral "?" --optional | typeLiteral --required | "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
// Constant ConstantAttribute = virtual --virtual | override --override | abstract --abstract Constant = ConstantAttribute* ~fun const id ":" Type "=" Expression ";" --withValue | ConstantAttribute* ~fun const id ":" Type ";" --withEmpty
// Struct Struct = "struct" typeLiteral "{" StructBody* "}" --originary | "message" typeLiteral "{" StructBody* "}" --message | "message" "(" integerLiteral ")" typeLiteral "{" StructBody* "}" --messageWithId StructBody = Field
// Contract Contract = ContractAttribute* contract id "{" ContractBody* "}" --simple | ContractAttribute* contract id with ListOf<id,","> "{" ContractBody* "}" --withTraits ContractInit = "init" "(" ListOf<FunctionArg,","> ")" "{" Statement* "}" ContractBody = Field | ContractInit | ReceiveFunction | Function | Constant
// Trait Trait = ContractAttribute* trait id "{" TraitBody* "}" --originary | ContractAttribute* trait id with ListOf<id,","> "{" TraitBody* "}" --withTraits TraitBody = Field | ReceiveFunction | Function | Constant
// Contract attributes ContractAttribute = "@interface" "(" stringLiteral ")" --interface
// Function FunctionAttribute = "get" --getter | mutates --mutates | extends --extends | virtual --virtual | override --override | inline --inline | abstract --abstract 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
// Statements Statement = StatementLet | StatementBlock | StatementReturn | StatementExpression | StatementAssign | StatementAugmentedAssign | StatementCondition | StatementWhile | StatementRepeat | StatementUntil 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 ")" ";"
// L-value LValue = id "." LValue --more | id --single
// Expressions Expression = ExpressionConditional ExpressionConditional = ExpressionOr "?" ExpressionOr ":" ExpressionConditional --ternary | ExpressionOr ExpressionOr = ExpressionOr "||" ExpressionAnd --or | ExpressionAnd ExpressionAnd = ExpressionAnd "&&" ExpressionCompare --and | ExpressionCompare ExpressionCompare = ExpressionCompare "!=" ExpressionBinary --not | ExpressionCompare "==" ExpressionBinary --eq | ExpressionCompare ">" ExpressionBinary --gt | ExpressionCompare ">=" ExpressionBinary --gte | ExpressionCompare "<" ExpressionBinary --lt | ExpressionCompare "<=" ExpressionBinary --lte | ExpressionBinary ExpressionBinary = ExpressionBinary ">>" ExpressionAdd --shr | ExpressionBinary "<<" ExpressionAdd --shl | ExpressionBinary "&" ExpressionAdd --bin_and | ExpressionBinary "|" ExpressionAdd --bin_or | ExpressionAdd ExpressionAdd = ExpressionAdd "+" ~"+" ExpressionMul --add | ExpressionAdd "-" ~"-" ExpressionMul --sub | ExpressionMul ExpressionMul = ExpressionMul "*" ExpressionUnary --mul | ExpressionMul "/" ExpressionUnary --div | ExpressionMul "%" ExpressionUnary --rem | ExpressionUnary ExpressionUnary = "-" ExpressionUnarySuffix --neg | "+" ExpressionUnarySuffix --add | "!" ExpressionUnarySuffix --not | ExpressionUnarySuffix ExpressionUnarySuffix = ExpressionValue "!!" --notNull | ExpressionValue ExpressionBracket = "(" Expression ")"
// Order is important ExpressionValue = ExpressionCall | ExpressionField | ExpressionStaticCall | ExpressionBracket | ExpressionNew | integerLiteral | boolLiteral | id | null | ExpressionInitOf | ExpressionString 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, ","> ")"
// Type Literal typeLiteral = letterAsciiUC typeLiteralPart* typeLiteralPart = letterAscii | digit | "_"
// Integer Literal // 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)* binDigit = "0" | "1" octDigit = "0".."7" nonZeroDigit = "1".."9"
// Letters letterAsciiLC = "a".."z" letterAsciiUC = "A".."Z" letterAscii = letterAsciiLC | letterAsciiUC letterComment = letterAsciiLC | letterAsciiUC | digit | "_"
// ID Literal idStart = letterAscii | "_" idPart = letterAscii | digit | "_" id = ~reservedWord #idStart #(idPart*)
// FunC id funcLetter = letterAscii | "_" | "'" | "?" | "!" | "::" | "&" funcId = funcLetter #(funcLetter | digit)*
// Bool Literal boolLiteral = ("true" | "false") ~idPart
// String literal stringLiteralCharacter = ~("\"" | "\\" | lineTerminator) any stringLiteral = "\"" stringLiteralCharacter* "\""
// Keywords // NOTE Order is important keyword = fun | let | return | extend | native | public | null | if | else | while | repeat | do | until | as | mutates | extends | import | with | trait | initOf | override | abstract | virtual | inline | const contract = "contract" ~idPart let = "let" ~idPart fun = "fun" ~idPart return = "return" ~idPart extend = "extend" ~idPart native = "native" ~idPart public = "public" ~idPart null = "null" ~idPart if = "if" ~idPart else = "else" ~idPart while = "while" ~idPart repeat = "repeat" ~idPart do = "do" ~idPart until = "until" ~idPart as = "as" ~idPart mutates = "mutates" ~idPart extends = "extends" ~idPart import = "import" ~idPart with = "with" ~idPart trait = "trait" ~idPart initOf = "initOf" ~idPart virtual = "virtual" ~idPart override = "override" ~idPart inline = "inline" ~idPart const = "const" ~idPart abstract = "abstract" ~idPart
// Attributes nameAttribute = "@name"
// Reserved reservedWord = keyword
// Comments space += comment | lineTerminator comment = multiLineComment | singleLineComment lineTerminator = "\n" | "\r" | "\u2028" | "\u2029" multiLineComment = "/*" (~"*/" any)* "*/" singleLineComment = "//" (~lineTerminator any)*}