From 8bb460701f882133995a83256315d7db0df6bb73 Mon Sep 17 00:00:00 2001 From: Alex McLean Date: Sat, 31 Dec 2022 21:42:49 +0000 Subject: [PATCH] Tidy parser, implement polymeters (#336) * rename parser stuff to be more explicit and fit with tidal concepts. qualify all strudel function calls * Add {,}%n polymeter support, with a few tests --- packages/mini/krill-parser.js | 824 +++++++++++++++++-------------- packages/mini/krill.pegjs | 92 ++-- packages/mini/mini.mjs | 62 ++- packages/mini/test/mini.test.mjs | 10 + 4 files changed, 549 insertions(+), 439 deletions(-) diff --git a/packages/mini/krill-parser.js b/packages/mini/krill-parser.js index 2bc565f7..95752beb 100644 --- a/packages/mini/krill-parser.js +++ b/packages/mini/krill-parser.js @@ -185,30 +185,32 @@ function peg$parse(input, options) { var peg$c11 = ":"; var peg$c12 = "["; var peg$c13 = "]"; - var peg$c14 = "<"; - var peg$c15 = ">"; - var peg$c16 = "@"; - var peg$c17 = "!"; - var peg$c18 = "("; - var peg$c19 = ")"; - var peg$c20 = "/"; - var peg$c21 = "*"; - var peg$c22 = "%"; - var peg$c23 = "?"; - var peg$c24 = "struct"; - var peg$c25 = "target"; - var peg$c26 = "euclid"; - var peg$c27 = "slow"; - var peg$c28 = "rotL"; - var peg$c29 = "rotR"; - var peg$c30 = "fast"; - var peg$c31 = "scale"; - var peg$c32 = "//"; - var peg$c33 = "cat"; - var peg$c34 = "$"; - var peg$c35 = "setcps"; - var peg$c36 = "setbpm"; - var peg$c37 = "hush"; + var peg$c14 = "{"; + var peg$c15 = "}"; + var peg$c16 = "%"; + var peg$c17 = "<"; + var peg$c18 = ">"; + var peg$c19 = "@"; + var peg$c20 = "!"; + var peg$c21 = "("; + var peg$c22 = ")"; + var peg$c23 = "/"; + var peg$c24 = "*"; + var peg$c25 = "?"; + var peg$c26 = "struct"; + var peg$c27 = "target"; + var peg$c28 = "euclid"; + var peg$c29 = "slow"; + var peg$c30 = "rotL"; + var peg$c31 = "rotR"; + var peg$c32 = "fast"; + var peg$c33 = "scale"; + var peg$c34 = "//"; + var peg$c35 = "cat"; + var peg$c36 = "$"; + var peg$c37 = "setcps"; + var peg$c38 = "setbpm"; + var peg$c39 = "hush"; var peg$r0 = /^[1-9]/; var peg$r1 = /^[eE]/; @@ -238,66 +240,70 @@ function peg$parse(input, options) { var peg$e18 = peg$literalExpectation(":", false); var peg$e19 = peg$literalExpectation("[", false); var peg$e20 = peg$literalExpectation("]", false); - var peg$e21 = peg$literalExpectation("<", false); - var peg$e22 = peg$literalExpectation(">", false); - var peg$e23 = peg$literalExpectation("@", false); - var peg$e24 = peg$literalExpectation("!", false); - var peg$e25 = peg$literalExpectation("(", false); - var peg$e26 = peg$literalExpectation(")", false); - var peg$e27 = peg$literalExpectation("/", false); - var peg$e28 = peg$literalExpectation("*", false); - var peg$e29 = peg$literalExpectation("%", false); - var peg$e30 = peg$literalExpectation("?", false); - var peg$e31 = peg$literalExpectation("struct", false); - var peg$e32 = peg$literalExpectation("target", false); - var peg$e33 = peg$literalExpectation("euclid", false); - var peg$e34 = peg$literalExpectation("slow", false); - var peg$e35 = peg$literalExpectation("rotL", false); - var peg$e36 = peg$literalExpectation("rotR", false); - var peg$e37 = peg$literalExpectation("fast", false); - var peg$e38 = peg$literalExpectation("scale", false); - var peg$e39 = peg$literalExpectation("//", false); - var peg$e40 = peg$classExpectation(["\n"], true, false); - var peg$e41 = peg$literalExpectation("cat", false); - var peg$e42 = peg$literalExpectation("$", false); - var peg$e43 = peg$literalExpectation("setcps", false); - var peg$e44 = peg$literalExpectation("setbpm", false); - var peg$e45 = peg$literalExpectation("hush", false); + var peg$e21 = peg$literalExpectation("{", false); + var peg$e22 = peg$literalExpectation("}", false); + var peg$e23 = peg$literalExpectation("%", false); + var peg$e24 = peg$literalExpectation("<", false); + var peg$e25 = peg$literalExpectation(">", false); + var peg$e26 = peg$literalExpectation("@", false); + var peg$e27 = peg$literalExpectation("!", false); + var peg$e28 = peg$literalExpectation("(", false); + var peg$e29 = peg$literalExpectation(")", false); + var peg$e30 = peg$literalExpectation("/", false); + var peg$e31 = peg$literalExpectation("*", false); + var peg$e32 = peg$literalExpectation("?", false); + var peg$e33 = peg$literalExpectation("struct", false); + var peg$e34 = peg$literalExpectation("target", false); + var peg$e35 = peg$literalExpectation("euclid", false); + var peg$e36 = peg$literalExpectation("slow", false); + var peg$e37 = peg$literalExpectation("rotL", false); + var peg$e38 = peg$literalExpectation("rotR", false); + var peg$e39 = peg$literalExpectation("fast", false); + var peg$e40 = peg$literalExpectation("scale", false); + var peg$e41 = peg$literalExpectation("//", false); + var peg$e42 = peg$classExpectation(["\n"], true, false); + var peg$e43 = peg$literalExpectation("cat", false); + var peg$e44 = peg$literalExpectation("$", false); + var peg$e45 = peg$literalExpectation("setcps", false); + var peg$e46 = peg$literalExpectation("setbpm", false); + var peg$e47 = peg$literalExpectation("hush", false); var peg$f0 = function() { return parseFloat(text()); }; var peg$f1 = function(chars) { return chars.join("") }; - var peg$f2 = function(s) { return s}; - var peg$f3 = function(sc) { sc.arguments_.alignment = "t"; return sc;}; - var peg$f4 = function(a) { return { weight: a} }; - var peg$f5 = function(a) { return { replicate: a } }; - var peg$f6 = function(p, s, r) { return { operator : { type_: "bjorklund", arguments_ :{ pulse: p, step:s, rotation:r || 0 } } } }; - var peg$f7 = function(a) { return { operator : { type_: "stretch", arguments_ :{ amount:a, type: 'slow' } } } }; - var peg$f8 = function(a) { return { operator : { type_: "stretch", arguments_ :{ amount:a, type: 'fast' } } } }; - var peg$f9 = function(a) { return { operator : { type_: "fixed-step", arguments_ :{ amount:a } } } }; - var peg$f10 = function(a) { return { operator : { type_: "degradeBy", arguments_ :{ amount:(a? a : 0.5) } } } }; - var peg$f11 = function(s, o) { return new ElementStub(s, o);}; - var peg$f12 = function(s) { return new PatternStub(s,"h"); }; - var peg$f13 = function(tail) { return { alignment: 'v', list: tail }; }; - var peg$f14 = function(tail) { return { alignment: 'r', list: tail }; }; - var peg$f15 = function(head, tail) { if (tail && tail.list.length > 0) { return new PatternStub([head, ...tail.list], tail.alignment); } else { return head; } }; - var peg$f16 = function(sc) { return sc; }; - var peg$f17 = function(s) { return { name: "struct", args: { sequence:s }}}; - var peg$f18 = function(s) { return { name: "target", args : { name:s}}}; - var peg$f19 = function(p, s, r) { return { name: "bjorklund", args :{ pulse: parseInt(p), step:parseInt(s) }}}; - var peg$f20 = function(a) { return { name: "stretch", args :{ amount: a}}}; - var peg$f21 = function(a) { return { name: "shift", args :{ amount: "-"+a}}}; - var peg$f22 = function(a) { return { name: "shift", args :{ amount: a}}}; - var peg$f23 = function(a) { return { name: "stretch", args :{ amount: "1/"+a}}}; - var peg$f24 = function(s) { return { name: "scale", args :{ scale: s.join("")}}}; - var peg$f25 = function(s, v) { return v}; - var peg$f26 = function(s, ss) { ss.unshift(s); return new PatternStub(ss,"t"); }; - var peg$f27 = function(sg) {return sg}; - var peg$f28 = function(o, soc) { return new OperatorStub(o.name,o.args,soc)}; - var peg$f29 = function(sc) { return sc }; - var peg$f30 = function(c) { return c }; - var peg$f31 = function(v) { return new CommandStub("setcps", { value: v})}; - var peg$f32 = function(v) { return new CommandStub("setcps", { value: (v/120/2)})}; - var peg$f33 = function() { return new CommandStub("hush")}; + var peg$f2 = function(s) { return s }; + var peg$f3 = function(s, stepsPerCycle) { s.arguments_.stepsPerCycle = stepsPerCycle ; return s; }; + var peg$f4 = function(a) { return a }; + var peg$f5 = function(s) { s.arguments_.alignment = 'slowcat'; return s; }; + var peg$f6 = function(a) { return { weight: a} }; + var peg$f7 = function(a) { return { replicate: a } }; + var peg$f8 = function(p, s, r) { return { operator : { type_: "bjorklund", arguments_ :{ pulse: p, step:s, rotation:r || 0 } } } }; + var peg$f9 = function(a) { return { operator : { type_: "stretch", arguments_ :{ amount:a, type: 'slow' } } } }; + var peg$f10 = function(a) { return { operator : { type_: "stretch", arguments_ :{ amount:a, type: 'fast' } } } }; + var peg$f11 = function(a) { return { operator : { type_: "degradeBy", arguments_ :{ amount:(a? a : 0.5) } } } }; + var peg$f12 = function(s, o) { return new ElementStub(s, o);}; + var peg$f13 = function(s) { return new PatternStub(s, 'fastcat'); }; + var peg$f14 = function(tail) { return { alignment: 'stack', list: tail }; }; + var peg$f15 = function(tail) { return { alignment: 'rand', list: tail }; }; + var peg$f16 = function(head, tail) { if (tail && tail.list.length > 0) { return new PatternStub([head, ...tail.list], tail.alignment); } else { return head; } }; + var peg$f17 = function(head, tail) { return new PatternStub(tail ? [head, ...tail.list] : [head], 'polymeter'); }; + var peg$f18 = function(sc) { return sc; }; + var peg$f19 = function(s) { return { name: "struct", args: { mini:s }}}; + var peg$f20 = function(s) { return { name: "target", args : { name:s}}}; + var peg$f21 = function(p, s, r) { return { name: "bjorklund", args :{ pulse: parseInt(p), step:parseInt(s) }}}; + var peg$f22 = function(a) { return { name: "stretch", args :{ amount: a}}}; + var peg$f23 = function(a) { return { name: "shift", args :{ amount: "-"+a}}}; + var peg$f24 = function(a) { return { name: "shift", args :{ amount: a}}}; + var peg$f25 = function(a) { return { name: "stretch", args :{ amount: "1/"+a}}}; + var peg$f26 = function(s) { return { name: "scale", args :{ scale: s.join("")}}}; + var peg$f27 = function(s, v) { return v}; + var peg$f28 = function(s, ss) { ss.unshift(s); return new PatternStub(ss, 'slowcat'); }; + var peg$f29 = function(sg) {return sg}; + var peg$f30 = function(o, soc) { return new OperatorStub(o.name,o.args,soc)}; + var peg$f31 = function(sc) { return sc }; + var peg$f32 = function(c) { return c }; + var peg$f33 = function(v) { return new CommandStub("setcps", { value: v})}; + var peg$f34 = function(v) { return new CommandStub("setcps", { value: (v/120/2)})}; + var peg$f35 = function() { return new CommandStub("hush")}; var peg$currPos = 0; var peg$savedPos = 0; var peg$posDetailsCache = [{ line: 1, column: 1 }]; @@ -926,12 +932,12 @@ function peg$parse(input, options) { return s0; } - function peg$parsetimeline() { - var s0, s1, s2, s3, s4, s5, s6, s7; + function peg$parsepolymeter() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8; s0 = peg$currPos; s1 = peg$parsews(); - if (input.charCodeAt(peg$currPos) === 60) { + if (input.charCodeAt(peg$currPos) === 123) { s2 = peg$c14; peg$currPos++; } else { @@ -940,10 +946,10 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { s3 = peg$parsews(); - s4 = peg$parsesingle_cycle(); + s4 = peg$parsepolymeter_stack(); if (s4 !== peg$FAILED) { s5 = peg$parsews(); - if (input.charCodeAt(peg$currPos) === 62) { + if (input.charCodeAt(peg$currPos) === 125) { s6 = peg$c15; peg$currPos++; } else { @@ -951,9 +957,13 @@ function peg$parse(input, options) { if (peg$silentFails === 0) { peg$fail(peg$e22); } } if (s6 !== peg$FAILED) { - s7 = peg$parsews(); + s7 = peg$parsepolymeter_steps(); + if (s7 === peg$FAILED) { + s7 = null; + } + s8 = peg$parsews(); peg$savedPos = s0; - s0 = peg$f3(s4); + s0 = peg$f3(s4, s7); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -970,51 +980,11 @@ function peg$parse(input, options) { return s0; } - function peg$parseslice() { - var s0; - - s0 = peg$parsestep(); - if (s0 === peg$FAILED) { - s0 = peg$parsesub_cycle(); - if (s0 === peg$FAILED) { - s0 = peg$parsetimeline(); - } - } - - return s0; - } - - function peg$parseslice_modifier() { - var s0; - - s0 = peg$parseslice_weight(); - if (s0 === peg$FAILED) { - s0 = peg$parseslice_bjorklund(); - if (s0 === peg$FAILED) { - s0 = peg$parseslice_slow(); - if (s0 === peg$FAILED) { - s0 = peg$parseslice_fast(); - if (s0 === peg$FAILED) { - s0 = peg$parseslice_fixed_step(); - if (s0 === peg$FAILED) { - s0 = peg$parseslice_replicate(); - if (s0 === peg$FAILED) { - s0 = peg$parseslice_degrade(); - } - } - } - } - } - } - - return s0; - } - - function peg$parseslice_weight() { + function peg$parsepolymeter_steps() { var s0, s1, s2; s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 64) { + if (input.charCodeAt(peg$currPos) === 37) { s1 = peg$c16; peg$currPos++; } else { @@ -1038,22 +1008,134 @@ function peg$parse(input, options) { return s0; } - function peg$parseslice_replicate() { + function peg$parseslow_sequence() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parsews(); + if (input.charCodeAt(peg$currPos) === 60) { + s2 = peg$c17; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e24); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsews(); + s4 = peg$parsesequence(); + if (s4 !== peg$FAILED) { + s5 = peg$parsews(); + if (input.charCodeAt(peg$currPos) === 62) { + s6 = peg$c18; + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e25); } + } + if (s6 !== peg$FAILED) { + s7 = peg$parsews(); + peg$savedPos = s0; + s0 = peg$f5(s4); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseslice() { + var s0; + + s0 = peg$parsestep(); + if (s0 === peg$FAILED) { + s0 = peg$parsesub_cycle(); + if (s0 === peg$FAILED) { + s0 = peg$parsepolymeter(); + if (s0 === peg$FAILED) { + s0 = peg$parseslow_sequence(); + } + } + } + + return s0; + } + + function peg$parseslice_modifier() { + var s0; + + s0 = peg$parseslice_weight(); + if (s0 === peg$FAILED) { + s0 = peg$parseslice_bjorklund(); + if (s0 === peg$FAILED) { + s0 = peg$parseslice_slow(); + if (s0 === peg$FAILED) { + s0 = peg$parseslice_fast(); + if (s0 === peg$FAILED) { + s0 = peg$parseslice_replicate(); + if (s0 === peg$FAILED) { + s0 = peg$parseslice_degrade(); + } + } + } + } + } + + return s0; + } + + function peg$parseslice_weight() { var s0, s1, s2; s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 33) { - s1 = peg$c17; + if (input.charCodeAt(peg$currPos) === 64) { + s1 = peg$c19; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e24); } + if (peg$silentFails === 0) { peg$fail(peg$e26); } } if (s1 !== peg$FAILED) { s2 = peg$parsenumber(); if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f5(s2); + s0 = peg$f6(s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseslice_replicate() { + var s0, s1, s2; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 33) { + s1 = peg$c20; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e27); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsenumber(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f7(s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1071,11 +1153,11 @@ function peg$parse(input, options) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 40) { - s1 = peg$c18; + s1 = peg$c21; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e25); } + if (peg$silentFails === 0) { peg$fail(peg$e28); } } if (s1 !== peg$FAILED) { s2 = peg$parsews(); @@ -1099,15 +1181,15 @@ function peg$parse(input, options) { } s12 = peg$parsews(); if (input.charCodeAt(peg$currPos) === 41) { - s13 = peg$c19; + s13 = peg$c22; peg$currPos++; } else { s13 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e26); } + if (peg$silentFails === 0) { peg$fail(peg$e29); } } if (s13 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f6(s3, s7, s11); + s0 = peg$f8(s3, s7, s11); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1137,67 +1219,11 @@ function peg$parse(input, options) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 47) { - s1 = peg$c20; + s1 = peg$c23; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e27); } - } - if (s1 !== peg$FAILED) { - s2 = peg$parsenumber(); - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f7(s2); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - return s0; - } - - function peg$parseslice_fast() { - var s0, s1, s2; - - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 42) { - s1 = peg$c21; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } - } - if (s1 !== peg$FAILED) { - s2 = peg$parsenumber(); - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f8(s2); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - return s0; - } - - function peg$parseslice_fixed_step() { - var s0, s1, s2; - - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 37) { - s1 = peg$c22; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e29); } + if (peg$silentFails === 0) { peg$fail(peg$e30); } } if (s1 !== peg$FAILED) { s2 = peg$parsenumber(); @@ -1216,16 +1242,44 @@ function peg$parse(input, options) { return s0; } + function peg$parseslice_fast() { + var s0, s1, s2; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 42) { + s1 = peg$c24; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e31); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsenumber(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f10(s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + function peg$parseslice_degrade() { var s0, s1, s2; s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 63) { - s1 = peg$c23; + s1 = peg$c25; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } + if (peg$silentFails === 0) { peg$fail(peg$e32); } } if (s1 !== peg$FAILED) { s2 = peg$parsenumber(); @@ -1233,7 +1287,7 @@ function peg$parse(input, options) { s2 = null; } peg$savedPos = s0; - s0 = peg$f10(s2); + s0 = peg$f11(s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1253,7 +1307,7 @@ function peg$parse(input, options) { s2 = null; } peg$savedPos = s0; - s0 = peg$f11(s1, s2); + s0 = peg$f12(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1262,7 +1316,7 @@ function peg$parse(input, options) { return s0; } - function peg$parsesingle_cycle() { + function peg$parsesequence() { var s0, s1, s2; s0 = peg$currPos; @@ -1278,7 +1332,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f12(s1); + s1 = peg$f13(s1); } s0 = s1; @@ -1293,7 +1347,7 @@ function peg$parse(input, options) { s2 = peg$currPos; s3 = peg$parsecomma(); if (s3 !== peg$FAILED) { - s4 = peg$parsesingle_cycle(); + s4 = peg$parsesequence(); if (s4 !== peg$FAILED) { s2 = s4; } else { @@ -1310,56 +1364,7 @@ function peg$parse(input, options) { s2 = peg$currPos; s3 = peg$parsecomma(); if (s3 !== peg$FAILED) { - s4 = peg$parsesingle_cycle(); - if (s4 !== peg$FAILED) { - s2 = s4; - } else { - peg$currPos = s2; - s2 = peg$FAILED; - } - } else { - peg$currPos = s2; - s2 = peg$FAILED; - } - } - } else { - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f13(s1); - } - s0 = s1; - - return s0; - } - - function peg$parsechoose_tail() { - var s0, s1, s2, s3, s4; - - s0 = peg$currPos; - s1 = []; - s2 = peg$currPos; - s3 = peg$parsepipe(); - if (s3 !== peg$FAILED) { - s4 = peg$parsesingle_cycle(); - if (s4 !== peg$FAILED) { - s2 = s4; - } else { - peg$currPos = s2; - s2 = peg$FAILED; - } - } else { - peg$currPos = s2; - s2 = peg$FAILED; - } - if (s2 !== peg$FAILED) { - while (s2 !== peg$FAILED) { - s1.push(s2); - s2 = peg$currPos; - s3 = peg$parsepipe(); - if (s3 !== peg$FAILED) { - s4 = peg$parsesingle_cycle(); + s4 = peg$parsesequence(); if (s4 !== peg$FAILED) { s2 = s4; } else { @@ -1383,11 +1388,60 @@ function peg$parse(input, options) { return s0; } + function peg$parsechoose_tail() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = []; + s2 = peg$currPos; + s3 = peg$parsepipe(); + if (s3 !== peg$FAILED) { + s4 = peg$parsesequence(); + if (s4 !== peg$FAILED) { + s2 = s4; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$currPos; + s3 = peg$parsepipe(); + if (s3 !== peg$FAILED) { + s4 = peg$parsesequence(); + if (s4 !== peg$FAILED) { + s2 = s4; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f15(s1); + } + s0 = s1; + + return s0; + } + function peg$parsestack_or_choose() { var s0, s1, s2; s0 = peg$currPos; - s1 = peg$parsesingle_cycle(); + s1 = peg$parsesequence(); if (s1 !== peg$FAILED) { s2 = peg$parsestack_tail(); if (s2 === peg$FAILED) { @@ -1397,7 +1451,7 @@ function peg$parse(input, options) { s2 = null; } peg$savedPos = s0; - s0 = peg$f15(s1, s2); + s0 = peg$f16(s1, s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1406,7 +1460,27 @@ function peg$parse(input, options) { return s0; } - function peg$parsesequence() { + function peg$parsepolymeter_stack() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$parsesequence(); + if (s1 !== peg$FAILED) { + s2 = peg$parsestack_tail(); + if (s2 === peg$FAILED) { + s2 = null; + } + peg$savedPos = s0; + s0 = peg$f17(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsemini() { var s0, s1, s2, s3, s4; s0 = peg$currPos; @@ -1418,7 +1492,7 @@ function peg$parse(input, options) { s4 = peg$parsequote(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f16(s3); + s0 = peg$f18(s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1468,19 +1542,19 @@ function peg$parse(input, options) { var s0, s1, s2, s3; s0 = peg$currPos; - if (input.substr(peg$currPos, 6) === peg$c24) { - s1 = peg$c24; + if (input.substr(peg$currPos, 6) === peg$c26) { + s1 = peg$c26; peg$currPos += 6; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e31); } + if (peg$silentFails === 0) { peg$fail(peg$e33); } } if (s1 !== peg$FAILED) { s2 = peg$parsews(); - s3 = peg$parsesequence_or_operator(); + s3 = peg$parsemini_or_operator(); if (s3 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f17(s3); + s0 = peg$f19(s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1497,12 +1571,12 @@ function peg$parse(input, options) { var s0, s1, s2, s3, s4, s5; s0 = peg$currPos; - if (input.substr(peg$currPos, 6) === peg$c25) { - s1 = peg$c25; + if (input.substr(peg$currPos, 6) === peg$c27) { + s1 = peg$c27; peg$currPos += 6; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } + if (peg$silentFails === 0) { peg$fail(peg$e34); } } if (s1 !== peg$FAILED) { s2 = peg$parsews(); @@ -1513,7 +1587,7 @@ function peg$parse(input, options) { s5 = peg$parsequote(); if (s5 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f18(s4); + s0 = peg$f20(s4); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1538,12 +1612,12 @@ function peg$parse(input, options) { var s0, s1, s2, s3, s4, s5, s6, s7; s0 = peg$currPos; - if (input.substr(peg$currPos, 6) === peg$c26) { - s1 = peg$c26; + if (input.substr(peg$currPos, 6) === peg$c28) { + s1 = peg$c28; peg$currPos += 6; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e33); } + if (peg$silentFails === 0) { peg$fail(peg$e35); } } if (s1 !== peg$FAILED) { s2 = peg$parsews(); @@ -1558,7 +1632,7 @@ function peg$parse(input, options) { s7 = null; } peg$savedPos = s0; - s0 = peg$f19(s3, s5, s7); + s0 = peg$f21(s3, s5, s7); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1578,64 +1652,6 @@ function peg$parse(input, options) { function peg$parseslow() { var s0, s1, s2, s3; - s0 = peg$currPos; - if (input.substr(peg$currPos, 4) === peg$c27) { - s1 = peg$c27; - peg$currPos += 4; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e34); } - } - if (s1 !== peg$FAILED) { - s2 = peg$parsews(); - s3 = peg$parsenumber(); - if (s3 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f20(s3); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - return s0; - } - - function peg$parserotL() { - var s0, s1, s2, s3; - - s0 = peg$currPos; - if (input.substr(peg$currPos, 4) === peg$c28) { - s1 = peg$c28; - peg$currPos += 4; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e35); } - } - if (s1 !== peg$FAILED) { - s2 = peg$parsews(); - s3 = peg$parsenumber(); - if (s3 !== peg$FAILED) { - peg$savedPos = s0; - s0 = peg$f21(s3); - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - return s0; - } - - function peg$parserotR() { - var s0, s1, s2, s3; - s0 = peg$currPos; if (input.substr(peg$currPos, 4) === peg$c29) { s1 = peg$c29; @@ -1662,7 +1678,7 @@ function peg$parse(input, options) { return s0; } - function peg$parsefast() { + function peg$parserotL() { var s0, s1, s2, s3; s0 = peg$currPos; @@ -1691,16 +1707,74 @@ function peg$parse(input, options) { return s0; } + function peg$parserotR() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4) === peg$c31) { + s1 = peg$c31; + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e38); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsews(); + s3 = peg$parsenumber(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f24(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsefast() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4) === peg$c32) { + s1 = peg$c32; + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e39); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsews(); + s3 = peg$parsenumber(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f25(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + function peg$parsescale() { var s0, s1, s2, s3, s4, s5; s0 = peg$currPos; - if (input.substr(peg$currPos, 5) === peg$c31) { - s1 = peg$c31; + if (input.substr(peg$currPos, 5) === peg$c33) { + s1 = peg$c33; peg$currPos += 5; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e38); } + if (peg$silentFails === 0) { peg$fail(peg$e40); } } if (s1 !== peg$FAILED) { s2 = peg$parsews(); @@ -1720,7 +1794,7 @@ function peg$parse(input, options) { s5 = peg$parsequote(); if (s5 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f24(s4); + s0 = peg$f26(s4); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1745,12 +1819,12 @@ function peg$parse(input, options) { var s0, s1, s2, s3; s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c32) { - s1 = peg$c32; + if (input.substr(peg$currPos, 2) === peg$c34) { + s1 = peg$c34; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e39); } + if (peg$silentFails === 0) { peg$fail(peg$e41); } } if (s1 !== peg$FAILED) { s2 = []; @@ -1759,7 +1833,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e40); } + if (peg$silentFails === 0) { peg$fail(peg$e42); } } while (s3 !== peg$FAILED) { s2.push(s3); @@ -1768,7 +1842,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e40); } + if (peg$silentFails === 0) { peg$fail(peg$e42); } } } s1 = [s1, s2]; @@ -1785,12 +1859,12 @@ function peg$parse(input, options) { var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; s0 = peg$currPos; - if (input.substr(peg$currPos, 3) === peg$c33) { - s1 = peg$c33; + if (input.substr(peg$currPos, 3) === peg$c35) { + s1 = peg$c35; peg$currPos += 3; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e41); } + if (peg$silentFails === 0) { peg$fail(peg$e43); } } if (s1 !== peg$FAILED) { s2 = peg$parsews(); @@ -1803,16 +1877,16 @@ function peg$parse(input, options) { } if (s3 !== peg$FAILED) { s4 = peg$parsews(); - s5 = peg$parsesequence_or_operator(); + s5 = peg$parsemini_or_operator(); if (s5 !== peg$FAILED) { s6 = []; s7 = peg$currPos; s8 = peg$parsecomma(); if (s8 !== peg$FAILED) { - s9 = peg$parsesequence_or_operator(); + s9 = peg$parsemini_or_operator(); if (s9 !== peg$FAILED) { peg$savedPos = s7; - s7 = peg$f25(s5, s9); + s7 = peg$f27(s5, s9); } else { peg$currPos = s7; s7 = peg$FAILED; @@ -1826,10 +1900,10 @@ function peg$parse(input, options) { s7 = peg$currPos; s8 = peg$parsecomma(); if (s8 !== peg$FAILED) { - s9 = peg$parsesequence_or_operator(); + s9 = peg$parsemini_or_operator(); if (s9 !== peg$FAILED) { peg$savedPos = s7; - s7 = peg$f25(s5, s9); + s7 = peg$f27(s5, s9); } else { peg$currPos = s7; s7 = peg$FAILED; @@ -1849,7 +1923,7 @@ function peg$parse(input, options) { } if (s8 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f26(s5, s6); + s0 = peg$f28(s5, s6); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1870,22 +1944,22 @@ function peg$parse(input, options) { return s0; } - function peg$parsesequence_or_group() { + function peg$parsemini_or_group() { var s0; s0 = peg$parsecat(); if (s0 === peg$FAILED) { - s0 = peg$parsesequence(); + s0 = peg$parsemini(); } return s0; } - function peg$parsesequence_or_operator() { + function peg$parsemini_or_operator() { var s0, s1, s2, s3, s4, s5; s0 = peg$currPos; - s1 = peg$parsesequence_or_group(); + s1 = peg$parsemini_or_group(); if (s1 !== peg$FAILED) { s2 = peg$parsews(); s3 = []; @@ -1895,7 +1969,7 @@ function peg$parse(input, options) { s4 = peg$parsecomment(); } peg$savedPos = s0; - s0 = peg$f27(s1); + s0 = peg$f29(s1); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1906,18 +1980,18 @@ function peg$parse(input, options) { if (s1 !== peg$FAILED) { s2 = peg$parsews(); if (input.charCodeAt(peg$currPos) === 36) { - s3 = peg$c34; + s3 = peg$c36; peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e42); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } if (s3 !== peg$FAILED) { s4 = peg$parsews(); - s5 = peg$parsesequence_or_operator(); + s5 = peg$parsemini_or_operator(); if (s5 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f28(s1, s5); + s0 = peg$f30(s1, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1939,10 +2013,10 @@ function peg$parse(input, options) { var s0, s1; s0 = peg$currPos; - s1 = peg$parsesequence_or_operator(); + s1 = peg$parsemini_or_operator(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f29(s1); + s1 = peg$f31(s1); } s0 = s1; if (s0 === peg$FAILED) { @@ -1952,7 +2026,7 @@ function peg$parse(input, options) { return s0; } - function peg$parsesequence_definition() { + function peg$parsemini_definition() { var s0; s0 = peg$parsesequ_or_operator_or_comment(); @@ -1975,7 +2049,7 @@ function peg$parse(input, options) { if (s2 !== peg$FAILED) { s3 = peg$parsews(); peg$savedPos = s0; - s0 = peg$f30(s2); + s0 = peg$f32(s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1988,19 +2062,19 @@ function peg$parse(input, options) { var s0, s1, s2, s3; s0 = peg$currPos; - if (input.substr(peg$currPos, 6) === peg$c35) { - s1 = peg$c35; + if (input.substr(peg$currPos, 6) === peg$c37) { + s1 = peg$c37; peg$currPos += 6; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e43); } + if (peg$silentFails === 0) { peg$fail(peg$e45); } } if (s1 !== peg$FAILED) { s2 = peg$parsews(); s3 = peg$parsenumber(); if (s3 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f31(s3); + s0 = peg$f33(s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -2017,19 +2091,19 @@ function peg$parse(input, options) { var s0, s1, s2, s3; s0 = peg$currPos; - if (input.substr(peg$currPos, 6) === peg$c36) { - s1 = peg$c36; + if (input.substr(peg$currPos, 6) === peg$c38) { + s1 = peg$c38; peg$currPos += 6; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e44); } + if (peg$silentFails === 0) { peg$fail(peg$e46); } } if (s1 !== peg$FAILED) { s2 = peg$parsews(); s3 = peg$parsenumber(); if (s3 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f32(s3); + s0 = peg$f34(s3); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -2046,16 +2120,16 @@ function peg$parse(input, options) { var s0, s1; s0 = peg$currPos; - if (input.substr(peg$currPos, 4) === peg$c37) { - s1 = peg$c37; + if (input.substr(peg$currPos, 4) === peg$c39) { + s1 = peg$c39; peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e45); } + if (peg$silentFails === 0) { peg$fail(peg$e47); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f33(); + s1 = peg$f35(); } s0 = s1; @@ -2065,7 +2139,7 @@ function peg$parse(input, options) { function peg$parsestatement() { var s0; - s0 = peg$parsesequence_definition(); + s0 = peg$parsemini_definition(); if (s0 === peg$FAILED) { s0 = peg$parsecommand(); } diff --git a/packages/mini/krill.pegjs b/packages/mini/krill.pegjs index 87e9df3f..bee60e0c 100644 --- a/packages/mini/krill.pegjs +++ b/packages/mini/krill.pegjs @@ -5,10 +5,10 @@ This program is free software: you can redistribute it and/or modify it under th */ // Some terminology: -// a sequence = a serie of elements placed between quotes -// a stack = a serie of vertically aligned slices sharing the same overall length -// a slice = a serie of horizontally aligned elements -// a choose = a serie of elements, one of which is chosen at random +// mini(notation) = a series of elements placed between quotes +// a stack = a series of vertically aligned slices sharing the same overall length +// a sequence = a series of horizontally aligned elements +// a choose = a series of elements, one of which is chosen at random { @@ -93,18 +93,26 @@ step_char = [0-9a-zA-Z~] / "-" / "#" / "." / "^" / "_" / ":" step = ws chars:step_char+ ws { return chars.join("") } // define a sub cycle e.g. [1 2, 3 [4]] -sub_cycle = ws "[" ws s:stack_or_choose ws "]" ws { return s} +sub_cycle = ws "[" ws s:stack_or_choose ws "]" ws { return s } -// define a timeline e.g <1 3 [3 5]>. We simply defer to a stack and change the alignement -timeline = ws "<" ws sc:single_cycle ws ">" ws - { sc.arguments_.alignment = "t"; return sc;} +// define a polymeter e.g. {1 2, 3 4 5} +polymeter = ws "{" ws s:polymeter_stack ws "}" stepsPerCycle:polymeter_steps? ws + { s.arguments_.stepsPerCycle = stepsPerCycle ; return s; } + +polymeter_steps = "%"a:number + { return a } + +// define a step-per-cycle timeline e.g <1 3 [3 5]>. We simply defer to a sequence and +// change the alignment to slowcat +slow_sequence = ws "<" ws s:sequence ws ">" ws + { s.arguments_.alignment = 'slowcat'; return s; } // a slice is either a single step or a sub cycle -slice = step / sub_cycle / timeline +slice = step / sub_cycle / polymeter / slow_sequence // slice modifier affects the timing/size of a slice (e.g. [a b c]@3) // at this point, we assume we can represent them as regular sequence operators -slice_modifier = slice_weight / slice_bjorklund / slice_slow / slice_fast / slice_fixed_step / slice_replicate / slice_degrade +slice_modifier = slice_weight / slice_bjorklund / slice_slow / slice_fast / slice_replicate / slice_degrade slice_weight = "@" a:number { return { weight: a} } @@ -121,9 +129,6 @@ slice_slow = "/"a:number slice_fast = "*"a:number { return { operator : { type_: "stretch", arguments_ :{ amount:a, type: 'fast' } } } } -slice_fixed_step = "%"a:number - { return { operator : { type_: "fixed-step", arguments_ :{ amount:a } } } } - slice_degrade = "?"a:number? { return { operator : { type_: "degradeBy", arguments_ :{ amount:(a? a : 0.5) } } } } @@ -131,35 +136,42 @@ slice_degrade = "?"a:number? slice_with_modifier = s:slice o:slice_modifier? { return new ElementStub(s, o);} -// a single cycle is a combination of one or more successive slices (as an array). If we -// have only one element, we skip the array and return the element itself -single_cycle = s:(slice_with_modifier)+ - { return new PatternStub(s,"h"); } +// a sequence is a combination of one or more successive slices (as an array) +sequence = s:(slice_with_modifier)+ + { return new PatternStub(s, 'fastcat'); } -// a stack is a serie of vertically aligned single cycles, separated by a comma -stack_tail = tail:(comma @single_cycle)+ - { return { alignment: 'v', list: tail }; } +// a stack is a series of vertically aligned sequence, separated by a comma +stack_tail = tail:(comma @sequence)+ + { return { alignment: 'stack', list: tail }; } -// a choose is a serie of pipe-separated single cycles, one of which is chosen -// at random each time through the pattern -choose_tail = tail:(pipe @single_cycle)+ - { return { alignment: 'r', list: tail }; } +// a choose is a series of pipe-separated sequence, one of which is +// chosen at random, each cycle +choose_tail = tail:(pipe @sequence)+ + { return { alignment: 'rand', list: tail }; } // if the stack contains only one element, we don't create a stack but return the // underlying element -stack_or_choose = head:single_cycle tail:(stack_tail / choose_tail)? +stack_or_choose = head:sequence tail:(stack_tail / choose_tail)? { if (tail && tail.list.length > 0) { return new PatternStub([head, ...tail.list], tail.alignment); } else { return head; } } -// a sequence is a quoted stack -sequence = ws quote sc:stack_or_choose quote +polymeter_stack = head:sequence tail:stack_tail? + { return new PatternStub(tail ? [head, ...tail.list] : [head], 'polymeter'); } + + +// Mini-notation innards ends +// ---------->8---------->8---------->8---------->8---------->8---------- +// Experimental haskellish parser begins + +// mini-notation = a quoted stack +mini = ws quote sc:stack_or_choose quote { return sc; } // ------------------ operators --------------------------- operator = scale / slow / fast / target / bjorklund / struct / rotR / rotL -struct = "struct" ws s:sequence_or_operator - { return { name: "struct", args: { sequence:s }}} +struct = "struct" ws s:mini_or_operator + { return { name: "struct", args: { mini:s }}} target = "target" ws quote s:step quote { return { name: "target", args : { name:s}}} @@ -189,27 +201,27 @@ comment = '//' p:([^\n]*) group_operator = cat // cat is another form of timeline -cat = "cat" ws "[" ws s:sequence_or_operator ss:(comma v:sequence_or_operator { return v})* ws "]" - { ss.unshift(s); return new PatternStub(ss,"t"); } +cat = "cat" ws "[" ws s:mini_or_operator ss:(comma v:mini_or_operator { return v})* ws "]" + { ss.unshift(s); return new PatternStub(ss, 'slowcat'); } -// ------------------ high level sequence --------------------------- +// ------------------ high level mini --------------------------- -sequence_or_group = +mini_or_group = group_operator / - sequence + mini -sequence_or_operator = - sg:sequence_or_group ws (comment)* +mini_or_operator = + sg:mini_or_group ws (comment)* {return sg} - / o:operator ws "$" ws soc:sequence_or_operator + / o:operator ws "$" ws soc:mini_or_operator { return new OperatorStub(o.name,o.args,soc)} sequ_or_operator_or_comment = - sc: sequence_or_operator + sc: mini_or_operator { return sc } / comment -sequence_definition = s:sequ_or_operator_or_comment +mini_definition = s:sequ_or_operator_or_comment // ---------------------- statements ---------------------------- @@ -227,4 +239,4 @@ hush = "hush" // ---------------------- statements ---------------------------- -statement = sequence_definition / command +statement = mini_definition / command diff --git a/packages/mini/mini.mjs b/packages/mini/mini.mjs index 745f0f85..c0ad106f 100644 --- a/packages/mini/mini.mjs +++ b/packages/mini/mini.mjs @@ -7,8 +7,6 @@ This program is free software: you can redistribute it and/or modify it under th import * as krill from './krill-parser.js'; import * as strudel from '@strudel.cycles/core'; -const { pure, Fraction, stack, slowcat, sequence, timeCat, silence, reify } = strudel; - /* var _seedState = 0; const randOffset = 0.0002; @@ -28,7 +26,7 @@ const applyOptions = (parent) => (pat, i) => { if (!legalTypes.includes(type)) { throw new Error(`mini: stretch: type must be one of ${legalTypes.join('|')} but got ${type}`); } - return reify(pat)[type](amount); + return strudel.reify(pat)[type](amount); } case 'bjorklund': return pat.euclid(operator.arguments_.pulse, operator.arguments_.step, operator.arguments_.rotation); @@ -48,12 +46,12 @@ const applyOptions = (parent) => (pat, i) => { // this is how it was: /* - return reify(pat)._degradeByWith( + return strudel.reify(pat)._degradeByWith( strudel.rand.early(randOffset * _nextSeed()).segment(1), operator.arguments_.amount ?? 0.5, ); */ - return reify(pat)._degradeBy(operator.arguments_.amount ?? 0.5); + return strudel.reify(pat)._degradeBy(operator.arguments_.amount ?? 0.5); // TODO: case 'fixed-step': "%" } @@ -87,7 +85,7 @@ function resolveReplications(ast) { source_: { type_: 'pattern', arguments_: { - alignment: 'h', + alignment: 'fastcat', }, source_: [ { @@ -113,31 +111,45 @@ export function patternifyAST(ast, code) { resolveReplications(ast); const children = ast.source_.map((child) => patternifyAST(child, code)).map(applyOptions(ast)); const alignment = ast.arguments_.alignment; - if (alignment === 'v') { - return stack(...children); + if (alignment === 'stack') { + return strudel.stack(...children); } - if (alignment === 'r') { + if (alignment === 'polymeter') { + // polymeter + const stepsPerCycle = strudel.Fraction( + ast.arguments_.stepsPerCycle + ? ast.arguments_.stepsPerCycle + : strudel.Fraction(children.length > 0 ? children[0].__weight : 1), + ); + + const aligned = children.map((child) => child.fast(stepsPerCycle.div(child.__weight || strudel.Fraction(1)))); + return strudel.stack(...aligned); + } + if (alignment === 'rand') { // https://github.com/tidalcycles/strudel/issues/245#issuecomment-1345406422 // return strudel.chooseInWith(strudel.rand.early(randOffset * _nextSeed()).segment(1), children); return strudel.chooseCycles(...children); } const weightedChildren = ast.source_.some((child) => !!child.options_?.weight); - if (!weightedChildren && alignment === 't') { - return slowcat(...children); + if (!weightedChildren && alignment === 'slowcat') { + return strudel.slowcat(...children); } if (weightedChildren) { - const pat = timeCat(...ast.source_.map((child, i) => [child.options_?.weight || 1, children[i]])); - if (alignment === 't') { - const weightSum = ast.source_.reduce((sum, child) => sum + (child.options_?.weight || 1), 0); + const weightSum = ast.source_.reduce((sum, child) => sum + (child.options_?.weight || 1), 0); + const pat = strudel.timeCat(...ast.source_.map((child, i) => [child.options_?.weight || 1, children[i]])); + if (alignment === 'slowcat') { return pat._slow(weightSum); // timecat + slow } + pat.__weight = weightSum; return pat; } - return sequence(...children); + const pat = strudel.sequence(...children); + pat.__weight = strudel.Fraction(children.length); + return pat; } case 'element': { if (ast.source_ === '~') { - return silence; + return strudel.silence; } if (typeof ast.source_ !== 'object') { if (!ast.location_) { @@ -153,10 +165,12 @@ export function patternifyAST(ast, code) { const [offsetStart = 0, offsetEnd = 0] = actual ? actual.split(ast.source_).map((p) => p.split('').filter((c) => c === ' ').length) : []; - return pure(value).withLocation( - [start.line, start.column + offsetStart, start.offset + offsetStart], - [start.line, end.column - offsetEnd, end.offset - offsetEnd], - ); + return strudel + .pure(value) + .withLocation( + [start.line, start.column + offsetStart, start.offset + offsetStart], + [start.line, end.column - offsetEnd, end.offset - offsetEnd], + ); } return patternifyAST(ast.source_, code); } @@ -183,10 +197,10 @@ export function patternifyAST(ast, code) { }); */ /* case 'struct': // TODO: - return silence; */ + return strudel.silence; */ default: console.warn(`node type "${ast.type_}" not implemented -> returning silence`); - return silence; + return strudel.silence; } } @@ -197,7 +211,7 @@ export const mini = (...strings) => { const ast = krill.parse(code); return patternifyAST(ast, code); }); - return sequence(...pats); + return strudel.sequence(...pats); }; // includes haskell style (raw krill parsing) @@ -211,5 +225,5 @@ export function minify(thing) { if (typeof thing === 'string') { return mini(thing); } - return reify(thing); + return strudel.reify(thing); } diff --git a/packages/mini/test/mini.test.mjs b/packages/mini/test/mini.test.mjs index 42830ff8..dacb4fa0 100644 --- a/packages/mini/test/mini.test.mjs +++ b/packages/mini/test/mini.test.mjs @@ -36,6 +36,16 @@ describe('mini', () => { expect(minS('c3 [d3 e3]')).toEqual(['c3: 0 - 1/2', 'd3: 1/2 - 3/4', 'e3: 3/4 - 1']); expect(minS('c3 [d3 [e3 f3]]')).toEqual(['c3: 0 - 1/2', 'd3: 1/2 - 3/4', 'e3: 3/4 - 7/8', 'f3: 7/8 - 1']); }); + it('supports curly brackets', () => { + expect(minS('{a b, c d e}*3')).toEqual(minS('[a b a b a b, c d e c d e]')); + expect(minS('{a b, c [d e] f}*3')).toEqual(minS('[a b a b a b, c [d e] f c [d e] f]')); + expect(minS('{a b c, d e}*2')).toEqual(minS('[a b c a b c, d e d e d e]')); + }); + it('supports curly brackets with explicit step-per-cycle', () => { + expect(minS('{a b, c d e}%3')).toEqual(minS('[a b a, c d e]')); + expect(minS('{a b, c d e}%5')).toEqual(minS('[a b a b a, c d e c d]')); + expect(minS('{a b, c d e}%6')).toEqual(minS('[a b a b a b, c d e c d e]')); + }); it('supports commas', () => { expect(minS('c3,e3,g3')).toEqual(['c3: 0 - 1', 'e3: 0 - 1', 'g3: 0 - 1']); expect(minS('[c3,e3,g3] f3')).toEqual(['c3: 0 - 1/2', 'e3: 0 - 1/2', 'g3: 0 - 1/2', 'f3: 1/2 - 1']);