Skip to content

Tutorial: Building a Music Touring Performance Deal (Step by Step)

DANGER

This is not correct, it's more of a placeholder

This tutorial walks you through constructing a Music Touring Performance Deal in the DealModel DSL. We’ll start small (header), add inputs (via JSON Schema), then layer in variables, operators, events, clauses, clause blocks, a type, and computations. By the end, you’ll have a clean, working model you can validate in the ANTLR Lab.

Tip: in the ANTLR Lab, always Generate after pasting your grammar, then Run your input with Start rule set to model. Keep the version unquoted (e.g., 1.0.0, not "1.0.0").

1. Start with the Model Header

Every model begins with a header that declares its deal type and version.

antlr
model { deal_type: "Music Touring Performance Deal", version: 1.0.0 }
FieldTypeDescription
deal_typeTEXT or STRINGHuman-readable identifier for the deal type.
versionSEMVERUnquoted semantic version (e.g., 1.0.0).

2. Add Inputs

Your model references a JSON Schema to describe the exact shape of the data that deal instances will provide. Think of this schema as describing the specific inputs for a particular deal. Using schema in this manner keeps the DSL grammar clean while allowing different deals to carry different data structures.

You can read the docs for JSON Schema in the link above to help you design your schema.

You can also use schema design tools to help you build your schema.

Reference your schema (recommended):

antlr
inputs { ref: "https://schemas.example.com/models/music-touring/performance/1.0.0.json" }

Or inline a small schema during prototyping:

antlr
inputs {
  schema: """{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object" }"""
}

Example: schema fragment for a deal-specific simple clause

json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "simple_clauses": {
      "type": "object",
      "properties": {
        "headline_billing": {
          "type": "string",
          "minLength": 1,
          "description": "Deal-specific text for headline billing."
        }
      },
      "additionalProperties": false
    }
  }
}

3. Selectors (optional, but helpful)

Selectors assign readable names to JSON paths so your expressions are cleaner.

antlr
selectors {
  show_revenue: "$.shows[*].revenue"
  fees_path: "$..fees[*]"
}

You’ll use these in computations (e.g., sum(show_revenue)).

4. Variables

Declare instance-bound variables (and optional derived ones).

antlr
var performance_date
var venue_name
var guarantee_amount
var pct_nbor
var nbor
var nbor_threshold_value
var payout_schedule_id

5. Operators

Operators describe how clauses (or blocks) combine. We’ll use a standard versus operator (or).

antlr
operator { name: versus display: "vs" type: or }
FieldDescription
nameIdentifier used in expressions.
displayLabel used in UI or templates.
typeand (additive) or or (exclusive / versus).

6. Events

Events are boolean conditions that gate financial clauses or blocks.

antlr
event {
  name: nbor_threshold
  description: "NBOR meets or exceeds the required threshold"
  condition: nbor >= nbor_threshold_value
}

Event conditions support arithmetic, comparisons, logical operators (&&, ||, !), and function calls like input(path).

7. Add a Simple Clause (pure text from inputs)

Simple clauses are often deal-specific prose provided in instance inputs. Render that text via input() in the template.

antlr
clause {
  name: headline_billing
  kind: simple
  description: "Deal-specific headline billing text"
  template: """
  {{ input("/simple_clauses/headline_billing") }}
  """
}

8. Add a Guarantee Clause (financial)

Guarantees are paid when active (they can still depend on a deliverable event if you choose to add a when:).

antlr
clause {
  name: base_guarantee
  kind: guarantee
  description: "Minimum guaranteed payment to the Artist"
  amount: guarantee_amount
  payable: on performance_date
  template: """
  Artist shall be paid a guaranteed fee of {{ money(guarantee_amount, "USD") }}
  for the performance on {{ date(performance_date) }} at {{ input("/venue_name") }}.
  """
}

9. Add a Contingent Clause (financial, event-guarded)

This clause only contributes if the event is true.

antlr
clause {
  name: nbor_share
  kind: contingent
  description: "Artist share of Net Box Office Receipts"
  when: nbor_threshold
  amount: pct_nbor * nbor
  payable: by_schedule payout_schedule_id
  template: """
  Artist shall be paid {{ percent(pct_nbor) }} of the Net Box Office Receipts (“NBOR”)
  for the performance on {{ date(performance_date) }} at {{ input("/venue_name") }}.
  """
}

10. Clause Block (compose the financial logic)

Clause blocks compose clauses (or other blocks). A versus block chooses the greater amount.

antlr
block {
  name: payout
  expr: base_guarantee versus nbor_share
  template: """
  Artist shall be paid the greater of {{ money(guarantee_amount, "USD") }}
  or {{ percent(pct_nbor) }} of NBOR (“Versus Deal”) for the performance on
  {{ date(performance_date) }} at {{ input("/venue_name") }}.
  """
}

11. Type (top-level composition)

The type defines the root composition to evaluate and render.

antlr
type {
  name: touring_performance
  compose: payout
  template: """
  The parties agree to the Performance Deal terms as set forth herein.
  """
}

12. Computations (metrics & outputs)

Define derived metrics and final outputs. Use your selectors here for clean aggregations.

antlr
computations {
  metric total_show_revenue = sum(show_revenue)
  metric total_fees = sum(fees_path)
  metric nbor_share_amount = pct_nbor * nbor

  output guarantee_value = amount(base_guarantee)
  output versus_value    = amount(payout)
  output total_payout    = max(guarantee_value, versus_value)
}

Intrinsics supported in expressions include amount(name), input(path), sum(path), count(path), min(path), max(path), and plugin(name, ...).

13. Full, Copy-Pasteable Model

Paste this into the ANTLR Lab Input pane and run (with your grammar generated):

antlr
model { deal_type: "Music Touring Performance Deal", version: 1.0.0 }

inputs { ref: "https://schemas.example.com/models/music-touring/performance/1.0.0.json" }

selectors {
  show_revenue: "$.shows[*].revenue"
  fees_path: "$..fees[*]"
}

var performance_date
var venue_name
var guarantee_amount
var pct_nbor
var nbor
var nbor_threshold_value
var payout_schedule_id

operator { name: versus display: "vs" type: or }

event {
  name: nbor_threshold
  description: "NBOR meets or exceeds the required threshold"
  condition: nbor >= nbor_threshold_value
}

clause {
  name: headline_billing
  kind: simple
  description: "Deal-specific headline billing text"
  template: """
  {{ input("/simple_clauses/headline_billing") }}
  """
}

clause {
  name: base_guarantee
  kind: guarantee
  description: "Minimum guaranteed payment to the Artist"
  amount: guarantee_amount
  payable: on performance_date
  template: """
  Artist shall be paid a guaranteed fee of {{ money(guarantee_amount, "USD") }}
  for the performance on {{ date(performance_date) }} at {{ input("/venue_name") }}.
  """
}

clause {
  name: nbor_share
  kind: contingent
  description: "Artist share of Net Box Office Receipts"
  when: nbor_threshold
  amount: pct_nbor * nbor
  payable: by_schedule payout_schedule_id
  template: """
  Artist shall be paid {{ percent(pct_nbor) }} of the Net Box Office Receipts (“NBOR”)
  for the performance on {{ date(performance_date) }} at {{ input("/venue_name") }}.
  """
}

block {
  name: payout
  expr: base_guarantee versus nbor_share
  template: """
  Artist shall be paid the greater of {{ money(guarantee_amount, "USD") }}
  or {{ percent(pct_nbor) }} of NBOR (“Versus Deal”) for the performance on
  {{ date(performance_date) }} at {{ input("/venue_name") }}.
  """
}

type {
  name: touring_performance
  compose: payout
  template: """
  The parties agree to the Performance Deal terms as set forth herein.
  """
}

computations {
  metric total_show_revenue = sum(show_revenue)
  metric total_fees = sum(fees_path)
  metric nbor_share_amount = pct_nbor * nbor

  output guarantee_value = amount(base_guarantee)
  output versus_value    = amount(payout)
  output total_payout    = max(guarantee_value, versus_value)
}

14. Testing & Common Pitfalls

IssueSymptomFix
Version quotedmismatched input '"1.0.0"'Remove quotes; use unquoted 1.0.0.
Hidden spacesToken errors at colons or bracesRe-type lines by hand; invisible Unicode spaces may exist.
Duplicate keywordsguarantee or contingent used both as name & kindRename clause IDs to base_guarantee etc.

15. Next Steps

  • Expand your JSON Schema to include deal-specific structures (schedules, deliverables, royalty ladders).
  • Add more events and contingent clauses to model participation bonuses, caps, or escalators.
  • Generate code from the IR to evaluate amounts, validate inputs, and render contract text.

Congratulations — you’ve built your first comple

Confidential. For internal use only.