tx3-lang 0.4.1

A DSL for defining protocols that run on UTxO blockchains
Documentation
WHITESPACE = _{ " " | "\t" | "\n" | "\r" }
COMMENT = _{ "//" ~ (!"\n" ~ ANY)* | "/*" ~ (!"*/" ~ ANY)* ~ "*/" }

// Identifiers and basic types
identifier = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "_")* }
ascii_text = @{ ASCII_ALPHANUMERIC+ }
number = @{ "-"? ~ ASCII_DIGIT+ }
string = @{ "\"" ~ (!"\"" ~ ANY)* ~ "\"" }
bool = @{ "true" | "false" }
hex_string = @{ "0x" ~ ASCII_HEX_DIGIT+ }
wildcard = @{ "*" }
unit = { "()" }
utxo_ref = { "0x" ~ ASCII_HEX_DIGIT+ ~ "#" ~ ASCII_DIGIT+ }

// Type identifiers

primitive_type = {
    "Int" |
    "Bool" |
    "Bytes" |
    "AnyAsset" |
    "Address" |
    "UtxoRef"
}

custom_type = { identifier }
list_type = { "List<" ~ type ~ ">" }

type = { 
    primitive_type |
    list_type |
    custom_type
}

// Parameters
parameter = { identifier ~ ":" ~ type }
parameter_list = { "(" ~ (parameter ~ ("," ~ parameter)* ~ ","?)? ~ ")" }

// Asset definitions
asset_def = {
    "asset" ~ identifier ~ "=" ~ hex_string ~ "." ~ ascii_text ~ ";"
}

// Party definitions
party_def = {
    "party" ~ identifier ~ ";"
}

// Policy definitions
policy_def_assign = {
    "=" ~ hex_string ~ ";"
}

policy_def_hash = { "hash" ~ ":" ~ data_expr }
policy_def_script = { "script" ~ ":" ~ data_expr }
policy_def_ref = { "ref" ~ ":" ~ data_expr }

policy_def_field = _{
    policy_def_hash |
    policy_def_ref |
    policy_def_script
}

policy_def_constructor = {
    "{" ~ (policy_def_field ~ ",")* ~ "}"
}

policy_def_value = _{  policy_def_assign | policy_def_constructor }

policy_def = {
    "policy" ~ identifier ~ policy_def_value
}

// Type definitions
record_field = { identifier ~ ":" ~ type }

record_def = {
    "type" ~ identifier ~ "{" ~
    (record_field ~ ",")* ~
    "}"
}

variant_case_struct = {
    identifier ~ "{" ~
    (record_field ~ ",")* ~
    "}"
}

variant_case_tuple = {
    identifier ~ "(" ~
    (type ~ ",")* ~
    ")"
}

variant_case_unit = {
    identifier
}

variant_case = _{
    variant_case_struct |
    variant_case_tuple |
    variant_case_unit
}

variant_def = {
    "type" ~ identifier ~ "{" ~
    (variant_case ~ ",")* ~
    "}"
}

type_def = _{
    record_def |
    variant_def
}

// Expressions
property_access = { identifier ~ "." ~ identifier ~ ("." ~ identifier)* }

static_asset_constructor = {
    identifier ~ "(" ~ data_expr ~ ("," ~ data_expr)? ~ ")"
}

any_asset_constructor = {
    "AnyAsset" ~ "(" ~ data_expr ~ "," ~ data_expr ~ "," ~ data_expr ~ ")"
}

asset_expr = { asset_term ~ (binary_operator ~ asset_term)* }
asset_term = _{ any_asset_constructor | static_asset_constructor | property_access | identifier }

binary_operator = { "+" | "-" }

data_expr = { data_term ~ (binary_operator ~ data_term)* }
data_term = _{
    unit |
    utxo_ref |
    hex_string |
    number |
    bool |
    string |
    struct_constructor |
    list_constructor |
    property_access |
    identifier
}

spread_expression = { "..." ~ data_expr }

record_constructor_field = {
    identifier ~ ":" ~ data_expr
}

explicit_variant_case_constructor = {
    "::" ~ identifier ~ "{" ~
    (record_constructor_field ~ ",")* ~
    spread_expression? ~
    "}"
}

implicit_variant_case_constructor = {
    "{" ~
    (record_constructor_field ~ ",")* ~
    spread_expression? ~
    "}"
}

variant_case_constructor = _{
    explicit_variant_case_constructor |
    implicit_variant_case_constructor
}

struct_constructor = {
    identifier ~ variant_case_constructor
}

list_constructor = {
    "[" ~ (data_expr ~ ",")* ~ data_expr? ~ "]"
}

address_expr = {
    identifier |
    hex_string |
    string
}

// input block

input_block_from = { "from" ~ ":" ~ address_expr }
input_block_datum_is = { "datum_is" ~ ":" ~ type }
input_block_min_amount = { "min_amount" ~ ":" ~ asset_expr }
input_block_redeemer = { "redeemer" ~ ":" ~ data_expr }
input_block_ref = { "ref" ~ ":" ~ data_expr }

input_block_field = _{
    input_block_from |
    input_block_datum_is |
    input_block_min_amount |
    input_block_redeemer |
    input_block_ref
}

input_block = {
    "input" ~ identifier ~ ("*")? ~ "{" ~
    (input_block_field ~ ",")* ~
    "}"
}

collateral_block_field = _{
    input_block_from |
    input_block_min_amount |
    input_block_ref
}

collateral_block = {
    "collateral" ~ "{" ~
    (collateral_block_field ~ ",")* ~
    "}"
}

reference_block = {
    "reference" ~ identifier ~ ("*")? ~ "{" ~
    input_block_ref ~ "," ~
    "}"
}

output_block_to = { "to" ~ ":" ~ address_expr }
output_block_amount = { "amount" ~ ":" ~ asset_expr }
output_block_datum = { "datum" ~ ":" ~ data_expr }

output_block_field = _{
    output_block_to |
    output_block_amount |
    output_block_datum
}

output_block = {
    "output" ~ identifier? ~ "{" ~
    (output_block_field ~ ",")* ~
    "}"
}

mint_block_amount = { "amount" ~ ":" ~ asset_expr }
mint_block_redeemer = { "redeemer" ~ ":" ~ data_expr }

mint_block_field = _{
    mint_block_amount |
    mint_block_redeemer
}

mint_block = {
    "mint" ~ "{" ~
    (mint_block_field ~ ",")* ~
    "}"
}

burn_block = {
    "burn" ~ "{" ~
    (mint_block_field ~ ",")* ~
    "}"
}

cardano_stake_delegation_certificate = {
    "stake_delegation_certificate" ~ "{" ~
    (record_constructor_field ~ ",")* ~
    "}"
}

cardano_vote_delegation_certificate = {
    "vote_delegation_certificate" ~ "{" ~
    "drep" ~ ":" ~ data_expr ~ "," ~
    "stake" ~ ":" ~ data_expr ~ "," ~
    "}"
}

cardano_block = {
    "cardano" ~ "::" ~ (cardano_stake_delegation_certificate | cardano_vote_delegation_certificate)
}

bitcoin_block = {
    "bitcoin" ~ "::" ~ identifier
}

chain_specific_block = {
    cardano_block |
    bitcoin_block
}

// Transaction definition
tx_def = {
    "tx" ~ identifier ~ parameter_list ~ "{" ~
    reference_block* ~
    input_block* ~
    collateral_block* ~
    burn_block? ~
    mint_block? ~
    output_block* ~
    chain_specific_block* ~
    "}"
}

// Program
program = {
    SOI ~
    (asset_def | party_def | policy_def | type_def | tx_def)* ~
    EOI
}