Skip to content

Commit

Permalink
Remaining tidal features (#19)
Browse files Browse the repository at this point in the history
* support repeat

* support "-" as rest

* parse "? " as "?0.5"

* separate expressions taking single value on the right, apply @ and ! at parse

* support polymeters without explicit count

* support range expressions with integers

* support slow expression

* support split expressions, aka "a b . c d" -> "[a b] [c d]"

* fix merging rests and holds

* refactor ing & cleanups

* update tidal differences explanation
  • Loading branch information
unlessgames authored Jun 13, 2024
1 parent 5db012c commit 6a44839
Show file tree
Hide file tree
Showing 3 changed files with 1,081 additions and 703 deletions.
53 changes: 29 additions & 24 deletions src/tidal/cycle.pest
Original file line number Diff line number Diff line change
Expand Up @@ -19,56 +19,61 @@ note = ${ (^"a"|^"b"|^"c"|^"d"|^"e"|^"f"|^"g") }
pitch = ${ note ~ mark? ~ octave? ~ !(ASCII_ALPHANUMERIC)}

/// type for empty steps
rest = @{ "~" ~ !(ASCII_ALPHANUMERIC) }
rest = @{ ("~" | "-") ~ !(ASCII_ALPHANUMERIC) }

/// type for held steps
hold = @{ "_" ~ !(ASCII_ALPHANUMERIC) }

/// arbitrary string identifier type
name = @{ (ASCII_ALPHANUMERIC | "_")+ }

repeat = { "!" }

/// possible literals for single steps
single = { hold | rest | number | pitch | name }

/// operators
op_fast = ${ "*" ~ parameter }
op_target = ${ ":" ~ parameter }
op_degrade = ${ "?" ~ parameter }
op_replicate = ${ "!" ~ parameter }
op_bjorklund = { "(" ~ (parameter ~ ",")+ ~ parameter ~ ")" }
// op_weight = ${ ("@") ~ parameter }
// op_slow = ${ "/" ~ parameter }
// op_range = { ".." ~ parameter } // ???
op = _{ op_fast | op_target | op_degrade | op_replicate | op_bjorklund }

/// groups
subdivision = { "[" ~ (stack | choices | section)? ~ "]" }
alternating = { "<" ~ (stack | section)? ~ ">" }
polymeter = { "{" ~ (stack | section)? ~ "}" ~ polymeter_tail }
polymeter_tail = { "%" ~ polymeter_count}
polymeter_count = { (ASCII_NONZERO_DIGIT ~ ASCII_DIGIT* ~ !(ASCII_ALPHANUMERIC | "."))}
subdivision = { "[" ~ (stack | split | choices | section)? ~ "]" }
alternating = { "<" ~ (stack | split | section)? ~ ">" }

polymeter_tail = { "%" ~ single }
polymeter = { "{" ~ (stack | split | section)? ~ "}" ~ polymeter_tail? }

group = _{ subdivision | alternating | polymeter }

// this should actually be { expr | group | single } at some point
/// parameter for expressions with operators
parameter = _{ single }

expr = { (single | group) ~ op+ }
// target = { (ASCII_ALPHANUMERIC | "_")+ }

/// operators
op_replicate = ${ "!" ~ single }
op_weight = ${ "@" ~ single? }
op_degrade = ${ "?" ~ single? }
op_target = ${ ":" ~ single }

op_fast = ${ "*" ~ parameter }
op_slow = ${ "/" ~ parameter }
op_bjorklund = { "(" ~ (parameter ~ ",")+ ~ parameter ~ ")" }
op = _{ op_target | op_degrade | op_replicate | op_weight | op_fast | op_slow | op_bjorklund }

expression = { (single | group) ~ op+ }
range = ${ integer ~ ".." ~ integer }

/// helper container that splits steps into sections
section = { (expr | single | group)+ }
section = { ( expression | range | single | repeat | group)+ }

/// a single choice inside a choice list
choice = { expr | single | group }
choice = { expression | range | single | group }
/// at least 2 choices, can only be inside subdivisions or the root
choices = { (choice) ~ ("|" ~ choice)+ }

/// parallel sections of events found inside groups
stack = { (section) ~ ("," ~ section)+ }
stack = { (split | section) ~ ("," ~ (split | section))+ }

// shorthand for subdivisions
// split = { (section) ~ ("." ~ section)+ }
// TODO shorthand for nested subdivisions
split = { (section) ~ ("." ~ section)+ }

/// the root of the cycle
mini = { SOI ~ ( stack | choices | section) ~ EOI }
mini = { SOI ~ ( stack | split | choices | section) ~ EOI }
Loading

0 comments on commit 6a44839

Please sign in to comment.