Example

Money and Dates

Payments with money and dates.

Small single-file spec for payments such as EUR 50.5 due on May 31, 2025.

What it shows

  • $flags: FLEXIBLE_WHITESPACE lets patterns tolerate any whitespace between tokens.
  • Number splits into semantic subtypes Decimal and Integer — order matters, so Decimal is tried first.
  • Month gives each full month name its own stable identity.
  • Date separates YearMonthDay, MonthDayYear, DayMonthYear, and TextualDate representations. Each exposes year, month, and day.
  • Currency is a small enum (EUR, USD, GBP).
  • Money composes currency and amount; Payment gives that value the amount role and its date the dueDate role.

Try adding another currency, adding a new Date shape, or extending Payment with an optional amount range.

Specs

spec.yml
$flags: 'FLEXIBLE_WHITESPACE'

Number:
  Decimal: '\d+\.\d+'
  Integer: '\d+'

Month:
  January: 'January'
  February: 'February'
  March: 'March'
  April: 'April'
  May: 'May'
  June: 'June'
  July: 'July'
  August: 'August'
  September: 'September'
  October: 'October'
  November: 'November'
  December: 'December'

Date:

  YearMonthDay:
    $fields:
      day: { $type: Number::Integer, $match: '0[1-9]|[12]\d|3[01]' }
      month: { $type: Number::Integer, $match: '0[1-9]|1[0-2]' }
      year: { $type: Number::Integer, $match: '\d{4}' }
    $patterns: '#{year}-#{month}-#{day}'

  MonthDayYear:
    $fields:
      day: { $type: Number::Integer, $match: '0[1-9]|[12]\d|3[01]' }
      month: { $type: Number::Integer, $match: '0[1-9]|1[0-2]' }
      year: { $type: Number::Integer, $match: '\d{4}' }
    $patterns: '#{month}/#{day}/#{year}'

  DayMonthYear:
    $fields:
      day: { $type: Number::Integer, $match: '0[1-9]|[12]\d|3[01]' }
      month: { $type: Number::Integer, $match: '0[1-9]|1[0-2]' }
      year: { $type: Number::Integer, $match: '\d{4}' }
    $patterns: '#{day}-#{month}-#{year}'

  TextualDate:
    $fields:
      year: { $type: Number::Integer, $match: '\d{4}' }
      month: Month
      day: { $type: Number::Integer, $match: '0[1-9]|[12]\d|3[01]' }
    $patterns: '#{month} #{day}, #{year}'

Currency:
  USD: '(USD|US\$|\$)'
  EUR: '(EUR|€)'
  GBP: '(GBP|£)'

Money:
  $flags: 'OPTIONAL_WHITESPACE'
  $fields:
    currency: Currency
    amount: Number
  $patterns:
    - '#{currency} #{amount}'
    - '#{amount} #{currency}'

Payment:
  $fields:
    amount: Money
    dueDate: Date
  $patterns: '#{amount} due on #{dueDate}'
Try it liveOpen Money and Dates in StudioTweak the spec, paste your own input, and see the parse tree update in real time.

Or browse other examples →