Skip to content

Tact Specification

This content is not available in your language yet.

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.

Terminal window
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)*
}