Crate marlowe_lang
source · [−]Expand description
An experimental implementation of the Marlowe language for Cardano smart contracts.
Its primary use-case is for creating smart contracts in Rust rather than directly using Marlowe, and instead be able to export the contracts into Marlowe programatically.
Parser tests are done against all example
contracts available on the Marlowe Playground as seen on 2022-06-06.
( Deserialize -> Re-serialize -> Compare )
Stability
At the time of writing this, the language specification of Marlowe is not yet finalized and so this crate may not exactly reflect the current syntax as seen in official implementations such as the Marlowe playground.
When the Marlowe v3 specs are finalized, this crate will (hopefully) be updated to reflect those.
Main entry-points:
This crate uses Pest.rs!
[grammars.rs] Click to expand/collapse
WHITESPACE = _{ " " | "\t" | "\r" | "\n" | "\r\n" }
comma = _{ "," }
lpar = _{ "(" }
rpar = _{ ")" }
lbra = _{ "[" }
rbra = _{ "]" }
Number = ${ "-"{0,1} ~ ASCII_DIGIT+ }
quoted_string = _{ "\"" ~ string ~ "\"" }
string = { str_char* }
str_char = _{
!("\"" | "\\") ~ ANY
| "\\" ~ ("\"" | "\\" )
}
Bound = ${ "Bound" ~ WHITESPACE+ ~ Number ~ WHITESPACE+ ~ Number}
xBound = _{
BoundHole | Bound | lpar ~ Bound ~ rpar
}
Timeout = _{ TimeoutHole | TimeConstant | Number | TimeParam }
TimeConstant = { ASCII_DIGIT+ }
TimeInterval = ${ lpar ~ WHITESPACE* ~ "TimeInterval" ~ WHITESPACE+ ~ Timeout ~ WHITESPACE+ ~ Timeout ~ WHITESPACE* ~ rpar }
TimeParam = ${ lpar ~ WHITESPACE* ~ "TimeParam" ~ WHITESPACE+ ~ quoted_string ~ WHITESPACE* ~ rpar }
Token = _{TokenHole|ADA|Currency}
ADA = { "Token \"\" \"\"" }
Currency = ${ lpar ~ WHITESPACE* ~ "Token" ~ WHITESPACE+ ~ quoted_string ~ WHITESPACE+ ~ quoted_string ~ WHITESPACE* ~ rpar }
ChoiceId = ${ lpar ~ WHITESPACE* ~"ChoiceId" ~ WHITESPACE+ ~ quoted_string ~ WHITESPACE+ ~ Party ~ WHITESPACE* ~ rpar}
Value = _{
Constant
| ConstantParam
| AvailableMoney
| Cond
| ChoiceValue
| MulValue
| DivValue
| SubValue
| AddValue
| NegValue
| UseValue
| TimeIntervalStart
| TimeIntervalEnd
| ValueHole
}
TimeIntervalStart = { "TimeIntervalStart" }
TimeIntervalEnd = { "TimeIntervalEnd" }
Cond = ${ lpar ~ WHITESPACE* ~ "Cond" ~ WHITESPACE+ ~ Observation ~ WHITESPACE+ ~ Value ~ WHITESPACE+ ~ Value ~ WHITESPACE* ~ rpar}
ChoiceValue = ${ lpar ~ WHITESPACE* ~ "ChoiceValue" ~ WHITESPACE+ ~ ChoiceId ~ WHITESPACE* ~ rpar}
MulValue = ${ lpar ~ WHITESPACE* ~ "MulValue" ~ WHITESPACE+ ~ Value ~ WHITESPACE+ ~ Value ~ WHITESPACE* ~ rpar }
DivValue = ${ lpar ~ WHITESPACE* ~ "DivValue" ~ WHITESPACE+ ~ Value ~ WHITESPACE+ ~ Value ~ WHITESPACE* ~ rpar}
SubValue = ${ lpar ~ WHITESPACE* ~ "SubValue" ~ WHITESPACE+ ~ Value ~ WHITESPACE+ ~ Value ~ WHITESPACE* ~ rpar}
AddValue = ${ lpar ~ WHITESPACE* ~ "AddValue" ~ WHITESPACE+ ~ Value ~ WHITESPACE+ ~ Value ~ WHITESPACE* ~ rpar}
NegValue = ${ lpar ~ WHITESPACE* ~ "NegValue" ~ WHITESPACE+ ~ Value ~ WHITESPACE* ~ rpar}
UseValue = ${ lpar ~ WHITESPACE* ~ "UseValue" ~ WHITESPACE+ ~ quoted_string ~ WHITESPACE* ~ rpar}
Constant = ${ lpar ~ WHITESPACE* ~ "Constant" ~ WHITESPACE+ ~ Number ~ WHITESPACE* ~ rpar }
ConstantParam = ${ lpar ~ WHITESPACE* ~ "ConstantParam" ~ WHITESPACE+ ~ quoted_string ~ WHITESPACE* ~ rpar }
AvailableMoney = ${ lpar ~ WHITESPACE* ~ "AvailableMoney" ~ WHITESPACE+ ~ Party ~ WHITESPACE+ ~ Token ~ WHITESPACE* ~ rpar}
Observation = _{ ObservationHole | TrueObs | FalseObs | ValueEQ | ValueLE |
ValueLT | ValueGT | ValueGE | OrObs |
NotObs | AndObs | ChoseSomething }
ValueEQ = ${ lpar ~ WHITESPACE* ~ "ValueE" ~ WHITESPACE+ ~ Value ~ WHITESPACE+ ~ Value ~WHITESPACE* ~ rpar }
ValueLE = ${ lpar ~ WHITESPACE* ~ "ValueLE" ~ WHITESPACE+ ~ Value ~ WHITESPACE+ ~ Value ~WHITESPACE* ~ rpar }
ValueLT = ${ lpar ~ WHITESPACE* ~ "ValueLT" ~ WHITESPACE+ ~ Value ~ WHITESPACE+ ~ Value ~WHITESPACE* ~ rpar }
ValueGT = ${ lpar ~ WHITESPACE* ~ "ValueGT" ~ WHITESPACE+ ~ Value ~ WHITESPACE+ ~ Value ~WHITESPACE* ~ rpar }
ValueGE = ${ lpar ~ WHITESPACE* ~ "ValueGE" ~ WHITESPACE+ ~ Value ~ WHITESPACE+ ~ Value ~WHITESPACE* ~ rpar }
TrueObs = { "TrueObs" }
FalseObs = { "FalseObs" }
ChoseSomething = @{ lpar ~ WHITESPACE* ~ "ChoseSomething" ~ WHITESPACE+ ~ ChoiceId ~WHITESPACE*~ rpar }
NotObs = ${ lpar ~ WHITESPACE* ~ "NotObs" ~ WHITESPACE+ ~ Observation ~ WHITESPACE* ~ rpar }
OrObs = ${ lpar ~ WHITESPACE* ~ "OrObs" ~ WHITESPACE+ ~ Observation ~ WHITESPACE+ ~ Observation ~ WHITESPACE* ~ rpar }
AndObs = ${ lpar ~ WHITESPACE* ~ "AndObs" ~ WHITESPACE+ ~ Observation ~ WHITESPACE+ ~ Observation ~ WHITESPACE* ~ rpar }
Action = _{ ActionHole | Notify | Choice | Deposit }
Deposit = ${ lpar ~ WHITESPACE* ~"Deposit" ~ WHITESPACE+ ~ Party ~ WHITESPACE+ ~ FromParty ~ WHITESPACE+ ~ Token ~ WHITESPACE+ ~ Value ~ WHITESPACE* ~ rpar }
Choice = ${ lpar ~ WHITESPACE* ~"Choice" ~ WHITESPACE+ ~ ChoiceId ~ WHITESPACE+ ~ ArrayOfBounds ~ WHITESPACE* ~ rpar }
Notify = ${ lpar ~ WHITESPACE* ~"Notify" ~ WHITESPACE+ ~ Observation ~ WHITESPACE* ~ rpar }
Case = ${
lpar ~ WHITESPACE* ~ "Case" ~ WHITESPACE+ ~ Action ~ WHITESPACE+ ~ WrappedContract ~ WHITESPACE* ~ rpar
| "Case" ~ WHITESPACE+ ~ Action ~ WHITESPACE+ ~ WrappedContract
}
Payee = _{ PayeeHole | PayeeAccount | PayeeParty }
PayeeAccount = ${ lpar ~ "Account" ~ WHITESPACE+ ~ Party ~ rpar }
PayeeParty = ${ lpar ~ "Party" ~ WHITESPACE+ ~ Party ~ rpar }
Party = _{ PartyHole | Role | PK }
FromParty = _{ FromPartyHole | Role | PK }
Role = ${ lpar ~ "Role" ~ WHITESPACE+ ~ quoted_string ~ rpar }
PubKey = ${ "\"" ~ ("0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"|"A"|"B"|"C"|"D"|"E"|"F"){64,64} ~ "\"" }
PK = ${ lpar ~ "PK" ~ WHITESPACE+ ~ PubKey ~ rpar }
Account = ${ "Account" ~ WHITESPACE+ ~ Party }
MainContract = _{ Contract ~ EOI }
Contract = { Close | When | If | Let | Assert | Pay }
When = ${ "When" ~ WHITESPACE+ ~ ArrayOfCases ~ WHITESPACE+ ~ Timeout ~ WHITESPACE+ ~ WrappedContract }
Pay = ${ "Pay" ~ WHITESPACE+ ~ Party ~ WHITESPACE+ ~ Payee ~ WHITESPACE+ ~ Token ~ WHITESPACE+ ~ Value ~ WHITESPACE+ ~ WrappedContract }
If = ${ "If" ~ WHITESPACE+ ~ Observation ~ WHITESPACE+ ~ WrappedContract ~ WHITESPACE+ ~ WrappedContract }
Let = ${ "Let" ~ WHITESPACE+ ~ quoted_string ~ WHITESPACE+ ~ Value ~ WHITESPACE+ ~ WrappedContract }
Assert = ${ "Assert" ~ WHITESPACE+ ~ Observation ~ WHITESPACE+ ~ WrappedContract }
Close = { "Close" }
WrappedContract = _{
ContractHole | Close | "(" ~ WHITESPACE* ~ (Assert|Let|If|Pay|When) ~ WHITESPACE* ~ ")"
}
ArrayOfCases = ${
lbra ~ WHITESPACE* ~ (Case|CaseHole) ~ (WHITESPACE* ~ "," ~ WHITESPACE* ~ (Case|CaseHole))* ~ WHITESPACE* ~ rbra
| lbra ~ WHITESPACE* ~ rbra
}
ArrayOfBounds = ${
lbra ~ WHITESPACE* ~ xBound ~ (WHITESPACE* ~ "," ~ WHITESPACE* ~ xBound)* ~ WHITESPACE* ~ rbra
| lbra ~ WHITESPACE* ~ rbra
}
Hole = _ { "?"~("-"|"_"|ASCII_DIGIT|ASCII_ALPHA)* }
PartyHole = { Hole }
FromPartyHole = { Hole }
ContractHole = { Hole }
PayeeHole = { Hole }
ValueHole = { Hole }
ObservationHole = { Hole }
TimeoutHole = { Hole }
TokenHole = { Hole }
BoundHole = { Hole }
RoleHole = { Hole }
PubkeyHole = { Hole }
CaseHole = { Hole }
ActionHole = { Hole }
AccountHole = { Hole }
Example usage
use marlowe_lang::types::marlowe::*;
use marlowe_lang::parsing::{
deserialization::deserialize,
serialization::serialize,
};
let my_contract = Contract::When {
when: vec![
Some(Case {
case: Some(Action::Notify {
notify_if: Some(Observation::True)
}),
then: Some(Contract::Close.boxed()) })
],
timeout: Some(Timeout::TimeParam("test".into())),
timeout_continuation: Some(Contract::Close.boxed()),
};
let serialized = serialize(my_contract);
let deserialized : Contract = deserialize(&serialized).unwrap();
println!("{serialized}");
Where ‘println!(“{serialized}”)’ would output this:
When [ Case (Notify (True)) Close ] (TimeParam "test") Close