├── .gitattributes
├── .gitignore
├── LICENSE.md
├── Makefile
├── Project.ede
├── README.md
├── SkoarPyon
├── apparatus.py
├── lex.py
├── rdpp.py
├── skoarmantics.py
├── skoarmantics_template.py
├── toke_inspector.py
└── toke_inspector_template.py
├── Skoar_SC.testsettings
├── Skoarcery
├── SkoarPyon
│ └── .gitignore
├── dragonsets.py
├── emissions.py
├── factoary
│ ├── Build_Py.py
│ ├── Build_Sc.py
│ ├── Buildoar.py
│ ├── Code_Lexer_Py.py
│ ├── Code_Lexer_Sc.py
│ ├── Code_Parser_Py.py
│ └── Code_Parser_Sc.py
├── laboaratoary
│ ├── TestDragonSpells.py
│ ├── TestNonterminals.py
│ ├── TestParseTable.py
│ ├── TestTerminals.py
│ └── Test_Sclang.py
├── langoids.py
├── nonterminals.py
├── parsetable.py
├── terminals.py
└── underskoar.py
├── SuperCollider
├── Skoar
│ ├── apparatus.sc
│ ├── beaty.sc
│ ├── decorating.sc
│ ├── fairy.sc
│ ├── koar.sc
│ ├── lex.sc
│ ├── minstrel.sc
│ ├── operatoars.sc
│ ├── pitchy.sc
│ ├── rdpp.sc
│ ├── skoar.sc
│ ├── skoarpions.sc
│ ├── skoarpuscles.sc
│ └── toker.sc
├── Testing
│ ├── cats.scd
│ ├── dev.scd
│ ├── increments.scd
│ ├── levels.scd
│ ├── noaty.scd
│ ├── ops.scd
│ ├── ops_dev.scd
│ ├── regex.scd
│ ├── sanity.scd
│ ├── spawn_skeletons.scd
│ └── unittests.sc
├── examples
│ ├── brandnewshoes.scd
│ ├── dungeontimes.scd
│ ├── synthdefs.scd
│ ├── windwaker.scd
│ ├── yay.scd
│ └── zelda.scd
└── testing
│ ├── bigskoar.scd
│ └── conditionals.scd
├── Testing
├── SC_tests.playlist
└── Skoarcery.playlist
├── build.py
├── examples.md
├── sanity.py
└── skoarcery.el
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | __*
3 | .DS_*
4 |
5 | Skoarcery.pyproj
6 | Skoarcery.pyproj.user
7 | Skoarcery.sln
8 | Skoarcery.v12.suo
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 |
2 | The Artistic License 2.0
3 |
4 | Copyright (c) 2014 Lucas Adrianus Cornelisse
5 |
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | This license establishes the terms under which a given free software
12 | Package may be copied, modified, distributed, and/or redistributed.
13 | The intent is that the Copyright Holder maintains some artistic
14 | control over the development of that Package while still keeping the
15 | Package available as open source and free software.
16 |
17 | You are always permitted to make arrangements wholly outside of this
18 | license directly with the Copyright Holder of a given Package. If the
19 | terms of this license do not permit the full use that you propose to
20 | make of the Package, you should contact the Copyright Holder and seek
21 | a different licensing arrangement.
22 |
23 | Definitions
24 |
25 | "Copyright Holder" means the individual(s) or organization(s)
26 | named in the copyright notice for the entire Package.
27 |
28 | "Contributor" means any party that has contributed code or other
29 | material to the Package, in accordance with the Copyright Holder's
30 | procedures.
31 |
32 | "You" and "your" means any person who would like to copy,
33 | distribute, or modify the Package.
34 |
35 | "Package" means the collection of files distributed by the
36 | Copyright Holder, and derivatives of that collection and/or of
37 | those files. A given Package may consist of either the Standard
38 | Version, or a Modified Version.
39 |
40 | "Distribute" means providing a copy of the Package or making it
41 | accessible to anyone else, or in the case of a company or
42 | organization, to others outside of your company or organization.
43 |
44 | "Distributor Fee" means any fee that you charge for Distributing
45 | this Package or providing support for this Package to another
46 | party. It does not mean licensing fees.
47 |
48 | "Standard Version" refers to the Package if it has not been
49 | modified, or has been modified only in ways explicitly requested
50 | by the Copyright Holder.
51 |
52 | "Modified Version" means the Package, if it has been changed, and
53 | such changes were not explicitly requested by the Copyright
54 | Holder.
55 |
56 | "Original License" means this Artistic License as Distributed with
57 | the Standard Version of the Package, in its current version or as
58 | it may be modified by The Perl Foundation in the future.
59 |
60 | "Source" form means the source code, documentation source, and
61 | configuration files for the Package.
62 |
63 | "Compiled" form means the compiled bytecode, object code, binary,
64 | or any other form resulting from mechanical transformation or
65 | translation of the Source form.
66 |
67 |
68 | Permission for Use and Modification Without Distribution
69 |
70 | (1) You are permitted to use the Standard Version and create and use
71 | Modified Versions for any purpose without restriction, provided that
72 | you do not Distribute the Modified Version.
73 |
74 |
75 | Permissions for Redistribution of the Standard Version
76 |
77 | (2) You may Distribute verbatim copies of the Source form of the
78 | Standard Version of this Package in any medium without restriction,
79 | either gratis or for a Distributor Fee, provided that you duplicate
80 | all of the original copyright notices and associated disclaimers. At
81 | your discretion, such verbatim copies may or may not include a
82 | Compiled form of the Package.
83 |
84 | (3) You may apply any bug fixes, portability changes, and other
85 | modifications made available from the Copyright Holder. The resulting
86 | Package will still be considered the Standard Version, and as such
87 | will be subject to the Original License.
88 |
89 |
90 | Distribution of Modified Versions of the Package as Source
91 |
92 | (4) You may Distribute your Modified Version as Source (either gratis
93 | or for a Distributor Fee, and with or without a Compiled form of the
94 | Modified Version) provided that you clearly document how it differs
95 | from the Standard Version, including, but not limited to, documenting
96 | any non-standard features, executables, or modules, and provided that
97 | you do at least ONE of the following:
98 |
99 | (a) make the Modified Version available to the Copyright Holder
100 | of the Standard Version, under the Original License, so that the
101 | Copyright Holder may include your modifications in the Standard
102 | Version.
103 |
104 | (b) ensure that installation of your Modified Version does not
105 | prevent the user installing or running the Standard Version. In
106 | addition, the Modified Version must bear a name that is different
107 | from the name of the Standard Version.
108 |
109 | (c) allow anyone who receives a copy of the Modified Version to
110 | make the Source form of the Modified Version available to others
111 | under
112 |
113 | (i) the Original License or
114 |
115 | (ii) a license that permits the licensee to freely copy,
116 | modify and redistribute the Modified Version using the same
117 | licensing terms that apply to the copy that the licensee
118 | received, and requires that the Source form of the Modified
119 | Version, and of any works derived from it, be made freely
120 | available in that license fees are prohibited but Distributor
121 | Fees are allowed.
122 |
123 |
124 | Distribution of Compiled Forms of the Standard Version
125 | or Modified Versions without the Source
126 |
127 | (5) You may Distribute Compiled forms of the Standard Version without
128 | the Source, provided that you include complete instructions on how to
129 | get the Source of the Standard Version. Such instructions must be
130 | valid at the time of your distribution. If these instructions, at any
131 | time while you are carrying out such distribution, become invalid, you
132 | must provide new instructions on demand or cease further distribution.
133 | If you provide valid instructions or cease distribution within thirty
134 | days after you become aware that the instructions are invalid, then
135 | you do not forfeit any of your rights under this license.
136 |
137 | (6) You may Distribute a Modified Version in Compiled form without
138 | the Source, provided that you comply with Section 4 with respect to
139 | the Source of the Modified Version.
140 |
141 |
142 | Aggregating or Linking the Package
143 |
144 | (7) You may aggregate the Package (either the Standard Version or
145 | Modified Version) with other packages and Distribute the resulting
146 | aggregation provided that you do not charge a licensing fee for the
147 | Package. Distributor Fees are permitted, and licensing fees for other
148 | components in the aggregation are permitted. The terms of this license
149 | apply to the use and Distribution of the Standard or Modified Versions
150 | as included in the aggregation.
151 |
152 | (8) You are permitted to link Modified and Standard Versions with
153 | other works, to embed the Package in a larger work of your own, or to
154 | build stand-alone binary or bytecode versions of applications that
155 | include the Package, and Distribute the result without restriction,
156 | provided the result does not expose a direct interface to the Package.
157 |
158 |
159 | Items That are Not Considered Part of a Modified Version
160 |
161 | (9) Works (including, but not limited to, modules and scripts) that
162 | merely extend or make use of the Package, do not, by themselves, cause
163 | the Package to be a Modified Version. In addition, such works are not
164 | considered parts of the Package itself, and are not subject to the
165 | terms of this license.
166 |
167 |
168 | General Provisions
169 |
170 | (10) Any use, modification, and distribution of the Standard or
171 | Modified Versions is governed by this Artistic License. By using,
172 | modifying or distributing the Package, you accept this license. Do not
173 | use, modify, or distribute the Package, if you do not accept this
174 | license.
175 |
176 | (11) If your Modified Version has been derived from a Modified
177 | Version made by someone other than you, you are nevertheless required
178 | to ensure that your Modified Version complies with the requirements of
179 | this license.
180 |
181 | (12) This license does not grant you the right to use any trademark,
182 | service mark, tradename, or logo of the Copyright Holder.
183 |
184 | (13) This license includes the non-exclusive, worldwide,
185 | free-of-charge patent license to make, have made, use, offer to sell,
186 | sell, import and otherwise transfer the Package with respect to any
187 | patent claims licensable by the Copyright Holder that are necessarily
188 | infringed by the Package. If you institute patent litigation
189 | (including a cross-claim or counterclaim) against any party alleging
190 | that the Package constitutes direct or contributory patent
191 | infringement, then this Artistic License to you shall terminate on the
192 | date that such litigation is filed.
193 |
194 | (14) Disclaimer of Warranty:
195 | THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
196 | IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
197 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
198 | NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
199 | LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
200 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
201 | DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
202 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
203 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 |
2 | test_grammar: Skoarcery\terminals.py Skoarcery\nonterminals.py Skoarcery\emissions.py Skoarcery\underskoar.py
3 | python -m unittest .\Skoarcery\laboaratory\TestDragonSpells.py
4 | python -m unittest .\Skoarcery\laboaratory\TestTerminals.py
5 | python -m unittest .\Skoarcery\laboaratory\TestNonTerminals.py
6 | python -m unittest .\Skoarcery\laboaratory\TestParseTable.py
7 |
8 | sc_lexer: test_grammar
9 | python -m unittest .\Skoarcery\factoary\Code_Lexer_Sc.py
10 |
11 | sc_parser: sc_lexer
12 | python -m unittest .\Skoarcery\factoary\Code_Parser_Sc.py
13 |
14 | sc_sanity:
15 | python -m unittest .\Skoarcery\laboaratory\Test_Sclang.py
16 |
17 | sc_clean:
18 | rm SuperCollider\Skoar\lex.sc
19 | rm SuperCollider\Skoar\rdpp.sc
20 |
21 | clean: sc_clean
22 |
23 | all: sc_parser sc_sanity
24 |
--------------------------------------------------------------------------------
/Project.ede:
--------------------------------------------------------------------------------
1 | ;; Object Skoarcery
2 | ;; EDE Project Files are auto generated: Do Not Edit
3 | (ede-proj-project "Skoarcery"
4 | :file "Project.ede"
5 | :name "Skoarcery"
6 | :targets nil)
7 |
--------------------------------------------------------------------------------
/SkoarPyon/apparatus.py:
--------------------------------------------------------------------------------
1 | from collections import UserDict
2 | from Skoarcery.SkoarPyon import toke_inspector, skoarmantics
3 | from Skoarcery.SkoarPyon.lex import Toke_Whitespace, Toke_EOF, SkoarToke
4 |
5 |
6 | class Toker:
7 |
8 | def __init__(I, code):
9 | I.skoarse = code
10 | I.am_here = 0
11 | I.saw = None
12 |
13 | def see(I, want):
14 |
15 | if I.saw:
16 | if isinstance(I.saw, want):
17 | return I.saw
18 | else:
19 | I.saw = want.match(I.skoarse, I.am_here)
20 | return I.saw
21 |
22 | return None
23 |
24 | def sees(I, wants):
25 |
26 | I.am_here += Toke_Whitespace.burn(I.skoarse, I.am_here)
27 |
28 | for want in wants:
29 | X = I.see(want)
30 | if X:
31 | return X
32 |
33 | return None
34 |
35 | def burn(I, want):
36 |
37 | toke = I.saw
38 |
39 | if toke is None:
40 | toke = I.see(want)
41 |
42 | if isinstance(toke, want):
43 | I.saw = None
44 | I.am_here += toke.burn()
45 | I.am_here += Toke_Whitespace.burn(I.skoarse, I.am_here)
46 | return toke
47 |
48 | raise Exception("I tried to burn " + want.__name__ + ", but what I saw is " + toke.__class__.__name__)
49 |
50 | def eof(I):
51 | try:
52 | Toke_EOF.burn(I.skoarse, I.am_here)
53 | except:
54 | I.dump()
55 | raise
56 |
57 | def dump(I):
58 | print("\nToker Dump")
59 | print("here : " + str(I.am_here))
60 | print("saw : " + str(I.saw))
61 | print("skoarse: " + I.skoarse[0:I.am_here] + "_$_" + I.skoarse[I.am_here:-1])
62 |
63 |
64 | # --------------
65 | # The Parse Tree
66 | # --------------
67 | class SkoarNoad:
68 |
69 | def __init__(self, name, parent, i=0):
70 | self.performer = lambda x: None
71 | self.j = 0
72 | self.parent = parent
73 | self.i = i # position in parent
74 | self.n = 0 # number of children
75 | self.name = name
76 | self.children = []
77 | self.is_beat = False
78 | self.next_jmp = None
79 | self.toke = None
80 |
81 | # if isinstance(toke, SkoarToke):
82 | # self.inspectable = toke.__class__.inspectable
83 | # else:
84 | # self.inspectable = False
85 |
86 | # ------------------
87 | # shrinking the tree
88 | # ------------------
89 | def replace_children(self, children):
90 | self.children = children
91 | self.recount_children()
92 |
93 | def recount_children(self):
94 | i = 0
95 | n = 0
96 |
97 | for x in self.children:
98 | if isinstance(x, SkoarNoad):
99 | x.i = i
100 | i += 1
101 | n += 1
102 |
103 | self.n = n
104 |
105 | # ----------------
106 | # growing the tree
107 | # ----------------
108 | def add_noad(self, noad):
109 | self.children.append(noad)
110 | noad.i = self.n
111 | self.n += 1
112 |
113 | def add_toke(self, name, toke):
114 | noad = SkoarNoad(name, self, self.n)
115 | noad.toke = toke
116 | self.children.append(noad)
117 | self.n += 1
118 |
119 | def absorb_toke(self):
120 | if self.n == 1:
121 |
122 | x = self.children.pop()
123 | self.n = 0
124 |
125 | if isinstance(x, SkoarNoad) and x.toke:
126 | self.toke = x.toke
127 | else:
128 | self.toke = x
129 |
130 | return self.toke
131 |
132 | # ----------------
133 | # showing the tree
134 | # ----------------
135 | def draw_tree(self, tab=1):
136 | s = ("{:>" + str(tab) + "}{}\n").format(" ", self.name)
137 | for x in self.children:
138 | if x:
139 | s += x.draw_tree(tab + 1)
140 |
141 | return s
142 |
143 | # -----------------
144 | # Climbing the Tree
145 | # -----------------
146 | def depth_visit(self, f):
147 |
148 | for x in self.children:
149 | if x:
150 | x.depth_visit(f)
151 |
152 | f(self)
153 |
154 | def next_item(self):
155 |
156 | if self.next_jmp:
157 | return self.next_jmp
158 |
159 | if self.j == self.n:
160 | if self.parent is None:
161 | raise StopIteration
162 |
163 | return self.parent.next_item()
164 |
165 | n = self.children[self.j]
166 | self.j += 1
167 | return n
168 |
169 | def go_here_next(self, noad):
170 | self.next_jmp = noad
171 | noad.parent.j = noad.i
172 |
173 | # -------------------
174 | # performing the tree
175 | # -------------------
176 | def on_enter(self):
177 | self.j = 0
178 |
179 | def action(self):
180 | self.performer()
181 |
182 |
183 | class SkoarIterator:
184 |
185 | def __init__(self, skoar):
186 | self.noad = skoar.tree
187 |
188 | def __iter__(self):
189 | return self
190 |
191 | def __next__(self):
192 | x = self.noad.next_item()
193 |
194 | if isinstance(x, SkoarNoad):
195 | self.noad = x
196 | x.on_enter()
197 |
198 | return x
199 |
200 |
201 | class Skoar:
202 |
203 | def __init__(self, skoarse):
204 | from ..SkoarPyon import rdpp
205 | self.skoarse = skoarse
206 | self.tree = None
207 | self.toker = Toker(self.skoarse)
208 | self.parser = rdpp.SkoarParser(self)
209 | self.markers = []
210 |
211 | self.control_stack = []
212 |
213 | self.cur_noat = None
214 | self.noat_direction = 1
215 |
216 | def parse(self):
217 | self.tree = self.parser.skoar(None)
218 | self.tree.draw_tree()
219 | self.toker.eof()
220 |
221 | def decorate(self, loud=False):
222 |
223 | debug = (lambda x: print(x)) if loud else (lambda x: x)
224 |
225 | def inspect(x):
226 |
227 | # tokens*
228 | if x.toke:
229 | try:
230 | # run the function x.name, pass the token
231 | toke_inspector.__dict__[x.name](x.toke)
232 |
233 | debug("decorated toke " + x.name + ":")
234 | for k, v in x.toke.__dict__.items():
235 | debug(" " + k + ": " + str(v))
236 | debug("")
237 | except KeyError:
238 | pass
239 |
240 | # nonterminals*
241 | else:
242 | try:
243 | # run the function, pass the noad (not the nonterminal)
244 | y = skoarmantics.__dict__[x.name]
245 | y(self, x)
246 |
247 | debug("decorated noad " + x.name + ":")
248 | for k, v in x.__dict__.items():
249 | if k not in ["children", "parent", "toke", "inspectable"]:
250 | debug(" " + k + ": " + repr(v))
251 | debug("")
252 | except KeyError:
253 | pass
254 |
255 | self.tree.depth_visit(inspect)
256 |
257 | def get_pattern_gen(self):
258 | for x in SkoarIterator(self):
259 | if isinstance(x, SkoarNoad):
260 |
261 | # run performance handler
262 | x.performer(self)
263 |
264 | if x.is_beat:
265 | yield [self.cur_noat.lexeme, x.beat.val]
266 |
267 | # ----
268 | # misc
269 | # ----
270 | def noat_go(self, noat):
271 |
272 | self.cur_noat = noat
273 |
274 | # # find direction and if we're moving
275 | # move = True
276 | # if noat.up:
277 | # self.noat_direction = 1
278 | #
279 | # elif noat.down:
280 | # self.noat_direction = -1
281 | #
282 | # elif noat == self.cur_noat:
283 | # move = False
284 | #
285 | # # move if we do
286 | # if move and self.noat_direction > 0:
287 | # print("up to ", end="")
288 | #
289 | # elif move and self.noat_direction < 0:
290 | # print("down to ", end="")
291 | #
292 | # print(noat.letter, end="")
293 | #
294 | # for i in range(0, noat.sharps):
295 | # print("#", end="")
296 | #
297 | # for i in range(0, noat.flats):
298 | # print("b", end="")
299 |
300 | # save these in a list for jumping around in
301 | def add_marker(self, marker_noad):
302 | self.markers.append(marker_noad)
303 |
304 | def jmp_colon(self, noad):
305 | from Skoarcery.SkoarPyon.lex import Toke_Bars
306 | toke = noad.toke
307 |
308 | if toke.unspent:
309 | # spend it
310 | toke.unspent = False
311 | print("here")
312 | # find where we are in self.markers
313 | j = 0
314 | n = len(self.markers)
315 | for i in range(0, n):
316 | t = self.markers[i]
317 | if noad == t:
318 | j = i
319 | break
320 | else:
321 | raise AssertionError("couldn't find where we are in markers")
322 |
323 | # go backwards in list and find either a
324 | # post_repeat or the start
325 | for i in range(j - 1, 0, -1):
326 | x = self.markers[i]
327 | t = x.toke
328 |
329 | if isinstance(t, Toke_Bars) and t.post_repeat:
330 | noad.go_here_next(x)
331 | break
332 | else:
333 | noad.go_here_next(self.markers[0])
334 |
335 |
336 | def parse(src):
337 |
338 | skoar = Skoar(src)
339 | skoar.parse()
340 |
341 | return skoar
342 |
343 |
--------------------------------------------------------------------------------
/SkoarPyon/skoarmantics.py:
--------------------------------------------------------------------------------
1 | # ============
2 | # Skoarmantics
3 | # ============
4 |
5 | #
6 | # We went depth first so our children should be defined
7 | #
8 |
9 |
10 | def msg_chain_node(skoar, noad):
11 | pass
12 |
13 |
14 | def beat(skoar, noad):
15 | noad.absorb_toke()
16 | noad.beat = noad.toke
17 | noad.is_beat = True
18 |
19 |
20 | def meter_beat(skoar, noad):
21 | noad.absorb_toke()
22 | noad.beat = noad.toke
23 |
24 |
25 | def listy(skoar, noad):
26 | from Skoarcery.SkoarPyon.lex import Toke_ListSep
27 |
28 | X = []
29 |
30 | for x in noad.children[1:-1]:
31 | if x.toke and isinstance(x.toke, Toke_ListSep):
32 | continue
33 | X.append(x)
34 |
35 | noad.replace_children(X)
36 |
37 |
38 | def clef(skoar, noad):
39 | pass
40 |
41 |
42 | def meter_symbolic(skoar, noad):
43 | pass
44 |
45 |
46 | def stmt(skoar, noad):
47 | pass
48 |
49 |
50 | def musical_keyword_misc(skoar, noad):
51 | pass
52 |
53 |
54 | def coda(skoar, noad):
55 | pass
56 |
57 |
58 | def meter_ass(skoar, noad):
59 | pass
60 |
61 |
62 | def assignment(skoar, noad):
63 | pass
64 |
65 |
66 | def accidentally(skoar, noad):
67 | pass
68 |
69 |
70 | def boolean(skoar, noad):
71 | pass
72 |
73 |
74 | def ottavas(skoar, noad):
75 | pass
76 |
77 |
78 | def skoaroid(skoar, noad):
79 | pass
80 |
81 |
82 | def msg(skoar, noad):
83 | pass
84 |
85 |
86 | def dal_goto(skoar, noad):
87 | pass
88 |
89 |
90 | def cthulhu(skoar, noad):
91 | pass
92 |
93 |
94 | def dynamic(skoar, noad):
95 | pass
96 |
97 |
98 | def optional_carrots(skoar, noad):
99 | pass
100 |
101 |
102 | def meter_sig_prime(skoar, noad):
103 | pass
104 |
105 |
106 | def meter(skoar, noad):
107 |
108 | # trim start and end tokens
109 | noad.replace_children(noad.children[1:-1])
110 |
111 |
112 | def marker(skoar, noad):
113 | from Skoarcery.SkoarPyon.lex import Toke_Bars
114 |
115 | noad.absorb_toke()
116 | skoar.add_marker(noad)
117 |
118 | toke = noad.toke
119 | if isinstance(toke, Toke_Bars):
120 | if toke.pre_repeat > 0:
121 | noad.performer = (lambda x: x.jmp_colon(noad))
122 |
123 |
124 | def noaty(skoar, noad):
125 | pass
126 |
127 |
128 | def noat_literal(skoar, noad):
129 | from Skoarcery.SkoarPyon.lex import Toke_NamedNoat
130 |
131 | noat = noad.absorb_toke()
132 | noad.noat = noat
133 |
134 | if isinstance(noat, Toke_NamedNoat):
135 | noad.performer = (lambda x: x.noat_go(noat))
136 |
137 |
138 | def noat_reference(skoar, noad):
139 |
140 | # TODO Symbol | CurNoat | listy
141 | pass
142 |
143 |
144 |
145 | def pedally(skoar, noad):
146 | pass
147 |
148 |
149 |
--------------------------------------------------------------------------------
/SkoarPyon/skoarmantics_template.py:
--------------------------------------------------------------------------------
1 | # ========================================================================================
2 | # Skoarmantics - Generated by Code_Skoarmantics_Py on 2014-05-05 21:29:46 for Python 3.3.2
3 | # ========================================================================================
4 |
5 |
6 |
7 |
8 | # -
9 | #
10 | # -
11 | def musical_keyword_misc(skoar, noad):
12 | pass
13 |
14 |
15 | def meter_sig_prime(skoar, noad):
16 | pass
17 |
18 |
19 | def optional_carrots(skoar, noad):
20 | pass
21 |
22 |
23 | def meter(skoar, noad):
24 | pass
25 |
26 |
27 | def ottavas(skoar, noad):
28 | pass
29 |
30 |
31 | def msg(skoar, noad):
32 | pass
33 |
34 |
35 | def pedally(skoar, noad):
36 | pass
37 |
38 |
39 | def dynamic(skoar, noad):
40 | pass
41 |
42 |
43 | def meter_beat(skoar, noad):
44 | pass
45 |
46 |
47 | def coda(skoar, noad):
48 | pass
49 |
50 |
51 | def markers(skoar, noad):
52 | pass
53 |
54 |
55 | def cthulhu(skoar, noad):
56 | pass
57 |
58 |
59 | def dal_goto(skoar, noad):
60 | pass
61 |
62 |
63 | def accidentally(skoar, noad):
64 | pass
65 |
66 |
67 | def listy(skoar, noad):
68 | pass
69 |
70 |
71 | def skoaroid(skoar, noad):
72 | pass
73 |
74 |
75 | def assignment(skoar, noad):
76 | pass
77 |
78 |
79 | def beat(skoar, noad):
80 | pass
81 |
82 |
83 | def boolean(skoar, noad):
84 | pass
85 |
86 |
87 | def stmt(skoar, noad):
88 | pass
89 |
90 |
91 | def meter_symbolic(skoar, noad):
92 | pass
93 |
94 |
95 | def msg_chain_node(skoar, noad):
96 | pass
97 |
98 |
99 | def meter_ass(skoar, noad):
100 | pass
101 |
102 |
103 | def clef(skoar, noad):
104 | pass
105 |
106 |
107 |
--------------------------------------------------------------------------------
/SkoarPyon/toke_inspector.py:
--------------------------------------------------------------------------------
1 | # ==============
2 | # toke_inspector
3 | # ==============
4 | #
5 | # Here we pick the vals out of the tokens
6 | # and set its attributes appropriately
7 | from math import ldexp
8 |
9 | import re
10 |
11 |
12 | def Toke_Int(toke):
13 | toke.val = int(toke.lexeme)
14 |
15 |
16 | def Toke_Float(toke):
17 | toke.val = float(toke.lexeme)
18 |
19 |
20 | def Toke_Carrots(toke):
21 | toke.val = len(toke.lexeme)
22 |
23 |
24 | def Toke_Tuplet(toke):
25 | toke.val = 0
26 |
27 |
28 | def Toke_Crotchets(toke):
29 | toke.is_rest = True
30 | toke.val = 2 ** len(toke.lexeme)
31 |
32 |
33 | def Toke_Quavers(toke):
34 | toke.is_rest = True
35 | # len("oo/")
36 | toke.val = ldexp(1, -(len(toke.lexeme) - 1))
37 |
38 |
39 | def Toke_DynPiano(toke):
40 | toke.val = 0
41 |
42 |
43 | def Toke_DynForte(toke):
44 | toke.val = 0
45 |
46 |
47 | def Toke_Quarters(toke):
48 | toke.is_rest = False
49 | toke.val = 2 ** (len(toke.lexeme) - 1)
50 |
51 |
52 | def Toke_Eighths(toke):
53 | toke.is_rest = False
54 | toke.val = ldexp(1, -len(toke.lexeme))
55 |
56 |
57 | vector_noat_regex = re.compile(r"(~?)([a-g])(?:(#*)|(b*))(~?)")
58 |
59 |
60 | def Toke_NamedNoat(toke):
61 | s = toke.lexeme
62 |
63 | r = vector_noat_regex.search(s)
64 |
65 | if r.group(1):
66 | toke.up = True
67 |
68 | toke.letter = r.group(2)
69 |
70 | sharps = r.group(3)
71 | if sharps:
72 | toke.sharps = len(sharps)
73 |
74 | flats = r.group(4)
75 | if flats:
76 | toke.flats = len(flats)
77 |
78 | if r.group(5):
79 | if toke.up:
80 | raise AssertionError("Can't noat up and down: " + s)
81 | toke.down = True
82 |
83 |
84 | def Toke_BooleanOp(toke):
85 | toke.val = toke.lexeme
86 |
87 |
88 | def Toke_Choard(toke):
89 | toke.val = toke.lexeme
90 |
91 |
92 | def Toke_MsgName(toke):
93 | toke.val = toke.lexeme
94 |
95 |
96 | def Toke_MsgNameWithArgs(toke):
97 | toke.val = toke.lexeme.rstrip("<")
98 |
99 |
100 | def Toke_Volta(toke):
101 | toke.val = int(toke.lexeme.strip("[.]"))
102 |
103 |
104 | def Toke_Symbol(toke):
105 | toke.val = toke.lexeme[1:]
106 |
107 |
108 | def Toke_Segno(toke):
109 | a = toke.lexeme.split("_")
110 | if len(a) > 1:
111 | toke.label = a[1]
112 | else:
113 | toke.label = ""
114 |
115 |
116 | def Toke_String(toke):
117 | toke.val = toke.lexeme[1:-1]
118 |
119 |
120 | def Toke_Bars(toke):
121 | toke.pre_repeat = toke.lexeme.startswith(":")
122 | toke.post_repeat = toke.lexeme.endswith(":")
123 | toke.unspent = True
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/SkoarPyon/toke_inspector_template.py:
--------------------------------------------------------------------------------
1 | # =============================================================================================
2 | # toke_inspector - Generated by Code_Lexer_Inspector_Py on 2014-05-10 14:13:48 for Python 3.3.2
3 | # =============================================================================================
4 |
5 | import re
6 | import abc
7 |
8 |
9 | # -----------
10 | # Value Tokes
11 | # -----------
12 | def Toke_Comment(toke):
13 | toke.val = 0
14 |
15 |
16 | def Toke_Int(toke):
17 | toke.val = 0
18 |
19 |
20 | def Toke_Float(toke):
21 | toke.val = 0
22 |
23 |
24 | def Toke_Carrots(toke):
25 | toke.val = 0
26 |
27 |
28 | def Toke_Tuplet(toke):
29 | toke.val = 0
30 |
31 |
32 | def Toke_Crotchets(toke):
33 | toke.val = 0
34 |
35 |
36 | def Toke_Quavers(toke):
37 | toke.val = 0
38 |
39 |
40 | def Toke_DynPiano(toke):
41 | toke.val = 0
42 |
43 |
44 | def Toke_DynForte(toke):
45 | toke.val = 0
46 |
47 |
48 | def Toke_Quarters(toke):
49 | toke.val = 0
50 |
51 |
52 | def Toke_Eighths(toke):
53 | toke.val = 0
54 |
55 |
56 | def Toke_NamedNoat(toke):
57 | toke.val = 0
58 |
59 |
60 | def Toke_BooleanOp(toke):
61 | toke.val = 0
62 |
63 |
64 | def Toke_Choard(toke):
65 | toke.val = 0
66 |
67 |
68 | def Toke_MsgName(toke):
69 | toke.val = 0
70 |
71 |
72 | def Toke_MsgNameWithArgs(toke):
73 | toke.val = 0
74 |
75 |
76 | def Toke_Segno(toke):
77 | toke.val = 0
78 |
79 |
80 | def Toke_Volta(toke):
81 | toke.val = 0
82 |
83 |
84 | def Toke_Symbol(toke):
85 | toke.val = 0
86 |
87 |
88 | def Toke_String(toke):
89 | toke.val = 0
90 |
91 |
92 | def Toke_Bars(toke):
93 | toke.val = 0
94 |
95 |
96 |
--------------------------------------------------------------------------------
/Skoar_SC.testsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 | build skoar for supercollider
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Skoarcery/SkoarPyon/.gitignore:
--------------------------------------------------------------------------------
1 | lex.py
2 | rdpp.py
3 |
--------------------------------------------------------------------------------
/Skoarcery/dragonsets.py:
--------------------------------------------------------------------------------
1 | # ==========================================
2 | # FIRST and FOLLOW sets from the dragon book
3 | # ==========================================
4 | from Skoarcery.langoids import Nonterminal, Production, Langoid
5 |
6 | FIRST = None
7 | FOLLOW = None
8 |
9 |
10 | def init(compute=True):
11 | global FIRST, FOLLOW
12 |
13 | FIRST = DragonSet("FIRST")
14 | FOLLOW = DragonSet("FOLLOW")
15 |
16 | print("Dragon sets initialized.")
17 |
18 | if compute:
19 | compute_sets()
20 |
21 |
22 | def compute_sets():
23 | compute_firsts()
24 | compute_follows()
25 |
26 | print("Dragon sets computed")
27 |
28 |
29 | class DragonSet:
30 |
31 | def __init__(self, name):
32 | self.name = name
33 | self.D = dict()
34 |
35 | def __call__(self, *args):
36 |
37 | key = ""
38 | X = args[0]
39 |
40 | if not X:
41 | print("EH? " + repr(args))
42 | raise AssertionError
43 |
44 | if isinstance(X, str):
45 | key = X
46 |
47 | if isinstance(X, Langoid):
48 | key = X.name
49 |
50 | if isinstance(X, Production):
51 | X = X.production
52 |
53 | if isinstance(X, list):
54 | if self.name == "FIRST":
55 | return FIRST_SEQ(X)
56 | raise NotImplementedError
57 |
58 | #print("Key: " + key + " < " + str(X) + " < " + repr(args[0]))
59 | try:
60 | S = self.D[key]
61 | except KeyError:
62 | S = set()
63 | self.D[key] = S
64 |
65 | return S
66 |
67 | def __len__(self):
68 | i = 0
69 |
70 | for S in self.D.values():
71 | i += len(S)
72 |
73 | return i
74 |
75 | def add_element(self, key, element):
76 |
77 | #print("add-Elemetn: " + repr(key) + str(key.__class__))
78 |
79 | try:
80 | S = self.D[key.name]
81 | except KeyError:
82 | S = set()
83 |
84 | S.add(element)
85 | self.D[key.name] = S
86 |
87 | def __str__(self):
88 | s = ""
89 |
90 | for k, v in self.D.items():
91 | s += self.name + "(" + str(k) + "): " + str(v) + "\n"
92 |
93 | return s
94 |
95 |
96 | def compute_firsts():
97 |
98 | from Skoarcery.terminals import Empty, tokens as T
99 | from Skoarcery.nonterminals import nonterminals as N
100 |
101 | global FIRST
102 |
103 | # do terminals first
104 | for X in T.values():
105 | FIRST(X).add(X)
106 |
107 | last = 0
108 | first_len = len(FIRST)
109 | while first_len > last:
110 |
111 | last = first_len
112 |
113 | for X in N.values():
114 | if X.derives_empty:
115 | FIRST(X).add(Empty)
116 |
117 | for R in X.production_rules:
118 |
119 | i = -1
120 | n = len(R.production)
121 |
122 | # figure out FIRST(X) first
123 | for Yi in R.production:
124 | i += 1
125 |
126 | Yi_to_end = R.production[i:]
127 |
128 | if len(Yi_to_end) > 0:
129 | S = FIRST(Yi_to_end)
130 |
131 | S.update(
132 | everything_but_e(FIRST(Yi))
133 | )
134 |
135 | FIRST(X).update(S)
136 | FIRST(Yi_to_end).update(S)
137 |
138 | if not Yi.derives_empty:
139 | break
140 |
141 | # if we got to the end of the loop without breaking, add Empty
142 | else:
143 | FIRST(X).add(Empty)
144 |
145 | first_len = len(FIRST)
146 |
147 |
148 | def everything_but_e(S):
149 | from Skoarcery.terminals import Empty
150 |
151 | return {el for el in S if el != Empty}
152 |
153 |
154 | #noinspection PyPep8Naming
155 | def FIRST_SEQ(list_of_langoids):
156 | from Skoarcery.terminals import Empty
157 |
158 | global FIRST
159 |
160 | OUT = set()
161 |
162 | for Yi in list_of_langoids:
163 |
164 | S = FIRST(Yi)
165 |
166 | OUT.update(everything_but_e(S))
167 |
168 | if Empty not in S:
169 | break
170 |
171 | # if we got to the end of the loop without breaking, add Empty
172 | else:
173 | OUT.add(Empty)
174 |
175 | return OUT
176 |
177 |
178 | #noinspection PyPep8Naming
179 | def compute_follows():
180 | from Skoarcery.terminals import EOF, Empty
181 | from Skoarcery.nonterminals import nonterminals as N, SKOAR
182 |
183 | global FIRST, FOLLOW
184 |
185 | # start symbol gets end symbol
186 | FOLLOW(SKOAR).add(EOF)
187 |
188 | # repeat until nothing can be added to any follow set
189 | last = 0
190 | follow_len = len(FOLLOW)
191 | while follow_len > last:
192 |
193 | last = follow_len
194 |
195 | for X in N.values():
196 |
197 | for R in X.production_rules:
198 |
199 | A = R.production
200 |
201 | # If there is a production [ A -> alpha B beta]:
202 | # everything except in FIRST(beta) is in FOLLOW(B)
203 |
204 | # examine each suffix (except last)
205 | n = len(A)
206 |
207 | for i in range(0, n - 1):
208 |
209 | B = A[i]
210 | if not isinstance(B, Nonterminal):
211 | continue
212 |
213 | beta = A[i + 1:]
214 |
215 | #print("n: " + str(n) + " i: " + str(i) + " A: " + repr(A) + " beta: " + repr(beta))
216 |
217 | S = FIRST(beta)
218 | FOLLOW(B).update(everything_but_e(S))
219 |
220 | for i in reversed(range(0, n)):
221 |
222 | B = A[i]
223 | if not isinstance(B, Nonterminal):
224 | continue
225 |
226 | # we are at the end of the list
227 | if i == n - 1:
228 | FOLLOW(B).update(FOLLOW(X))
229 | continue
230 |
231 | beta = A[i + 1:]
232 |
233 | S = FIRST(beta)
234 |
235 | #print(": FIRST(" + repr(beta) + ") = " + repr(S))
236 |
237 | if Empty in S:
238 | FOLLOW(B).update(FOLLOW(X))
239 | else:
240 | break
241 |
242 | follow_len = len(FOLLOW)
243 |
244 |
245 |
--------------------------------------------------------------------------------
/Skoarcery/factoary/Build_Py.py:
--------------------------------------------------------------------------------
1 | from imp import reload
2 | import unittest
3 | from Skoarcery.factoary.Buildoar import Buildoar
4 | from Skoarcery.factoary.Code_Lexer_Py import Code_Lexer_Py
5 | from Skoarcery.factoary.Code_Parser_Py import Code_Parser_Py
6 | from Skoarcery.laboaratoary.TestDragonSpells import DragonTests
7 | from Skoarcery.laboaratoary.ExamineParseTree import ExamineParseTree
8 | from Skoarcery.laboaratoary.TestParseTable import Verify_LL_1
9 | from Skoarcery.laboaratoary.TestNonterminals import TestNonterminals
10 | from Skoarcery.laboaratoary.TestPerformer import Test_Performer
11 | from Skoarcery.laboaratoary.TestTerminals import TestTokens
12 | from Skoarcery.laboaratoary.TestApparatus import Test_Apparatus
13 |
14 |
15 | class Build_Pymp(Buildoar):
16 |
17 | def tes_Build_Skoar_Python(self):
18 |
19 | #
20 | # Grammar
21 | self.step("Test Grammar",
22 | [TestTokens, TestNonterminals, Verify_LL_1, DragonTests])
23 |
24 | #
25 | # Lexer
26 | self.step("Build Lexer", Code_Lexer_Py)
27 |
28 | from Skoarcery.SkoarPyon import lex
29 | reload(lex)
30 |
31 | # #
32 | # # Toke Inspector
33 | # self.step(Code_Lexer_Inspector_Py)
34 | #
35 | # from Skoarcery.pymp import toke_inspector
36 | # reload(toke_inspector)
37 |
38 | #
39 | # Parser
40 | self.step("Build Parser", Code_Parser_Py)
41 |
42 | from Skoarcery.SkoarPyon import rdpp
43 | reload(rdpp)
44 |
45 | #
46 | # Apparatus
47 | self.step("Sanity",
48 | [Test_Apparatus, ExamineParseTree, Test_Performer])
49 |
50 | if __name__ == '__main__':
51 | unittest.main()
52 |
--------------------------------------------------------------------------------
/Skoarcery/factoary/Build_Sc.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from Skoarcery.factoary.Buildoar import Buildoar
3 | from Skoarcery.factoary.Code_Lexer_Sc import Code_Lexer_Sc
4 | from Skoarcery.factoary.Code_Parser_Sc import Code_Parser_Sc
5 | from Skoarcery.laboaratoary.TestDragonSpells import DragonTests
6 | from Skoarcery.laboaratoary.TestParseTable import Verify_LL_1
7 | from Skoarcery.laboaratoary.TestNonterminals import TestNonterminals
8 | from Skoarcery.laboaratoary.TestTerminals import TestTokens
9 | from Skoarcery.laboaratoary.Test_Sclang import Test_Sclang, Test_Sclang_Sanity, Test_Sclang_Dev
10 |
11 |
12 | class Build_Sc(Buildoar):
13 |
14 | def build(self):
15 |
16 | #
17 | # Grammar
18 | self.step("Test Grammar",
19 | [TestTokens, TestNonterminals, Verify_LL_1, DragonTests])
20 |
21 | #
22 | # Lexer
23 | self.step("Build Lexer", Code_Lexer_Sc)
24 |
25 | # #
26 | # # Toke Inspector
27 | #
28 | # self.run_tests("Build toke inspector", Code_Lexer_Inspector_Sc))
29 |
30 | #
31 | # Parser
32 | self.step("Build Parser", Code_Parser_Sc)
33 |
34 | #
35 | # SuperCollider should compile class lib
36 |
37 | def sanity(self):
38 | self.step("Sanity Tests", Test_Sclang_Sanity)
39 |
40 | #
41 | # Apparatus
42 | #self.step("Sanity", [Test_Apparatus, ExamineParseTree, Test_Performer])
43 |
44 | def dev(self):
45 | self.step("Dev Tests", Test_Sclang_Dev)
46 |
47 |
48 | #if __name__ == '__main__':
49 | # b = Build_Sc()
50 | # b.build()
51 |
52 |
--------------------------------------------------------------------------------
/Skoarcery/factoary/Buildoar.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 |
4 | class Buildoar(unittest.TestCase):
5 |
6 | def step(self, msg, list_of_steps, assert_success=True):
7 | from unittest import TestSuite as TS, makeSuite as sweeten, TextTestRunner as Runner
8 |
9 | sweet = TS()
10 |
11 | if not isinstance(list_of_steps, list):
12 | list_of_steps = [list_of_steps]
13 |
14 | for test in list_of_steps:
15 | sweet.addTest(sweeten(test))
16 |
17 | result = Runner().run(sweet)
18 |
19 | if assert_success:
20 | self.assertTrue(result.wasSuccessful(), msg)
21 | print(msg + ": [ OK ]")
22 |
23 |
24 | if __name__ == '__main__':
25 | unittest.main()
26 |
--------------------------------------------------------------------------------
/Skoarcery/factoary/Code_Lexer_Py.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from Skoarcery import terminals, emissions, underskoar
4 |
5 |
6 | class Code_Lexer_Py(unittest.TestCase):
7 |
8 | def setUp(self):
9 | terminals.init()
10 | emissions.init()
11 | underskoar.init(emissions.PY)
12 |
13 | def imports(self):
14 | emissions.PY.raw(
15 | """
16 | import re
17 | import abc
18 |
19 |
20 | class SubclassResponsibilityError(NotImplementedError):
21 | pass
22 |
23 |
24 | class SkoarError(AssertionError):
25 | pass
26 |
27 |
28 | """
29 | )
30 |
31 | def base_token(self):
32 | underskoar.skoarToke()
33 |
34 | def EOF_token(self):
35 | underskoar.EOF_token()
36 |
37 | def whitespace_token(self):
38 | underskoar.whitespace_token()
39 |
40 | def typical_token(self, token):
41 | underskoar.typical_token(token)
42 |
43 | def test_PY_lexer(self):
44 |
45 | fd = open("SkoarPyon/lex.py", mode="w")
46 |
47 | emissions.PY.fd = fd
48 | emissions.PY.file_header("lex", "Code_Py_Lexer")
49 |
50 | self.imports()
51 | self.base_token()
52 | self.whitespace_token()
53 | self.EOF_token()
54 |
55 | emissions.PY.cmt_hdr("Everyday Tokes")
56 | for token in terminals.tokens.values():
57 | if token not in terminals.odd_balls:
58 | self.typical_token(token)
59 |
60 | fd.close()
61 |
--------------------------------------------------------------------------------
/Skoarcery/factoary/Code_Lexer_Sc.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | import os
3 |
4 | from Skoarcery import terminals, emissions, underskoar
5 |
6 |
7 | bs = "{"
8 | be = "}"
9 |
10 |
11 | class Code_Lexer_Sc(unittest.TestCase):
12 |
13 | def setUp(self):
14 | terminals.init()
15 | emissions.init()
16 | underskoar.init(emissions.SC)
17 |
18 | def exceptions(self):
19 |
20 | SC = emissions.SC
21 | SC.cmt_hdr("SkoarException")
22 | SC.class_("SkoarError", "Exception")
23 |
24 | SC.static_method("new", "msg")
25 | SC.return_("super.new(msg)")
26 | SC.end()
27 |
28 | SC.static_method("errorString")
29 | SC.return_('"SKOAR" ++ super.errorString')
30 | SC.end()
31 |
32 | SC.end()
33 |
34 | def base_token(self):
35 | underskoar.skoarToke()
36 |
37 | def EOF_token(self):
38 | underskoar.EOF_token()
39 |
40 | def whitespace_token(self):
41 | underskoar.whitespace_token()
42 |
43 | def typical_token(self, token):
44 | underskoar.typical_token(token)
45 |
46 | def test_SC_lexer(self):
47 |
48 | print(os.getcwd())
49 | fd = open("SuperCollider/Skoar/lex.sc", mode="w")
50 |
51 | emissions.SC.fd = fd
52 | emissions.SC.file_header("lex", "Code_Sc_Lexer")
53 |
54 | self.exceptions()
55 | self.base_token()
56 | self.whitespace_token()
57 | self.EOF_token()
58 |
59 | emissions.SC.cmt_hdr("Everyday Tokes")
60 | for token in terminals.tokens.values():
61 | if token not in terminals.odd_balls:
62 | self.typical_token(token)
63 |
64 | fd.close()
--------------------------------------------------------------------------------
/Skoarcery/factoary/Code_Parser_Py.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from Skoarcery import langoids, terminals, nonterminals, dragonsets, parsetable, emissions
3 | from Skoarcery.langoids import Terminal, Nonterminal
4 |
5 |
6 | class Code_Parser_Py(unittest.TestCase):
7 |
8 | def setUp(self):
9 | terminals.init()
10 | nonterminals.init()
11 | langoids.init()
12 | dragonsets.init()
13 | parsetable.init()
14 | emissions.init()
15 |
16 | def test_PY_rdpp(self):
17 | from Skoarcery.dragonsets import FIRST, FOLLOW
18 | from Skoarcery.terminals import Empty
19 |
20 | fd = open("SkoarPyon/rdpp.py", "w")
21 | PY = emissions.PY
22 | PY.fd = fd
23 |
24 | # Header
25 | # Imports
26 | # class SkoarParseException
27 | # class SkoarParser:
28 | # __init__
29 | # fail
30 | self.code_start()
31 |
32 | PY.tab += 1
33 | N = nonterminals.nonterminals.values()
34 |
35 | # precompute desirables
36 | PY.method("init_desirables")
37 | for A in N:
38 |
39 | R = A.production_rules
40 |
41 | PY.nl()
42 | PY.cmt(str(A))
43 |
44 | # each production
45 | for P in R:
46 |
47 | if P.derives_empty:
48 | continue
49 |
50 | # A -> alpha
51 | alpha = P.production
52 |
53 | desires = FIRST(alpha)
54 |
55 | if Empty in desires:
56 | desires.discard(Empty)
57 | desires.update(FOLLOW(A))
58 |
59 | i = 0
60 |
61 | n = len(desires)
62 | PY.dict_set("self.desirables", str(P), "[", end="")
63 | for toke in desires:
64 | PY.raw(toke.toker_name)
65 | i += 1
66 | if i != n:
67 | if i % 5 == 0:
68 | PY.raw(",\n")
69 | PY.stmt(" ", end="")
70 | else:
71 | PY.raw(", ")
72 |
73 | else:
74 | PY.raw("]\n")
75 |
76 | PY.end()
77 |
78 | # write each nonterminal as a function
79 | for A in N:
80 |
81 | R = A.production_rules
82 |
83 | #PY.cmt(str(A))
84 | PY.stmt("def " + A.name + "(self, parent):")
85 | PY.tab += 1
86 | PY.stmt("self.tab += 1")
87 |
88 | if A.intermediate:
89 | PY.var("noad", "parent")
90 | else:
91 | PY.var("noad", PY.v_new("SkoarNoad", PY.v_sym(A.name), "parent"))
92 |
93 | PY.nl()
94 |
95 | #PY.code_line("print('" + A.name + "')")
96 |
97 | for P in R:
98 |
99 | if P.derives_empty:
100 | continue
101 |
102 | # A -> alpha
103 | alpha = P.production
104 |
105 | PY.stmt("desires = " + PY.v_dict_get("self.desirables", str(P)))
106 |
107 | PY.if_("self.toker.sees(desires)")
108 |
109 | #PY.print(str(P))
110 |
111 | for x in alpha:
112 | if isinstance(x, Terminal):
113 | PY.stmt("noad.add_toke('" + x.toker_name + "', self.toker.burn(" + x.toker_name + "))")
114 |
115 | #PY.print("burning: " + x.name)
116 | else:
117 | if x.intermediate:
118 | PY.stmt("self." + x.name + "(noad)")
119 | else:
120 | PY.stmt("noad.add_noad(self." + x.name + "(noad))")
121 | else:
122 | PY.return_("noad")
123 | PY.tab -= 1
124 | PY.nl()
125 |
126 | if A.derives_empty:
127 | PY.cmt("")
128 | #PY.print("burning empty")
129 | PY.return_("noad")
130 |
131 | else:
132 | PY.cmt("Error State")
133 | PY.stmt("self.fail()")
134 |
135 | PY.tab -= 1
136 | PY.nl()
137 |
138 | PY.tab -= 1
139 |
140 | fd.close()
141 |
142 | def code_start(self):
143 | from Skoarcery.terminals import Empty
144 |
145 | PY = emissions.PY
146 |
147 | PY.file_header("rdpp", "PyRDPP - Create Recursive Descent Predictive Parser")
148 | s = "from Skoarcery.SkoarPyon.apparatus import SkoarNoad\n"\
149 | "from Skoarcery.SkoarPyon.lex import "
150 | T = terminals.tokens.values()
151 | n = len(T)
152 | i = 0
153 | for t in T:
154 | if t == Empty:
155 | n -= 1
156 | continue
157 | s += t.toker_name
158 | i += 1
159 | if i < n:
160 | if i % 5 == 0:
161 | s += ", \\\n "
162 | else:
163 | s += ", "
164 |
165 | PY.raw(s + """
166 |
167 |
168 | class SkoarParseException(Exception):
169 | pass
170 |
171 |
172 | class SkoarParser:
173 |
174 | def __init__(self, runtime):
175 | self.runtime = runtime
176 | self.toker = runtime.toker
177 | self.tab = 0
178 | self.desirables = dict()
179 | self.init_desirables()
180 |
181 | def fail(self):
182 | self.toker.dump()
183 | raise SkoarParseException
184 |
185 | @property
186 | def tabby(self):
187 | if self.tab == 0:
188 | return ""
189 |
190 | return ("{:>" + str(self.tab * 2) + "}").format(" ")
191 |
192 | def print(self, line, end):
193 | print(self.tabby + line, end=end)
194 |
195 |
196 | """)
197 |
--------------------------------------------------------------------------------
/Skoarcery/factoary/Code_Parser_Sc.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from Skoarcery import langoids, terminals, nonterminals, dragonsets, parsetable, emissions
3 | from Skoarcery.langoids import Terminal, Nonterminal
4 |
5 |
6 | class Code_Parser_Sc(unittest.TestCase):
7 |
8 | def setUp(self):
9 | terminals.init()
10 | nonterminals.init()
11 | langoids.init()
12 | dragonsets.init()
13 | parsetable.init()
14 | emissions.init()
15 |
16 | def test_SC_rdpp(self):
17 | from Skoarcery.dragonsets import FIRST, FOLLOW
18 | from Skoarcery.terminals import Empty
19 |
20 | fd = open("SuperCollider/Skoar/rdpp.sc", "w")
21 | ____SC = SC = emissions.SC
22 | SC.fd = fd
23 |
24 | # Header
25 | # Imports
26 | # class SkoarParseException
27 | # class SkoarParser:
28 | # init
29 | # fail
30 | self.code_start()
31 |
32 | SC.tab += 1
33 | N = nonterminals.nonterminals.values()
34 |
35 | # precompute desirables
36 | SC.method("init_desirables")
37 | for A in N:
38 |
39 | R = A.production_rules
40 |
41 | SC.nl()
42 | SC.cmt(str(A))
43 |
44 | # each production
45 | for P in R:
46 |
47 | if P.derives_empty:
48 | continue
49 |
50 | # A -> alpha
51 | alpha = P.production
52 |
53 | desires = FIRST(alpha)
54 |
55 | if Empty in desires:
56 | desires.discard(Empty)
57 | desires.update(FOLLOW(A))
58 |
59 | i = 0
60 |
61 | n = len(desires)
62 | SC.dict_set("desirables", str(P), "[", end="")
63 | for toke in desires:
64 | SC.raw(toke.toker_name)
65 | i += 1
66 | if i != n:
67 | if i % 5 == 0:
68 | SC.raw(",\n")
69 | SC.stmt(" ", end="")
70 | else:
71 | SC.raw(", ")
72 |
73 | else:
74 | SC.raw("]);\n")
75 |
76 | SC.end()
77 |
78 | # write each nonterminal as a function
79 | for A in N:
80 |
81 | R = A.production_rules
82 |
83 | #SC.cmt(str(A))
84 | SC.method(A.name, "parent")
85 |
86 | if A.intermediate:
87 | SC.var("noad", "parent")
88 | else:
89 | SC.var("noad", SC.v_new("SkoarNoad", SC.v_sym(A.name), "parent"))
90 |
91 | SC.var("desires", SC.null)
92 | SC.nl()
93 |
94 | SC.stmt("deep = deep + 1")
95 | SC.if_("deep > 100")
96 | ____SC.stmt("this.fail_too_deep")
97 | SC.end_if()
98 |
99 | # each production
100 | for P in R:
101 |
102 | if P.derives_empty:
103 | continue
104 |
105 | # A -> alpha
106 | alpha = P.production
107 |
108 | SC.stmt("desires = " + SC.v_dict_get("desirables", str(P)))
109 |
110 | SC.cmt(str(P))
111 |
112 | SC.if_("toker.sees(desires).notNil")
113 |
114 | # debugging
115 | #SC.print(str(P))
116 |
117 | for x in alpha:
118 | if isinstance(x, Terminal):
119 | SC.stmt('noad.add_toke(' + SC.v_sym(x.toker_name) + ', toker.burn(' + x.toker_name + '))')
120 |
121 | # debugging
122 | #SC.print("burning: " + x.name)
123 | else:
124 | if x.intermediate:
125 | SC.stmt(SC.this + "." + x.name + "(noad)")
126 | else:
127 | SC.stmt("noad.add_noad(this." + x.name + "(noad))")
128 | else:
129 | SC.stmt("deep = deep - 1")
130 | SC.return_("noad")
131 |
132 | SC.end_if()
133 |
134 | if A.derives_empty:
135 | SC.cmt("")
136 |
137 | # debugging
138 | #SC.print("burning empty")
139 |
140 | SC.stmt("deep = deep - 1")
141 | SC.return_("noad")
142 |
143 | else:
144 | SC.cmt("Error State")
145 | SC.stmt("this.fail")
146 |
147 | SC.end()
148 |
149 | SC.end()
150 |
151 | fd.close()
152 |
153 | def code_start(self):
154 | SC = emissions.SC
155 | SC.file_header("rdpp", "Code_Parser_Sc - Create Recursive Descent Predictive Parser")
156 | SC.raw("""
157 | SkoarParseException : Exception {
158 |
159 | }
160 |
161 | SkoarParser {
162 |
163 | var 50} {}".format(str(N), str(X)))
36 |
37 | def test_follow(self):
38 |
39 | print("\n\n ==========--------( FOLLOW sets )--------------------------------------------------------========\n\n")
40 |
41 | dragonsets.compute_follows()
42 |
43 | X = list()
44 | for K in dragonsets.FOLLOW.D.keys():
45 | X.append(K)
46 |
47 | X.sort()
48 |
49 | for K in X:
50 | FK = dragonsets.FOLLOW(K)
51 |
52 | self.assertGreater(len(FK), 0)
53 |
54 | print("{:>50} {}".format(str(K), str(FK)))
55 |
56 |
--------------------------------------------------------------------------------
/Skoarcery/laboaratoary/TestNonterminals.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from Skoarcery import dragonsets, terminals, nonterminals
3 |
4 |
5 | class TestNonterminals(unittest.TestCase):
6 |
7 | def setUp(self):
8 | terminals.init()
9 | nonterminals.init()
10 |
11 | def tearDown(self):
12 | pass
13 |
14 |
15 | def test_unused(self):
16 | T = terminals.tokens
17 | N = nonterminals.nonterminals
18 |
19 | unused = []
20 |
21 | skip = [N["skoar"]]
22 |
23 | for x in N.values():
24 |
25 | if x in skip:
26 | continue
27 |
28 | # should be on the right side of some production
29 | uses = False
30 | for n in N.values():
31 | uses |= 0 < len([p for p in n.production_rules if x in p.production])
32 |
33 | if not uses:
34 | unused.append(x.name)
35 |
36 | if unused:
37 | print("-------( Unused Nonterminals ) ------------\n")
38 | for untoked in unused:
39 | print(untoked)
40 | print("")
41 |
42 | self.fail("Unused Nonterminals: " + str(len(unused)))
43 |
44 |
45 |
46 | def test_undefined(self):
47 | T = terminals.tokens
48 | N = nonterminals.nonterminals
49 |
50 | undefined = set()
51 |
52 | # verify everything on the right side is defined
53 | for x in N.values():
54 |
55 | for p in x.production_rules:
56 |
57 | for y in p.production:
58 |
59 | if not (y in N.values() or y in T.values()):
60 |
61 | undefined.add(y)
62 |
63 | if len(undefined) > 0:
64 | print("-------( Undefined langoids in productions ) ------------\n")
65 | for x in undefined:
66 | print(x.name)
67 | print("")
68 |
69 | self.fail("Unused Nonterminals: " + str(len(undefined)))
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/Skoarcery/laboaratoary/TestParseTable.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from Skoarcery import langoids, terminals, nonterminals, dragonsets
3 | from Skoarcery.langoids import Terminal
4 |
5 |
6 | class Verify_LL_1(unittest.TestCase):
7 |
8 | def setUp(self):
9 | terminals.init()
10 | nonterminals.init()
11 | langoids.init()
12 | dragonsets.init()
13 | pass
14 |
15 | def tearDown(self):
16 | pass
17 |
18 | # Dragon Spell: 4.4 Construction of a predictive parsing table
19 | def test_make_table(self):
20 | from collections import defaultdict
21 | from Skoarcery.dragonsets import FIRST, FOLLOW
22 | from Skoarcery.terminals import Empty, EOF
23 |
24 | # M[ Nonterm, Term ] = Production
25 | M = defaultdict(dict)
26 |
27 | duplicates = 0
28 | # (1) For each production A -> alpha
29 | #
30 | print("for each production P = A -> alpha:")
31 | for A in nonterminals.nonterminals.values():
32 | M[A] = []
33 | for P in A.production_rules:
34 |
35 | alpha = P.production
36 | print("\n P = " + str(P))
37 |
38 | #
39 | # (2)
40 | #
41 | print(" for a in FIRST(alpha):")
42 | for a in FIRST(alpha):
43 |
44 | if a != Empty:
45 | X = M[A, a]
46 |
47 | if X:
48 | print("")
49 | print(" #### Grammar is not LL(1). Whoopsiedaisies. ####-----------------------")
50 | print("")
51 | print(" M[{}, {}]:".format(A.name, a.name))
52 | print(" " + str(X))
53 | print(" " + str(P))
54 | print("")
55 |
56 | #print("X = {}\nP = {}\nA = {}\na = {}".format(str(X), str(P), str(A), str(a)))
57 | duplicates += 1
58 |
59 | print(" M[A,a] = M[{}, {}] = P".format(A.name, a.name))
60 | M[A, a] = P
61 |
62 | # (3)
63 | else:
64 |
65 | print(" , so for b in FOLLOW(A):")
66 | for b in FOLLOW(A):
67 | X = M[A, b]
68 |
69 | if X:
70 |
71 | print("")
72 | print(" #### Grammar is not LL(1). Whoopsiedaisies. ####-----------------------")
73 | print("")
74 | print(" M[{}, {}]:".format(A.name, b.name))
75 | print(" " + str(X))
76 | print(" " + str(P))
77 | print("")
78 |
79 | #print("X = {}\nP = {}\nA = {}\nb = {}".format(str(X), str(P), str(A), str(b)))
80 | #raise AssertionError("3) Grammar is not LL(1). Fuck.")
81 | duplicates += 1
82 |
83 | print(" M[A,b] = M[{}, {}] = P".format(A.name, b.name))
84 | M[A, b] = P
85 |
86 | self.assertTrue(duplicates is 0, str(duplicates) + " duplicate entries: Grammar is not LL(1).")
87 |
--------------------------------------------------------------------------------
/Skoarcery/laboaratoary/TestTerminals.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from Skoarcery import dragonsets, terminals, nonterminals
3 |
4 |
5 | class TestTokens(unittest.TestCase):
6 |
7 | def setUp(self):
8 | terminals.init()
9 | nonterminals.init()
10 |
11 | def tearDown(self):
12 | pass
13 |
14 | def tes_input(self):
15 | print("\n\n ==========--------( Tokens: Input )--------------------------------------------------========\n\n")
16 | print(terminals.src)
17 |
18 | def test_sorted(self):
19 | print("\n\n ==========--------( Tokens: Created )--------------------------------------------------========\n\n")
20 | L = terminals.list_of_names
21 |
22 | L.sort()
23 |
24 | i = 0
25 | for T in L:
26 | i += 1
27 | print("{:>16}".format(T), end=('\n' if ((i % 7) == 0) else ' '))
28 |
29 | print("\n")
30 |
31 | def test_untoked(self):
32 | T = terminals.tokens
33 | N = nonterminals.nonterminals
34 |
35 | unused = []
36 |
37 | skip = [terminals.Empty, terminals.EOF, terminals.Whitespace]
38 |
39 | for t in T.values():
40 |
41 | if t in skip:
42 | continue
43 |
44 | uses = []
45 | for n in N.values():
46 | uses.extend([p for p in n.production_rules if t in p.production])
47 |
48 | if len(uses) is 0:
49 | unused.append(t.name)
50 |
51 | if unused:
52 | print("-------( Untoked ) ------------\n")
53 | for untoked in unused:
54 | print(untoked)
55 | print("")
56 |
57 | self.fail("Untoked tokens: " + str(len(unused)))
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/Skoarcery/laboaratoary/Test_Sclang.py:
--------------------------------------------------------------------------------
1 |
2 | import unittest
3 | from subprocess import Popen, PIPE
4 | import subprocess
5 | import json
6 |
7 |
8 | class Test_Sclang(unittest.TestCase):
9 |
10 | #home = "/p/supercollider/build/Install/SuperCollider/SuperCollider.app/Contents/Resources/"
11 | #home = "C:\\supercollider\\SuperCollider\\"
12 | #home = "C:\\Users\\lucas\\Documents\\GitHub\\supercollider\\build\\x64\\Release\\SuperCollider\\"
13 | home = "C:\\Users\\lucas\\Documents\\GitHub\\bagong.supercollider\\build_pa\\Install\\SuperCollider\\"
14 |
15 | #sclang = home + "sclang"
16 | sclang = home + "sclang.exe"
17 |
18 | def print(self, msg):
19 | print("sclang: " + msg, end="")
20 |
21 | def exec(self, scd_code_file=None):
22 |
23 | class_lib_compiled = False
24 | class_lib_inited = False
25 | error_seen = False
26 |
27 | a_cmd = [Test_Sclang.sclang, "-D"]
28 |
29 | if scd_code_file:
30 | a_cmd.append(scd_code_file)
31 |
32 |
33 | proc = Popen(a_cmd, stdout=PIPE, stderr=subprocess.STDOUT)
34 | while proc.poll() is None:
35 | b = proc.stdout.readline()
36 | line = str(b, encoding="utf-8")
37 | self.print(line)
38 |
39 | #
40 | # yay
41 | if line.startswith("Class tree inited in"):
42 | class_lib_inited = True
43 |
44 | if line.startswith("compile done"):
45 | class_lib_compiled = True
46 |
47 | #
48 | # nay
49 | if line.startswith("-----------------------------------"):
50 | error_seen = True
51 | break
52 |
53 | #
54 | # complete
55 | if line.find("Welcome to SuperCollider") != -1:
56 | break
57 |
58 | self.assertFalse(error_seen, "Errors compiling class library.")
59 | self.assertTrue(class_lib_compiled, "Class library didn't compile.")
60 | self.assertTrue(class_lib_inited, "Class libarary did initialize.")
61 |
62 | failures = []
63 | tests_passed = False
64 | while proc.poll() is None:
65 | b = proc.stdout.readline()
66 | line = str(b, encoding="utf-8")
67 | self.print(line)
68 |
69 | #
70 | # yay
71 | if line.startswith("SKOAR PASS"):
72 | tests_passed = True
73 | break
74 |
75 | #
76 | # nay
77 | if line.startswith("SKOAR FAIL"):
78 | tests_passed = False
79 | failures.append(line)
80 | break
81 |
82 | if line.startswith("FAIL"):
83 | #tests_passed = False
84 | failures.append(line)
85 | break
86 | #
87 | # nay
88 | if line.startswith("^^ The preceding error dump"):
89 | tests_passed = False
90 | break
91 |
92 | try:
93 | proc.terminate()
94 | finally:
95 | proc.stdout.close()
96 |
97 | if not tests_passed:
98 | print("JSON: " + json.dumps({"test": scd_code_file, "failures": failures}, separators=(',', ': ')))
99 | #print(str(a_cmd))
100 | #for line in failures:
101 | # self.print(line)
102 |
103 | self.assertTrue(tests_passed, "scland unit tests failed.")
104 |
105 |
106 | class Test_Sclang_Sanity(Test_Sclang):
107 |
108 | def test_SC_sanity(self):
109 | self.exec("SuperCollider/testing/sanity.scd")
110 |
111 | def test_SC_cats(self):
112 | self.exec("SuperCollider/testing/cats.scd")
113 |
114 | def test_SC_ops(self):
115 | self.exec("SuperCollider/testing/ops.scd")
116 |
117 | def test_SC_noaty(self):
118 | self.exec("SuperCollider/testing/noaty.scd")
119 |
120 | def test_SC_levels(self):
121 | self.exec("SuperCollider/testing/levels.scd")
122 |
123 |
124 | class Test_Sclang_Dev(Test_Sclang):
125 | def test_SC_ops_dev(self):
126 | self.exec("SuperCollider/testing/ops_dev.scd")
127 |
128 | def test_SC_dev(self):
129 | self.exec("SuperCollider/testing/dev.scd")
130 |
131 | def test_SC_increments(self):
132 | self.exec("SuperCollider/testing/increments.scd")
133 |
--------------------------------------------------------------------------------
/Skoarcery/langoids.py:
--------------------------------------------------------------------------------
1 |
2 | def init():
3 | print("langoids initialized.")
4 |
5 |
6 | class Production:
7 |
8 | def __init__(self, name, list_of_langoids):
9 | from Skoarcery.terminals import Empty
10 |
11 | self.name = name
12 | self.production = list_of_langoids
13 | self.derives_empty = self.first == Empty
14 |
15 | def __str__(self):
16 | s = self.name + " ->"
17 |
18 | for alpha in self.production:
19 | s += " " + alpha.name
20 |
21 | return s
22 |
23 | @property
24 | def first(self):
25 | return self.production[0]
26 |
27 |
28 | class Langoid:
29 |
30 | def __init__(self, name):
31 | self.name = name
32 | self.derives_empty = False
33 |
34 | def __hash__(self):
35 | return hash(self.name)
36 |
37 | def __eq__(self, other):
38 | return self.name == other.name
39 |
40 | def __str__(self):
41 | return self.name
42 |
43 | def __repr__(self):
44 | return self.name
45 |
46 | def __index__(self):
47 | return self.name
48 |
49 |
50 | class Terminal(Langoid):
51 |
52 | def __init__(self, name, regex):
53 | super().__init__(name)
54 |
55 | self.regex = regex
56 |
57 | if name == "":
58 | self.derives_empty = True
59 |
60 | def __str__(self):
61 | return "T_" + self.name
62 |
63 | @property
64 | def toker_name(self):
65 | return "Toke_" + self.name
66 |
67 |
68 | class Nonterminal(Langoid):
69 |
70 | def __init__(self, name):
71 | super().__init__(name)
72 |
73 | # list of productions
74 | self.production_rules = []
75 | self.first = set()
76 | self.follow = set()
77 | self.derives_empty = False
78 | self.intermediate = False
79 | self.has_semantics = False
80 |
81 | def add_production(self, p):
82 |
83 | o = Production(self.name, p)
84 |
85 | if o.derives_empty:
86 | self.derives_empty = True
87 |
88 | self.production_rules.append(o)
89 |
90 | def __repr__(self):
91 | return "N_" + self.name
92 |
93 |
94 |
--------------------------------------------------------------------------------
/Skoarcery/nonterminals.py:
--------------------------------------------------------------------------------
1 | src = """
2 | #
3 | # Skoar Nonterminals
4 | #
5 | # like_this for nonterminals, LikeThis for terminals
6 | #
7 | # is the empty string
8 | #
9 | # + before a nonterminal indicates this is an intermediate step that can be
10 | # skipped in the constructed parse tree, it will not create a new skoarnode,
11 | # instead appending its noads to its parent's children list.
12 |
13 |
14 | skoar : branches
15 | +branches : branch branches |
16 | branch : optional_voice phrases Newline
17 | +optional_voice : Voice |
18 |
19 | +phrases : phrasey phrases |
20 | +phrasey : Comment | marker | Meter | expr | dal_goto | beat
21 |
22 | skoarpion : SkoarpionStart skrp_sig skrp_suffix
23 | skrp_sig : ArgSpec SkoarpionSep | SymbolName opt_arg_spec SkoarpionSep |
24 | opt_arg_spec : ArgSpec |
25 | skrp_suffix : skrp_lines SkoarpionEnd
26 |
27 | +skrp_lines : optional_voice phrases skrp_moar_lines
28 | +skrp_moar_lines : Newline skrp_lines |
29 |
30 | listy : ListS listy_suffix
31 | +listy_suffix : listy_entries ListE | ListE
32 | +listy_entries : expr moar_listy_entries
33 | +moar_listy_entries: ListSep listy_entries | Newline |
34 |
35 | marker : Segno | Fine | coda | Volta | Bars
36 | coda : Coda optional_al_coda
37 | optional_al_coda : AlCoda |
38 | dal_goto : DaCapo al_x | DalSegno al_x
39 | al_x : AlCoda | AlSegno | AlFine |
40 |
41 | beat : Crotchets | Quavers | Quarters | Eighths | Slash
42 |
43 | musical_keyword : dynamic | ottavas | musical_keyword_misc
44 | musical_keyword_misc : Rep | Portamento | Carrot
45 | ottavas : OctaveShift | OttavaA | OttavaB | QuindicesimaA | QuindicesimaB | Loco
46 | dynamic : DynPiano | DynForte | DynSFZ | DynFP
47 |
48 | nouny : cthulhu | cuts | conditional | loop | nouny_literal | musical_keyword | listy | deref | skoarpion
49 | +nouny_literal : UGen | Tuplet | Caesura | Freq | Int | Float | String | Choard | NamedNoat | Symbol | Fairy | HashLevel | False | True | Cat
50 |
51 | deref : Deref deref_prime
52 | +deref_prime : MsgNameWithArgs listy_suffix | MsgName
53 |
54 | expr : SymbolColon expr | msgable expr_prime
55 | expr_prime : assignment expr_prime | math expr_prime | boolean | times |
56 |
57 | times : Times
58 | boolean : BooleanOp expr
59 | boolean_expr : expr
60 | math* : MathOp msgable
61 | assignment : AssOp settable
62 | +settable : Caesura | Symbol | listy | Quarters | Eighths | Fairy
63 |
64 | msgable : nouny msg_chain_node
65 | +msg_chain_node : MsgOp msg msg_chain_node |
66 | msg : MsgNameWithArgs listy_suffix | MsgName | listy | loop
67 |
68 | cthulhu : LWing Semicolon cthulhu_prime
69 | +cthulhu_prime : boolean_expr Semicolon RWing | Nosey Semicolon RWing
70 |
71 | conditional : CondS cond_ifs CondE
72 | +cond_ifs : cond_if cond_ifs_suffix
73 | +cond_ifs_suffix : Newline cond_ifs |
74 | cond_if : optional_voice boolean_expr CondIf if_body cond_else
75 | +cond_else : CondIf if_body |
76 |
77 | if_body : phrases
78 |
79 | loop : LoopS loop_body loop_condition LoopE
80 | loop_body : phrases
81 | loop_condition : LoopSep boolean_expr |
82 |
83 | cuts : CutsS phrases CutsE
84 |
85 | """
86 |
87 |
88 | SKOAR = None
89 | nonterminals = None
90 |
91 |
92 | def init():
93 | global nonterminals, SKOAR
94 | nonterminals = dict()
95 |
96 | from Skoarcery import terminals
97 | from Skoarcery.langoids import Nonterminal
98 |
99 | # create and track as they appear
100 | def hello(name):
101 |
102 | try:
103 | xoid = nonterminals[name]
104 | except KeyError:
105 | xoid = Nonterminal(name)
106 | nonterminals[name] = xoid
107 |
108 | return xoid
109 |
110 | for bnf_line in src.split("\n"):
111 | if len(bnf_line) == 0 or bnf_line.lstrip().startswith("#"):
112 | continue
113 |
114 | #print(bnf_line)
115 | a = bnf_line.split(":")
116 |
117 | name = a[0].strip()
118 |
119 | if name.startswith("+"):
120 | name = name.lstrip("+")
121 | intermediate = True
122 | else:
123 | intermediate = False
124 |
125 | # i'm not using this, but feel like i ought to be
126 | if name.endswith("*"):
127 | name = name.rstrip("*")
128 | has_semantics = True
129 | else:
130 | has_semantics = False
131 |
132 | for production in a[1].split("|"):
133 |
134 | p = []
135 | for langoid in production.split():
136 |
137 | if len(langoid) == 0:
138 | continue
139 |
140 | toke = terminals.tokens.get(langoid)
141 |
142 | if toke:
143 | p.append(toke)
144 | else:
145 |
146 | if langoid[0].isupper():
147 | raise Exception("Unknown token " + langoid)
148 |
149 | X = hello(langoid)
150 |
151 | p.append(X)
152 |
153 | X = hello(name)
154 | X.intermediate = intermediate
155 | X.has_semantics = has_semantics
156 | X.add_production(p)
157 |
158 | SKOAR = nonterminals["skoar"]
159 |
160 | print("nonterminals initialized.")
161 |
--------------------------------------------------------------------------------
/Skoarcery/parsetable.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from Skoarcery import langoids, terminals, nonterminals, dragonsets
3 | from Skoarcery.langoids import Terminal
4 |
5 |
6 | class Not_LL_1(Exception):
7 | pass
8 |
9 | M = None
10 |
11 |
12 | #
13 | # Dragon Spell: 4.4 Construction of a predictive parsing table
14 | #
15 | def init():
16 | from collections import defaultdict
17 | from Skoarcery.dragonsets import FIRST, FOLLOW
18 | from Skoarcery.terminals import Empty, EOF
19 |
20 | global M
21 |
22 | # M[ Nonterm, Term ] = Production
23 | M = defaultdict(dict)
24 |
25 | # (1) For each production A -> alpha
26 | #
27 | for A in nonterminals.nonterminals.values():
28 |
29 | for P in A.production_rules:
30 |
31 | alpha = P.production
32 |
33 | # (2)
34 | for a in FIRST(alpha):
35 | if a != Empty:
36 | X = M[A, a]
37 |
38 | if X:
39 | raise Not_LL_1
40 |
41 | M[A, a] = P
42 |
43 | # (3)
44 | else:
45 | for b in FOLLOW(A):
46 |
47 | X = M[A, b]
48 |
49 | if X:
50 | raise Not_LL_1
51 |
52 | M[A, b] = P
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/Skoarcery/terminals.py:
--------------------------------------------------------------------------------
1 | src = """
2 | #
3 | # Skoar Tokes
4 | #
5 | # format (at very start of line): TokeName: regex
6 | #
7 | # If token carries information: TokeName*: regex
8 | # - be sure an inspector for TokeName exists
9 | #
10 |
11 | : unused
12 | EOF: unused
13 | Whitespace: [ \\t]*
14 | Newline: [\\n\\r][\\n\\r \\t]*
15 |
16 | True: yes|true
17 | False: no|false
18 | Cat: =\\^\\.\\^=
19 |
20 | Voice*: \\.(([a-zA-Z_][a-zA-Z0-9_]*)?|\\.+)
21 |
22 | Comment: <[?](.|[\\n\\r])*?[?]>
23 |
24 | # careful not to match ottavas ending in (ma,mb,va,vb), or steal from floats
25 | Int*: (-)?(0|[1-9][0-9]*)(?![0-9]*Hz|[mv][ab]|\\.[0-9]|/)
26 | Float*: (-)?(0|[1-9][0-9]*)\\.[0-9]+(?!Hz)
27 |
28 | Freq*: (0|[1-9][0-9]*)(\\.[0-9]+)?Hz
29 |
30 | Meter*: [1-9][0-9]*/[1-9][0-9]*
31 |
32 | ArgSpec: <[a-zA-Z]+(,[a-zA-Z]+)*>
33 |
34 | ListS: <(?![=?])|<(?=[=]\\^\\.)
35 | ListE: >(?![=])
36 | ListSep: ,
37 |
38 | # one ^ but don't eat ^^( which is cthulhu's left wing
39 | Carrot*: \\^(?!\\^[(])
40 | LWing: \\^\\^[(]
41 | RWing: [)]\\^\\^
42 |
43 | Tuplet*: /\\d+(:\\d+)?|(du|tri|quadru)plets?|(quin|sex|sep|oc)tuplets?
44 | Crotchets*: [}]+\\.?
45 | Quavers*: o+/\\.?
46 |
47 | Quarters*: \\.?[)]+(?:__?)?\\.?
48 | Eighths*: \\.?\\]+(?:__?)?\\.?
49 |
50 | Caesura: //
51 | Slash: /(?![/0-9])
52 |
53 | HashLevel: \\[#*[ ]*\\]
54 |
55 |
56 | # we can't allow f for forte as f is a noat, so we allow
57 | #
58 | # forte fforte ffforte ff fff, but not f
59 | #
60 | # for consisentecy, piano, ppiano, pppiano work too.
61 | #
62 | # default velocity:
63 | # ppp (16), pp (32), p (48), mp (64), mf (80), f (96), ff (112), fff (127)
64 |
65 | DynPiano*: (m(ezzo)?p|p+)(iano)?
66 | DynForte*: m(ezzo)?f(orte)?|f+orte|ff+
67 | DynSFZ: sfz
68 | DynFP: fp
69 |
70 | AssOp: =>|[+]>|->|[*]>
71 | MsgOp: \\.(?![)\\]])
72 | MathOp: [+*\\-](?!>)
73 |
74 | NamedNoat*: (?:_?)(?:[a-g](?![ac-zA-Z_]))(#|b)?
75 | Choard*: ~*[ABCDEFG](?![.ce-ln-rt-zA-LN-Z]|a[l ])(#|b)?([Mm0-9]|sus|dim|aug|dom)*(/[A-G][#b]?)?~*
76 |
77 | BooleanOp*: ==|!=|<=|>=|and|or|xor
78 | CondS: [{][?][\\n]*
79 | CondIf: [?][?](?![}])
80 | CondE: [?][}]
81 | Semicolon: ;
82 |
83 | CutsS: [{]=[\\n]*
84 | CutsE: =[}]
85 |
86 | LoopS: [{]:[\\n]*
87 | LoopE: :[}]
88 | LoopSep: ::[\\n]*(?![|])
89 |
90 | Fairy: [$]
91 |
92 | # we do this, because skoaroids can follow skoaroids.
93 | MsgName*: [a-zA-Z_][a-zA-Z0-9_]*(?!<)
94 | MsgNameWithArgs*: [a-zA-Z_][a-zA-Z0-9_]*<
95 |
96 | Symbol*: [\\\\@][a-zA-Z0-9_][a-zA-Z0-9_]*
97 | SymbolName*: [a-zA-Z0-9_][a-zA-Z0-9_]*
98 | SymbolColon*: [a-zA-Z0-9_][a-zA-Z0-9_]*[ \\t]*:(?![:|}])
99 |
100 |
101 | SkoarpionStart: [{]!
102 | SkoarpionEnd: ![}]
103 | SkoarpionSep: !!
104 | Deref: !(?![!}]|=)
105 |
106 | Nosey: ,
107 |
108 | DaCapo: D\\.C\\.|Da Capo
109 | DalSegno: D\\.S\\.|Dal Segno
110 | Fine: fine
111 | Segno*: ,[Ss](?:egno)?`(?:[a-zA-Z_][a-zA-Z0-9_]*`)*
112 | Coda: \\([+]\\)(?:`(?:[a-zA-Z_][a-zA-Z0-9_]*`)*)?
113 | Rep*: %+
114 | AlCoda: al(la)? coda
115 | AlSegno: al segno
116 | AlFine: al fine
117 |
118 | UGen: u[A-Z][A-Za-z0-9_]*
119 | OctaveShift*: ~+o|o~+
120 |
121 | OttavaA: 8va|ottava (alta|sopra)|all' ottava
122 | OttavaB: 8vb|ottava (bassa|sotto)
123 |
124 | QuindicesimaA: 15ma|alla quindicesima
125 | QuindicesimaB: 15mb
126 |
127 | Portamento: port\\.?
128 | Loco: loco
129 | Volta*: \\[\\d+\\.\\]
130 |
131 | # TODO: deal with \"
132 | String*: \'[^']*\'
133 |
134 | Bars*: :?\\|+:?
135 |
136 | Times: [Tt]imes
137 | """
138 |
139 | #
140 | #
141 | #
142 |
143 | list_of_names = None
144 | inspectables = None
145 | tokens = None
146 | Empty = None
147 | EOF = None
148 | Whitespace = None
149 |
150 | odd_balls = None
151 |
152 |
153 | def init():
154 | from Skoarcery.langoids import Terminal
155 | global src, list_of_names, tokens, EOF, Empty, Whitespace, odd_balls, inspectables
156 |
157 | list_of_names = []
158 | inspectables = []
159 | tokens = dict()
160 |
161 | for token_line in src.split("\n"):
162 |
163 | token_line = token_line.strip()
164 | if len(token_line) > 0 and not token_line.startswith("#"):
165 |
166 | (token, v, regex) = token_line.partition(":")
167 |
168 | token = token.strip()
169 | regex = regex.strip()
170 |
171 | if token.endswith("*"):
172 | token = token.rstrip("*")
173 | inspectables.append(token)
174 |
175 | list_of_names.append(token)
176 |
177 | tokens[token] = Terminal(token, regex)
178 |
179 | #print("# tokens initialized.")
180 |
181 | Empty = Terminal("", None)
182 | EOF = Terminal("EOF", None)
183 | Whitespace = tokens["Whitespace"]
184 |
185 | odd_balls = {Empty, EOF, Whitespace}
186 |
187 |
188 |
--------------------------------------------------------------------------------
/Skoarcery/underskoar.py:
--------------------------------------------------------------------------------
1 | from Skoarcery import terminals, emissions
2 |
3 | # underskoarcery :P
4 | _ = _____ = _________ = _____________ = _________________ = _____________________ = None
5 |
6 | # -------
7 | # Symbols
8 | # -------
9 | SkoarToke_ = "SkoarToke"
10 | lexeme_ = "lexeme"
11 | regex_ = "regex"
12 | size_ = "size"
13 | inspectable_ = "inspectable"
14 | burn_ = "burn"
15 | match_ = "match"
16 | buf_ = "buf"
17 | offs_ = "offs"
18 | toke_class_ = "toke_class"
19 | match_toke_ = "match_toke"
20 | s_ = "s"
21 | n_ = "n"
22 | SkoarError_ = "SkoarError"
23 | SubclassResponsibilityError_ = "SubclassResponsibilityError"
24 |
25 |
26 | #
27 | # configure schematics to output a language
28 | # implemented by one of the tongues in emissions
29 | def init(tongue):
30 | global _, _____, _________, _____________, _________________, _____________________
31 | assert tongue in emissions.tongues
32 | _ = _____ = _________ = _____________ = _________________ = _____________________ = tongue
33 |
34 |
35 | def skoarToke():
36 |
37 | regex = toke_class_ + "." + regex_
38 |
39 | _.cmt_hdr("Abstract Token")
40 |
41 | _.abstract_class(SkoarToke_)
42 |
43 | _____.attrvar("<", lexeme_)
44 | _____.attrvar("", size_)
45 |
46 | _____.classvar("<", regex_, _.null)
47 | _____.nl()
48 |
49 | _____.constructor(s_, n_)
50 | _________.stmt(_.v_ass(_.v_attr(lexeme_), s_))
51 | _________.stmt(_.v_ass(_.v_attr(size_), n_))
52 | _____.end()
53 |
54 | _____.cmt("how many characters to burn from the buffer")
55 | _____.method(burn_)
56 | _________.return_(size_)
57 | _____.end()
58 |
59 | _____.cmt("override and return " + _.null + " for no match, new toke otherwise")
60 | _____.abstract_static_method(match_, buf_, offs_)
61 | _________.throw(SubclassResponsibilityError_, _.v_str("What are you doing human?"))
62 | _____.end()
63 |
64 | _____.cmt("match requested toke")
65 | _____.static_method(match_toke_, buf_, offs_, toke_class_)
66 | _________.var(match_)
67 |
68 | if isinstance(_, emissions.ScTongue):
69 | _________.find_regex(match_, regex, buf_, offs_)
70 |
71 | _________.if_(match_ + ".isNil")
72 | _____________.return_(_.null)
73 | _________.end_if()
74 |
75 | _________.return_(_.v_new(toke_class_, "match[0]", "match[1]"))
76 |
77 | else:
78 | _____.try_()
79 | _________.find_regex(match_, regex, buf_, offs_)
80 |
81 | _________.return_(_.v_new(toke_class_, _.v_regex_group_zero(match_)))
82 |
83 | _____.except_any()
84 | _________.nop()
85 | _____.end()
86 |
87 | _____.return_(_.null)
88 |
89 | _____.end()
90 | _.end()
91 |
92 |
93 | def whitespace_token():
94 |
95 | Whitespace = terminals.Whitespace
96 | regex = _.v_def_regex(Whitespace.regex)
97 |
98 | _.cmt_hdr("Whitespace is special")
99 | _.class_(Whitespace.toker_name, SkoarToke_)
100 | _____.classvar("<", regex_, regex)
101 | _____.nl()
102 | _____.static_method(burn_, buf_, offs_)
103 | _________.var(match_)
104 |
105 | if isinstance(_, emissions.ScTongue):
106 | _________.find_regex(match_, Whitespace.toker_name + "." + regex_, buf_, offs_)
107 | _________.if_(match_ + " != " + _.null)
108 | _____________.return_("match[1]")
109 | _________.end_if()
110 |
111 | else:
112 | _____.try_()
113 | _________.find_regex(match_, Whitespace.toker_name + "." + regex_, buf_, offs_)
114 | _________.return_(_.v_length(_.v_regex_group_zero(match_)))
115 | _____.except_any()
116 | _________.nop()
117 | _____.end()
118 |
119 | _________.return_("0")
120 | _____.end()
121 | _.end()
122 |
123 |
124 | def EOF_token():
125 |
126 | EOF = terminals.EOF
127 |
128 | _.cmt_hdr("EOF is special")
129 | _.class_(EOF.toker_name, SkoarToke_)
130 | _____.static_method(burn_, buf_, offs_)
131 | _________.if_(_.v_length(buf_) + " > " + offs_)
132 | _____________.throw(SkoarError_, _.v_str("Tried to burn EOF when there's more input."))
133 | _________.end_if()
134 | _________.return_("0")
135 | _____.end()
136 | _____.static_method(match_, buf_, offs_)
137 | _________.if_(_.v_length(buf_) + " < " + offs_)
138 | _____________.throw(SkoarError_, _.v_str("Tried to burn EOF when there's more input."))
139 | _________.end_if()
140 | _________.if_(_.v_length(buf_) + " == " + offs_)
141 | _____________.return_(_.v_new(EOF.toker_name, ""))
142 | _________.end_if()
143 | _________.return_(_.null)
144 | _____.end()
145 | _.end()
146 |
147 |
148 | def typical_token(token):
149 |
150 | #inspectable = _.true if token.name in terminals.inspectables else _.false
151 |
152 | _.class_(token.toker_name, SkoarToke_)
153 | _____.classvar("<", regex_, _.v_def_regex(token.regex))
154 | #_____.classvar("<", inspectable_, inspectable)
155 | _____.nl()
156 | _____.static_method(match_, buf_, offs_)
157 | _________.return_(SkoarToke_ + "." + match_toke_ + "(" + buf_ + ", " + offs_ + ", " + token.toker_name + ")")
158 | _____.end()
159 | _.end()
160 |
161 |
--------------------------------------------------------------------------------
/SuperCollider/Skoar/apparatus.sc:
--------------------------------------------------------------------------------
1 | // ==========================
2 | // The Parse Tree - SkoarNoad
3 | // ==========================
4 | SkoarNoad {
5 |
6 | var address; // a list code to find the noad quickly
7 | var <>parent; // the parent noad
8 | var <>children; // a list of child noads
9 |
10 | var <>name; // name of the nonterminal (a \symbol)
11 | var <>skoarpuscle; // skoarpuscle types go here
12 | var <>toke;
13 |
14 | var <>on_enter;
15 | var <>one_shots; // function to set for stuff that appFalse for one beat.
16 |
17 | var <>voice; // what voice to use
18 | var <>skoap; // what skoap are we in
19 |
20 | *new {
21 | | name, parent=nil |
22 | ^super.new.init(name, parent);
23 | }
24 |
25 | init {
26 | | nameArg, parentArg |
27 |
28 | parent = parentArg;
29 | name = nameArg;
30 |
31 | children = List[];
32 | address = [];
33 | }
34 |
35 | asString {
36 | var ns = name.asString;
37 |
38 | if (skoarpuscle.notNil) {
39 | ns = ns ++ ": " ++ skoarpuscle.asString
40 | };
41 | ^ns;
42 | }
43 |
44 | // here we return a copy, as whomever uses it is likely going to start
45 | // popping numbers off of it.
46 | address {
47 | ^Array.newFrom(address);
48 | }
49 |
50 | // -------------------
51 | // decorating the tree
52 | // -------------------
53 | decorate_zero {
54 | | v, s, parent_address, i=0 |
55 |
56 | if (voice.isNil) {
57 | voice = v;
58 | } {
59 | // the voice has changed, this is what the children get
60 | v = voice;
61 | };
62 |
63 | address = [];
64 | skoap = s;
65 |
66 | i = 0;
67 | children.do {
68 | | y |
69 | y.decorate(v, s, address, i);
70 | i = i + 1;
71 | };
72 |
73 | }
74 |
75 | decorate {
76 | | v, s, parent_address, i=0 |
77 |
78 | if (voice.isNil) {
79 | voice = v;
80 | } {
81 | // the voice has changed, this is what the children get
82 | v = voice;
83 | };
84 |
85 | address = [i] ++ parent_address;
86 | skoap = s;
87 |
88 | i = 0;
89 | children.do {
90 | | y |
91 | y.decorate(v, s, address, i);
92 | i = i + 1;
93 | };
94 |
95 | }
96 |
97 | // ----------------
98 | // growing the tree
99 | // ----------------
100 | add_noad {
101 | | noad |
102 | children = children.add(noad);
103 | }
104 |
105 | add_toke {
106 | | name, t |
107 | var x = SkoarNoad(t.class.name, this);
108 | x.toke = t;
109 | children = children.add(x);
110 | }
111 |
112 | // ----------------
113 | // showing the tree
114 | // ----------------
115 | draw_tree {
116 | | tab = 1 |
117 | var n = 16;
118 | var s;
119 | var sa = skoap.asString ++ ":";
120 | var sv;
121 |
122 | address.reverseDo {
123 | | x |
124 | sa = sa ++ x.asString ++ ";";
125 | };
126 |
127 | sv = if (voice.notNil) {
128 | voice.name.asString.padLeft(n) ++ ":"
129 | } {
130 | ":".padLeft(n+1)
131 | };
132 |
133 | s = sa.padRight(n) ++ sv ++ " ".padLeft(tab) ++ name;
134 |
135 | if (skoarpuscle.notNil) {
136 | s = s ++ ": " ++ skoarpuscle.val;
137 | };
138 |
139 | s = s ++ "\n";
140 | children.do {
141 | | x |
142 | s = if (x.isKindOf(SkoarNoad)) {
143 | s ++ x.draw_tree(tab + 1)
144 | } {
145 | s ++ " ".padLeft(tab + 1) ++ x.class.asString ++ "\n"
146 | };
147 | };
148 |
149 | ^s;
150 | }
151 |
152 | // -----------------
153 | // climbing the Tree
154 | // -----------------
155 |
156 | // depth-first, find the leaves, run handler, working towards trunk
157 | //
158 | // if it's crashing during the decorating stage, here's a good place to
159 | // start debugging
160 | depth_visit {
161 | | f |
162 | //var s = " " ++ if (toke.notNil) {toke.lexeme} {""};
163 | //debug(">>> depth_visit: " ++ name ++ s);
164 |
165 | children.do {
166 | | y |
167 | y.depth_visit(f);
168 | };
169 |
170 | //debug("--- depth_visit: " ++ name ++ s);
171 |
172 | // note: leaves first
173 | f.(this);
174 |
175 | //debug("<<< depth_visit: " ++ name ++ s);
176 | }
177 |
178 | inorder {
179 | | f |
180 |
181 | //debug(">>> inorder: " ++ name);
182 |
183 | f.(this);
184 |
185 | children.do {
186 | | y |
187 | y.inorder(f);
188 | };
189 |
190 | //debug("<<< inorder: " ++ name);
191 | }
192 |
193 | // debug here if it's crashing while performing the skoar
194 | inorder_from_here {
195 | | here, f |
196 | var j = here.pop;
197 | var n = children.size - 1;
198 |
199 | //debug("inorder_from_here: j:" ++ j ++ " " ++ name);
200 |
201 | if (j.isNil) {
202 | this.inorder(f);
203 | } {
204 | children[j].inorder_from_here(here, f);
205 |
206 | j = j + 1;
207 | if (j <= n) {
208 | for (j, n, {
209 | | k |
210 | children[k].inorder(f);
211 | });
212 | };
213 | };
214 | }
215 |
216 | // expect skoarpuscle
217 | next_skoarpuscle {
218 | var x;
219 |
220 | if (skoarpuscle.notNil) {
221 | ^skoarpuscle;
222 | };
223 |
224 | x = children[0];
225 |
226 | if (x.notNil) {
227 | ^x.next_skoarpuscle;
228 | };
229 |
230 | ^nil;
231 | }
232 |
233 | next_toke {
234 | var x;
235 |
236 | if (toke.notNil) {
237 | ^toke;
238 | };
239 |
240 | x = children[0];
241 |
242 | if (x.notNil) {
243 | ^x.next_toke;
244 | };
245 |
246 | ^nil;
247 | }
248 |
249 | // -------------------
250 | // performing the tree
251 | // -------------------
252 | enter_noad {
253 | | minstrel, nav |
254 |
255 | if (on_enter.notNil) {
256 | on_enter.(minstrel, nav);
257 | };
258 |
259 | if (skoarpuscle.notNil and: skoarpuscle.respondsTo(\on_enter)) {
260 | skoarpuscle.on_enter(minstrel, nav);
261 | };
262 | }
263 |
264 | // ------------------
265 | // searching the tree
266 | // ------------------
267 |
268 | // desires - array of names of noads as symbol, or SkoarToke implementation classes
269 | // writer - a function that will do something with the matches
270 | match {
271 | | desires, writer |
272 |
273 | desires.do {
274 | | item |
275 |
276 | if (item == name) {
277 | writer.(this);
278 | };
279 | };
280 | }
281 |
282 | collect {
283 | | desires |
284 |
285 | var results = List.new;
286 |
287 | this.depth_visit({
288 | | x |
289 | x.match(desires, {
290 | | y |
291 | results.add(y);
292 | });
293 | });
294 |
295 | ^results.asArray;
296 | }
297 |
298 | collect_skoarpuscles {
299 | | j=0 |
300 |
301 | var results = List.new;
302 | while {j < children.size} {
303 |
304 | children[j].inorder({
305 | | x |
306 | if (x.skoarpuscle.notNil) {
307 | //debug("found skoarpuscle: " ++ x.skoarpuscle.asString);
308 | results.add(x.skoarpuscle);
309 | };
310 | });
311 |
312 | j = j + 1;
313 | };
314 | ^results.asArray;
315 |
316 | }
317 |
318 | }
319 |
320 |
321 |
322 |
--------------------------------------------------------------------------------
/SuperCollider/Skoar/beaty.sc:
--------------------------------------------------------------------------------
1 |
2 | SkoarpuscleBeat : Skoarpuscle {
3 |
4 | var "
30 |
31 | all_voice = skr.all_voice;
32 |
33 | skoarpion = skoar.tree.next_skoarpuscle.val;
34 |
35 | event_stream = Routine({
36 | var running = true;
37 | var nav_result = nil;
38 |
39 | while {running} {
40 |
41 | nav_result = block {
42 | | nav |
43 | koar.do_skoarpion(skoarpion, this, nav, nil, nil);
44 | nav.(\nav_done);
45 | };
46 |
47 | switch (nav_result)
48 |
49 | {\nav_done} { running = false; }
50 | {\nav_fine} { running = false; }
51 |
52 | {\nav_da_capo} {
53 | //"Da Capo time.".postln;
54 | // do nothing, will enter skoarpion again
55 | }
56 |
57 | {\nav_colon} {
58 | // do nothing, will enter skoarpion again
59 | }
60 |
61 | {
62 | SkoarError("Unhandled nav: " ++ nav_result).throw;
63 | };
64 |
65 | };
66 |
67 | //("Minstrel " ++ koar.name ++ " done.").postln;
68 | });
69 |
70 | }
71 |
72 | nextEvent {
73 | ^event_stream.next;
74 | }
75 |
76 | pfunk {
77 | ^Pfunc({this.nextEvent;});
78 | }
79 |
80 | reset_colons {
81 | fairy.forget_that_you_have_seen(SkoarpuscleBars);
82 | koar.state_put(\colons_burned, Dictionary.new;);
83 | }
84 |
85 | }
86 |
87 | // ----------------------------------
88 | // Skoarchestra - A band of minstrels
89 | // ----------------------------------
90 | Skoarchestra {
91 |
92 | var minstrels;
93 |
94 | *new {
95 | | skoar |
96 | ^super.new.init(skoar);
97 | }
98 |
99 | init {
100 | | skoar |
101 | minstrels = List.new;
102 |
103 | if (skoar.voices.size == 1) {
104 | minstrels.add(SkoarMinstrel.new(\all, skoar.all_voice, skoar));
105 | } {
106 | skoar.voices.do {
107 | | v |
108 | if (v != skoar.all_voice) {
109 | minstrels.add(SkoarMinstrel.new(v.name, v, skoar));
110 | };
111 | };
112 | };
113 | }
114 |
115 | eventStream {
116 | var funkStreams = List.new;
117 |
118 | minstrels.do {
119 | | m |
120 | funkStreams.add(m.pfunk);
121 | };
122 |
123 | ^Ppar.new(funkStreams).asStream;
124 | }
125 |
126 | pfunk {
127 | var x = this.eventStream;
128 |
129 | ^Pfunc({x.next;});
130 | }
131 |
132 | }
133 |
--------------------------------------------------------------------------------
/SuperCollider/Skoar/pitchy.sc:
--------------------------------------------------------------------------------
1 | // -------------------
2 | // Pitchy Skoarpuscles
3 | // -------------------
4 | SkoarpuscleKey : Skoarpuscle {
5 |
6 | var 0) {
19 | var x = a[0];
20 |
21 | if (x.isKindOf(SkoarpuscleChoard)) {
22 | choard = x;
23 | };
24 |
25 | if (a.size > 1) {
26 | var y = a[1];
27 | if (y.isKindOf(SkoarpuscleSymbol)) {
28 | scale_name = y.val;
29 | };
30 | };
31 |
32 | };
33 |
34 |
35 | };
36 |
37 | if (choard.isKindOf(SkoarpuscleChoard)) {
38 | var minor;
39 |
40 | root = switch (choard.letter)
41 | {"C"} {0}
42 | {"D"} {2}
43 | {"E"} {4}
44 | {"F"} {5}
45 | {"G"} {7}
46 | {"A"} {-1}
47 | {"B"} {-3} + choard.sharps;
48 |
49 | minor = choard.lexeme.findRegexp("m")[0];
50 |
51 | if (minor.notNil and: scale_name.isNil) {
52 | scale_name = \minor;
53 | };
54 |
55 | };
56 |
57 | if (scale_name.isNil) {
58 | scale_name = \major;
59 | };
60 | scale = Scale.all[scale_name];
61 | }
62 |
63 | apply {
64 | | event |
65 |
66 | event[\scale] = scale;
67 | event[\root] = root;
68 |
69 | ^event;
70 | }
71 | }
72 |
73 | SkoarpuscleNoat : Skoarpuscle {
74 |
75 | var "
84 | var s = lex;
85 | var r = s.findRegexp(noat_regex);
86 | var x = -1;
87 | var letter;
88 |
89 | lexeme = lex;
90 |
91 | low = r[1][1] != "";
92 | letter = r[2][1];
93 |
94 | r = s.findRegexp(sharps_regex);
95 | s = r[1][1];
96 |
97 | if (s.beginsWith("#")) {
98 | x = 1;
99 | };
100 |
101 | sharps = s.size * x;
102 |
103 | x = switch (letter)
104 | {"c"} {0}
105 | {"d"} {2}
106 | {"e"} {4}
107 | {"f"} {5}
108 | {"g"} {7}
109 | {"a"} {9}
110 | {"b"} {11};
111 |
112 | case {sharps > 0} {
113 | x = x + 1;
114 | } {sharps < 0} {
115 | x = x - 1;
116 | };
117 |
118 | if (low == false) {
119 | x = x + 12;
120 | };
121 |
122 | val = x;
123 | }
124 |
125 | flatten {^val;}
126 |
127 | isNoatworthy { ^true; }
128 |
129 | asNoat {
130 | ^SkoarNoat_Note(val);
131 | }
132 |
133 | asString {
134 | ^lexeme;
135 | }
136 |
137 | asSymbol {
138 | ^lexeme.asSymbol;
139 | }
140 |
141 | raiseBy {
142 | | x |
143 | ("should raise " ++ lexeme ++ " by " ++ x).postln;
144 | }
145 |
146 | on_enter {
147 | | m, nav |
148 | m.fairy.impress(this);
149 | }
150 |
151 | }
152 |
153 |
154 | SkoarpuscleChoard : Skoarpuscle {
155 |
156 | var 0} {
193 | x = sharps + x;
194 | } {sharps < 0} {
195 | x = x - sharps;
196 | };
197 |
198 | first = x;
199 | third = x + 4;
200 | fifth = x + 7;
201 |
202 | if (lex.findRegexp("[^i]m").size != 0) {
203 | third = third - 1;
204 | };
205 |
206 | if (lex.findRegexp("sus2").size != 0) {
207 | third = third - 2;
208 | };
209 |
210 | if (lex.findRegexp("sus4").size != 0) {
211 | third = third + 1;
212 | };
213 |
214 | if (lex.findRegexp("dim").size != 0) {
215 | third = third - 1;
216 | fifth = fifth - 1;
217 | };
218 |
219 | if (lex.findRegexp("aug").size != 0) {
220 | fifth = fifth + 1
221 | };
222 |
223 | val = [first, third, fifth];
224 |
225 | if (lex.findRegexp("M7").size != 0) {
226 | val = val.add(first + 11);
227 | } {
228 | if (lex.findRegexp("7").size != 0) {
229 | val = val.add(first + 10);
230 | }
231 | };
232 |
233 | if (lex.findRegexp("aug6").size != 0) {
234 | val = val.add(fifth + 1); // fifth has already been incremented
235 | };
236 |
237 | }
238 |
239 | asString {
240 | ^lexeme;
241 | }
242 |
243 | asSymbol {
244 | ^lexeme.asSymbol;
245 | }
246 |
247 | raiseBy {
248 | | x |
249 | ("should raise " ++ lexeme ++ " by " ++ x).postln;
250 | }
251 |
252 | flatten {^lexeme;}
253 |
254 | on_enter {
255 | | m, nav |
256 | m.fairy.impress(this);
257 | }
258 |
259 | isNoatworthy { ^true; }
260 |
261 | asNoat {
262 | ^this;
263 | }
264 |
265 | execute {
266 | | minstrel |
267 | //"SkoarNoat.execute: ".post; key.post; val.postln;
268 | minstrel.koar[\choard] = val;
269 | }
270 | }
271 |
272 | SkoarNoat {
273 | var >> parsing skoar...".postln;
47 | tree = parser.skoar(nil);
48 |
49 | try {
50 | toker.eof;
51 | } {
52 | | e |
53 | e.postln;
54 | toker.dump;
55 | e.throw;
56 | };
57 |
58 | parse_time = (Process.elapsedTime - start_time).round(0.01);
59 |
60 | //"---< Undecorated Skoar Tree >---".postln; tree.draw_tree.postln;
61 | //"<<< tree created, now decorating...".postln;
62 |
63 | this.decorate;
64 | decorate_time = (Process.elapsedTime - start_time - parse_time).round(0.01);
65 |
66 | //this.draw_skoarpions;
67 |
68 | debug("Skoar parsed in " ++ parse_time ++ " seconds, decorated in "
69 | ++ decorate_time ++ ". Total: " ++ (parse_time + decorate_time) ++ " sec.");
70 |
71 |
72 | }
73 |
74 | decorate {
75 |
76 | var inspector = SkoarTokeInspector.new;
77 | var skoarmantics = Skoarmantics.new;
78 |
79 | var f = {
80 | | noad |
81 | var t = noad.toke;
82 |
83 | if (t.notNil) {
84 | var g = inspector[t.class.asSymbol];
85 |
86 | if (g.isKindOf(Function)) {
87 | g.(this, noad, t);
88 | };
89 | } {
90 | var g = skoarmantics[noad.name];
91 |
92 | if (g.isKindOf(Function)) {
93 | g.(this, noad);
94 | };
95 | };
96 | };
97 |
98 | tree.depth_visit(f);
99 | }
100 |
101 | // ----
102 | // misc
103 | // ----
104 |
105 | // creates a new one if needed
106 | get_voice {
107 | | k |
108 |
109 | var voice = nil;
110 |
111 | if (voices.includesKey(k)) {
112 | voice = voices[k];
113 | } {
114 | voice = SkoarKoar(this, k);
115 | voices[k] = voice;
116 | };
117 |
118 | ^voice;
119 |
120 | }
121 |
122 | cthulhu {
123 | | noad |
124 |
125 | // TODO more
126 | "^^(;,;)^^".postln;
127 |
128 | this.dump;
129 |
130 | "".postln;
131 | SkoarError("^^(;,;)^^").throw;
132 |
133 | }
134 |
135 | play {
136 | this.pskoar.play;
137 | }
138 |
139 | pskoar {
140 | ^Skoarchestra.new(this).pfunk;
141 | }
142 |
143 | pvoice {
144 | | voice_name |
145 | ^SkoarMinstrel.new(this.tree, voices[voice_name], this).pfunk;
146 | }
147 |
148 | json {
149 | var pf = Skoarchestra.new(this).pfunk;
150 |
151 | "[".postln;
152 | pf.do({
153 | | event |
154 | " { ".post;
155 | //event.play;
156 |
157 | event.keysValuesDo({
158 | | key, value |
159 | ("'" ++ key ++ "':'").post;
160 | value.printOn(Post,2000);
161 | "', ".post;
162 | });
163 | "}, ".postln;
164 | });
165 | "]".postln;
166 |
167 | }
168 |
169 | draw_skoarpions {
170 | skoarpions.do {
171 | | x |
172 | x.post_tree;
173 |
174 | "Projections: ".postln;
175 | voices.keysDo {
176 | | koar_name |
177 | var projection = x.projection(koar_name);
178 |
179 | projection.block.draw_tree.postln;
180 | };
181 | };
182 | }
183 | }
184 |
185 |
186 | +String {
187 | skoar {
188 | ^Skoar(this);
189 | }
190 |
191 | pskoar {
192 | ^this.skoar.pskoar;
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/SuperCollider/Skoar/skoarpions.sc:
--------------------------------------------------------------------------------
1 | Skoarpion {
2 |
3 | var skoar;
4 | var ---");
172 |
173 | if (arg_spec.notNil) {
174 | "arg_spec: ".post; arg_spec.postln;
175 |
176 | arg_spec.val.do {
177 | | x |
178 | if (x.isKindOf(Skoarpuscle)) {
179 | x.val.post; " ".post;
180 | } {
181 | x.post; " ".post;
182 | };
183 | };
184 | "".postln;
185 | };
186 |
187 | if (body.notNil) {
188 | "body:".postln;
189 | body.draw_tree.post;
190 | };
191 |
192 | "".postln;
193 | }
194 | }
195 |
196 | SkoarIteratoar {
197 | var arr;
198 | var <>i;
199 | var <>n;
200 |
201 | init_iter {
202 | | a |
203 | arr = a;
204 | n = a.size;
205 | i = -1;
206 | }
207 |
208 | // this is returning noads
209 | selector {
210 | | f |
211 | i = f.value % n;
212 | ^arr[i];
213 | }
214 |
215 | at {
216 | | j |
217 | ^this.selector({j});
218 | }
219 |
220 | choose {
221 | ^this.selector({n.rand});
222 | }
223 |
224 | wchoose {
225 | | weights |
226 | ^this.selector({weights.val.windex});
227 | }
228 |
229 | next {
230 | ^this.selector({1 + i});
231 | }
232 |
233 | last {
234 | ^this.selector({i - 1});
235 | }
236 | }
237 |
238 | SkoarpionProjection : SkoarIteratoar {
239 |
240 | var body;
241 | var proj;
242 | var 0) {
266 | skip_to[addr[m-1]] = i;
267 | };
268 |
269 | // don't use add_noad, it corrupts noad.
270 | proj.children.add(x);
271 | proj.skoap = x.skoap;
272 | };
273 | };
274 |
275 | this.init_iter(proj.children);
276 | }
277 |
278 | block {
279 | ^proj;
280 | }
281 |
282 | inline {
283 | ^proj;
284 | }
285 |
286 | map_dst {
287 | | dst |
288 | var addr = dst.address.copyToEnd(0);
289 | var j = addr.pop;
290 |
291 | if (j.isNil) {
292 | ^addr;
293 | };
294 |
295 | ^(addr ++ skip_to[j]);
296 | }
297 |
298 | }
299 |
--------------------------------------------------------------------------------
/SuperCollider/Skoar/toker.sc:
--------------------------------------------------------------------------------
1 |
2 | // =========
3 | // The Toker
4 | // =========
5 |
6 | Toker {
7 | var skoarse;
8 | var i_am_here;
9 | var i_saw;
10 |
11 | *new {
12 | | code |
13 | ^super.new.init( code );
14 | }
15 |
16 | init {
17 | | code |
18 | skoarse = code;
19 | i_am_here = 0;
20 | i_saw = nil;
21 | }
22 |
23 | see {
24 | | want |
25 |
26 | if (i_saw.notNil) {
27 | if (i_saw.isKindOf(want)) {
28 | ^i_saw
29 | }
30 | } {
31 | i_saw = want.match(skoarse, i_am_here);
32 | ^i_saw;
33 | }
34 |
35 | ^nil;
36 | }
37 |
38 | sees {
39 | | wants |
40 |
41 | i_am_here = i_am_here + Toke_Whitespace.burn(skoarse, i_am_here);
42 |
43 | wants.do {
44 | | want |
45 | var x = this.see(want);
46 |
47 | if (x.notNil) {
48 | ^x;
49 | };
50 | };
51 |
52 | ^nil;
53 | }
54 |
55 | burn {
56 | | want |
57 |
58 | var toke = i_saw;
59 | var msg;
60 |
61 | if (toke.isNil) {
62 | toke = this.see(want);
63 | };
64 |
65 | toke.isKindOf(want) and: {
66 | i_saw = nil;
67 | i_am_here = i_am_here + toke.burn;
68 | i_am_here = i_am_here + Toke_Whitespace.burn(skoarse, i_am_here);
69 | ^toke;
70 | };
71 |
72 | msg = "Tried to burn " ++ want.asString ++ ", but saw " ++ toke.asString;
73 |
74 | "Toker Fail.".postln;
75 | msg.postln;
76 | this.dump;
77 |
78 | SkoarParseException(msg).throw;
79 | }
80 |
81 | eof {
82 | Toke_EOF.burn(skoarse, i_am_here);
83 | }
84 |
85 | dump {
86 | ("\nToker Dump" ++
87 | "\nhere : " ++ i_am_here.asString ++
88 | "\nsaw : " ++ i_saw.asString ++
89 | "\nskoarse: " ++ skoarse.copyRange(0,i_am_here)
90 | ++ "_$_" ++ skoarse.copyRange(i_am_here, skoarse.size)).postln;
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/SuperCollider/Testing/cats.scd:
--------------------------------------------------------------------------------
1 |
2 | var qrt = (\dur:1);
3 | var eth = (\dur:1/2);
4 | var sxt = (\dur:1/4);
5 |
6 | SkoarTestRunner((
7 |
8 | cats_eat_values: [
9 | "2 => @two ) =^.^= => @two ) < =^.^= > => @two )",
10 | [(\two:2),(\two:inf),(\two:[nil])]
11 | ],
12 |
13 | cats_regex_ambiguity: [
14 | "<=^.^=,=^.^=> => @foo )",
15 | [(\foo:[nil,nil])]
16 | ],
17 |
18 | cats_are_cats: [
19 | "{? =^.^= == =^.^= ?? 3 ?? 2 ?} => @foo )",
20 | [(\foo:3)]
21 | ],
22 |
23 | cats_are_false: [
24 | "{? =^.^= ?? 3 ?? 2 ?} => @foo )",
25 | [(\foo:2)]
26 | ],
27 |
28 | cats_nonexistant_variable: [
29 | "{? !x == =^.^= ?? 3 ?? 2 ?} => @foo )",
30 | [(\foo:3)]
31 | ],
32 |
33 | cats_nonexistant_variable_two: [
34 | "{? !x ?? 3 ?? 2 ?} => @foo )",
35 | [(\foo:2)]
36 | ],
37 |
38 | cats_missing_args: [
39 | "{! bar !! {? !x ?? 3 ?? 2 ?} !} !bar => @foo )",
40 | [(\foo:2)]
41 | ],
42 |
43 | ));
44 |
--------------------------------------------------------------------------------
/SuperCollider/Testing/dev.scd:
--------------------------------------------------------------------------------
1 |
2 | var qrt = (\dur:1);
3 | var eth = (\dur:1/2);
4 |
5 | SkoarTestRunner((
6 |
7 | da_capo_a: [
8 | ") ) ) fine ] ] D.C. al fine",
9 | [
10 | qrt, qrt, qrt, eth, eth,
11 | qrt, qrt, qrt
12 | ]
13 | ],
14 |
15 | da_capo_b: [
16 | ") ) ) |: ] ] :| fine D.C. al fine",
17 | [
18 | qrt, qrt, qrt, eth, eth, eth, eth,
19 | qrt, qrt, qrt, eth, eth, eth, eth
20 | ]
21 | ],
22 |
23 | // next is unimplemented
24 | listy_f: [
25 | "<3,4> => @x <0, !x.next, !x.next, 2> => @food )",
26 | [( 'dur': 1.0, 'food': [ 0, 3, 4, 2 ], 'x':[3, 4] )]
27 | ],
28 |
29 | // right now it's popping the skoar off, and forgetting that it has seen the colon
30 | colons_unbalanced: [
31 | "| ) ) ) :| ] ] :|",
32 | [
33 | qrt, qrt, qrt,
34 | qrt, qrt, qrt, eth, eth,
35 | qrt, qrt, qrt, eth, eth,
36 | ]
37 | ],
38 |
39 | argspec_ambiguity: [
40 | "{! ) !}",
41 | [qrt]
42 | ],
43 |
44 | ));
45 |
--------------------------------------------------------------------------------
/SuperCollider/Testing/increments.scd:
--------------------------------------------------------------------------------
1 |
2 | var qrt = (\dur:1);
3 | var eth = (\dur:1/2);
4 |
5 | SkoarTestRunner((
6 |
7 | incr_int: [
8 | "1 => @x ) 1 +> @x ) 2 +> @x ) 5 +> @x )",
9 | [(x: 1), (x: 2), (x: 4), (x: 9)]
10 | ],
11 |
12 | decr_int: [
13 | "1 => @x ) 1 -> @x ) 2 -> @x ) 5 -> @x )",
14 | [(x: 1), (x: 0), (x: -2), (x: -7)]
15 | ],
16 |
17 | multr_int: [
18 | "2 => @x ) 3 x> @x ) 1 x> @x ) 0 x> @x )",
19 | [(x: 2), (x: 6), (x: 6), (x: 0)]
20 | ]
21 |
22 | ));
23 |
--------------------------------------------------------------------------------
/SuperCollider/Testing/levels.scd:
--------------------------------------------------------------------------------
1 |
2 | var qrt = (\dur:1);
3 | var eth = (\dur:1/2);
4 |
5 | SkoarTestRunner((
6 |
7 | ppp: [
8 | "ppp ) pp ) p ) mp )",
9 | [(amp: 1/8), (amp: 2/8), (amp: 3/8), (amp: 4/8)]
10 | ],
11 |
12 | pppiano: [
13 | "pppiano ) ppiano ) piano ) mezzopiano ) mpiano )",
14 | [(amp: 1/8), (amp: 2/8), (amp: 3/8), (amp: 4/8), (amp: 4/8)]
15 | ],
16 |
17 | fff: [
18 | "fff ) ff ) forte ) mf )",
19 | [(amp: 1), (amp: 7/8), (amp: 6/8), (amp: 5/8)]
20 | ],
21 |
22 | ffforte: [
23 | "ffforte ) fforte ) forte ) mforte ) mezzoforte )",
24 | [(amp: 1), (amp: 7/8), (amp: 6/8), (amp: 5/8), (amp: 5/8)]
25 | ],
26 |
27 | hashbars_short: [
28 | "[] =>@x) [ ] =>@x) [#] =>@x) [ ] =>@x) [# ] =>@x) [##] =>@x) [# ] =>@x) [## ] =>@x) [###] =>@x) ",
29 | [(x: 0), (x: 0), (x: 1), (x: 0), (x: 1/2), (x: 1), (x: 1/3), (x: 2/3), (x: 1), ]
30 | ],
31 |
32 | hashbars_longer: [
33 | "[##### ] =>@x) [############################## ] =>@x) [############################################################ ] =>@x)",
34 | [(x: 5/11), (x: 30/31), (x: 60/61), ]
35 | ],
36 |
37 | ));
38 |
--------------------------------------------------------------------------------
/SuperCollider/Testing/noaty.scd:
--------------------------------------------------------------------------------
1 |
2 | var qrt = (\dur:1);
3 | var eth = (\dur:1/2);
4 |
5 | SkoarTestRunner((
6 |
7 | low: [
8 | "_c) _d) _e) _f) _g) _a) _b)",
9 | [(note: 0), (note: 2), (note: 4), (note: 5), (note: 7), (note: 9), (note: 11)]
10 | ],
11 |
12 | high: [
13 | "c) d) e) f) g) a) b)",
14 | [(note: 12), (note: 14), (note: 16), (note: 17), (note: 19), (note: 21), (note: 23)]
15 | ],
16 |
17 | flats_low: [
18 | "_cb) _db) _eb) _fb) _gb) _ab) _bb ) _b )",
19 | [(note: -1), (note: 1), (note: 3), (note: 4), (note: 6), (note: 8), (note: 10), (note: 11)]
20 | ],
21 |
22 | flats_high: [
23 | "cb) db) eb) fb) gb) ab) bb ) b )",
24 | [(note: 11), (note: 13), (note: 15), (note: 16), (note: 18), (note: 20), (note: 22), (note: 23)]
25 | ],
26 |
27 | sharps_low: [
28 | "_c#) _d#) _e#) _f#) _g#) _a#) _b# ) _b )",
29 | [(note: 1), (note: 3), (note: 5), (note: 6), (note: 8), (note: 10), (note: 12), (note: 11)]
30 | ],
31 |
32 | sharps_high: [
33 | "c#) d#) e#) f#) g#) a#) b#) b)",
34 | [(note: 13), (note: 15), (note: 17), (note: 18), (note: 20), (note: 22), (note: 24), (note: 23)]
35 | ],
36 |
37 | choards_basic: [
38 | "C) D) E) F) G) A) B)",
39 | [ (note: [0,4,7]), (note: [2,6,9]),
40 | (note: [4,8,11]), (note: [5,9,12]),
41 | (note: [7,11,14]), (note: [9,13,16]),
42 | (note: [11,15,18])]
43 | ],
44 |
45 | choards_moar: [
46 | "Cm) C7) Cm7) CM7) CmM7) Cdim) Csus2) Csus4M7) Caug) Caug6)",
47 | [ (note: [0, 3, 7]),
48 | (note: [0, 4, 7, 10]),
49 | (note: [0, 3, 7, 10]),
50 | (note: [0, 4, 7, 11]),
51 | (note: [0, 3, 7, 11]),
52 |
53 | (note: [0, 3, 6]),
54 |
55 | (note: [0, 2, 7]),
56 | (note: [0, 5, 7, 11]), // c f g b
57 |
58 | (note: [0, 4, 8]),
59 | (note: [0, 4, 8, 9]),
60 | ]
61 | ],
62 |
63 | ));
64 |
--------------------------------------------------------------------------------
/SuperCollider/Testing/ops.scd:
--------------------------------------------------------------------------------
1 |
2 | var qrt = (\dur:1);
3 | var eth = (\dur:1/2);
4 |
5 | SkoarTestRunner((
6 |
7 | math_add_a: [
8 | "1 + 2 ) 3 + 4 + 5 )",
9 | [(\degree:3),(\degree:12)]
10 | ],
11 |
12 | math_add_b: [
13 | "1 + 2 ) 3 + 4 + 5 ) $ + 3 )",
14 | [(\degree:3),(\degree:12),(\degree:15)]
15 | ],
16 |
17 | math_add_c: [
18 | "0 + 0 ) 1 + 1 + 1 => @x )",
19 | [(\degree:0),(\degree:3)]
20 | ],
21 |
22 | math_mul_a: [
23 | "1 * 2 ) 3 * 4 * 5 )",
24 | [(\degree:2),(\degree:60)]
25 | ],
26 |
27 | math_mul_b: [
28 | "1 + 2 * 5 ) 3 + 4 * 5 ) $ * 2 + 1 )",
29 | [(\degree:15),(\degree:35),(\degree:71)]
30 | ],
31 |
32 |
33 | // ---------------------------------------------------
34 | // ---------------------------------------------------
35 | // Addition
36 | // ---------------------------------------------------
37 | // ---------------------------------------------------
38 |
39 | op_add_Symbol_Symbol: [
40 | "@abc + @def => @x )",
41 | [(x:'abcdef')]
42 | ],
43 |
44 | op_add_Symbol_Int: [
45 | "@abc + 7 => @x )",
46 | [(x:'abc7')]
47 | ],
48 |
49 | op_add_Symbol_Noat: [
50 | "@abc + c# => @x )",
51 | [(x: 'abcc#')]
52 | ],
53 |
54 | op_add_Symbol_Choard: [
55 | "@abc + A# => @x )",
56 | [(x: 'abcA#')]
57 | ],
58 |
59 |
60 | op_add_Symbol_List: [
61 | "@abc + <0,1> => @x )",
62 | [(x: ['abc', 0, 1])]
63 | ],
64 |
65 | op_add_Symbol_Freq: [
66 | "@abc + 2600Hz => @x )",
67 | [(x: 'abc2600Hz')]
68 | ],
69 |
70 | op_add_Symbol_String: [
71 | "@abc + 'ABC' => @x )",
72 | [(x: 'abcABC')]
73 | ],
74 |
75 | op_add_Symbol_Float: [
76 | "@abc + 2.18 => @x )",
77 | [(x: 'abc2.18')]
78 | ],
79 |
80 | op_add_Int_Symbol: [
81 | "7 + @abc => @x )",
82 | [(x: '7abc')]
83 | ],
84 |
85 | op_add_Int_Int: [
86 | "7 + 7 => @x )",
87 | [(x: 14)]
88 | ],
89 |
90 |
91 | op_add_Int_List: [
92 | "7 + <0,1> => @x )",
93 | [(x: [7,0,1])]
94 | ],
95 |
96 | op_add_Int_Freq: [
97 | "7 + 2600Hz )",
98 | [(freq: 2607)]
99 | ],
100 |
101 |
102 |
103 | op_add_Int_String: [
104 | "7 + 'ABC' => @x )",
105 | [(x: "7ABC")]
106 | ],
107 |
108 | op_add_Int_Float: [
109 | "7 + 2.18 => @x )",
110 | [(x: 9.18)]
111 | ],
112 |
113 |
114 | op_add_List_Symbol: [
115 | "<0,1> + @abc => @x )",
116 | [(x: [0,1,\abc])]
117 | ],
118 |
119 | op_add_List_Int: [
120 | "<0,1> + 7 => @x )",
121 | [(x: [0,1,7])]
122 | ],
123 |
124 | op_add_List_List: [
125 | "<0,1> + <0,1> => @x )",
126 | [(x: [0,1,0,1])]
127 | ],
128 |
129 | op_add_List_Freq: [
130 | "<0,1> + 2600Hz => @x )",
131 | [(x: [0,1,2600])]
132 | ],
133 |
134 | op_add_List_String: [
135 | "<0,1> + 'ABC' => @x )",
136 | [(x: [0,1,"ABC"] )]
137 | ],
138 |
139 | op_add_List_Float: [
140 | "<0,1> + 2.18 => @x )",
141 | [(x: [0,1,2.18])]
142 | ],
143 |
144 |
145 | op_add_Noat_Symbol: [
146 | "c# + @abc=> @x )",
147 | [(x: 'c#abc')]
148 | ],
149 |
150 |
151 |
152 | op_add_Noat_String: [
153 | "c# + 'ABC' => @x )",
154 | [(x: "c#ABC")]
155 | ],
156 |
157 |
158 | op_add_Choard_Symbol: [
159 | "A# + @abc=> @x )",
160 | [(x: 'A#abc')]
161 | ],
162 |
163 |
164 |
165 | op_add_Choard_String: [
166 | "A# + 'ABC' => @x )",
167 | [(x: "A#ABC" )]
168 | ],
169 |
170 |
171 |
172 | op_add_String_Symbol: [
173 | "'ABC' + @abc => @x )",
174 | [(x: "ABCabc" )]
175 | ],
176 |
177 | op_add_String_Int: [
178 | "'ABC' + 7 => @x )",
179 | [(x: "ABC7" )]
180 | ],
181 |
182 | op_add_String_Noat: [
183 | "'ABC' + c# => @x )",
184 | [(x: "ABCc#" )]
185 | ],
186 |
187 | op_add_String_Choard: [
188 | "'ABC' + A# => @x )",
189 | [(x: "ABCA#")]
190 | ],
191 |
192 | op_add_String_List: [
193 | "'ABC' + <0,1> => @x )",
194 | [(x: ["ABC",0,1])]
195 | ],
196 |
197 | op_add_String_Freq: [
198 | "'ABC' + 2600Hz => @x )",
199 | [(x: "ABC2600Hz" )]
200 | ],
201 |
202 |
203 |
204 | op_add_String_String: [
205 | "'ABC' + 'ABC' => @x )",
206 | [(x: "ABCABC" )]
207 | ],
208 |
209 | op_add_String_Float: [
210 | "'ABC' + 2.18 => @x )",
211 | [(x: "ABC2.18" )]
212 | ],
213 |
214 | op_add_Freq_Symbol: [
215 | "2600Hz + @abc=> @x )",
216 | [(x:'2600Hzabc')]
217 | ],
218 |
219 | op_add_Freq_Int: [
220 | "2600Hz + 7 => @x )",
221 | [(x:2607)]
222 | ],
223 |
224 |
225 | op_add_Freq_List: [
226 | "2600Hz + <0,1> => @x )",
227 | [(x: [2600,0,1])]
228 | ],
229 |
230 | op_add_Freq_Freq: [
231 | "2600Hz + 2600Hz => @x )",
232 | [(x: 5200)]
233 | ],
234 |
235 | op_add_Freq_String: [
236 | "2600Hz + 'ABC' => @x )",
237 | [(x: "2600HzABC" )]
238 | ],
239 |
240 | op_add_Freq_Float: [
241 | "2600Hz + 2.18 => @x )",
242 | [(x: 2602.18 )]
243 | ],
244 |
245 |
246 | op_add_Float_Symbol: [
247 | "2.18 + @abc=> @x )",
248 | [(x: '2.18abc')]
249 | ],
250 |
251 | op_add_Float_Int: [
252 | "2.18 + 7 => @x )",
253 | [(x: 9.18)]
254 | ],
255 |
256 |
257 |
258 | op_add_Float_Float: [
259 | "2.18 + 2.18 => @x )",
260 | [(x: 4.36)]
261 | ],
262 |
263 | op_add_Hash_Int: [
264 | "[### ] + 7 => @x )",
265 | [(x: 7.6)]
266 | ],
267 |
268 | op_add_Int_Hash: [
269 | "7 + [### ]=> @x )",
270 | [(x: 7.6)]
271 | ],
272 |
273 | op_add_Hash_Hash: [
274 | "[### ] + [#### ] => @x )",
275 | [(x: 0.7)]
276 | ],
277 |
278 | // ---------------------------------------------------
279 | // ---------------------------------------------------
280 | // Subtraction
281 | // ---------------------------------------------------
282 | // ---------------------------------------------------
283 |
284 | op_sub_Int_Int: [
285 | "7 - 7 => @x )",
286 | [(x: 0)]
287 | ],
288 |
289 | op_sub_Int_Freq: [
290 | "7 - 2600Hz => @x )",
291 | [(x: -2593)]
292 | ],
293 |
294 | op_sub_Int_Float: [
295 | "7 - 2.18 => @x )",
296 | [(x: 4.82)]
297 | ],
298 |
299 | op_sub_Freq_Freq: [
300 | "2600Hz - 2600Hz => @x )",
301 | [(x: 0)]
302 | ],
303 |
304 | op_sub_Freq_Float: [
305 | "2600Hz - 2.18 )",
306 | [(freq: 2597.82 )]
307 | ],
308 |
309 | op_sub_Float_Int: [
310 | "2.18 - 7 => @x )",
311 | [(x: -4.82)]
312 | ],
313 |
314 | op_sub_Float_Float: [
315 | "2.18 - 2.18 => @x )",
316 | [(x: 0)]
317 | ],
318 |
319 | op_sub_Hash_Int: [
320 | "[### ] - 7 => @x )",
321 | [(x: -6.4)]
322 | ],
323 |
324 | op_sub_Int_Hash: [
325 | "7 - [### ]=> @x )",
326 | [(x: 6.4)]
327 | ],
328 |
329 | op_sub_Hash_Hash: [
330 | "[### ] - [#### ] => @x )",
331 | [(x: -0.1)]
332 | ],
333 |
334 |
335 | op_add_Float_String: [
336 | "2.18 + 'ABC' => @x )",
337 | [(x: "2.18ABC")]
338 | ],
339 |
340 | // False
341 | op_add_Float_False: [
342 | "2.18 + no => @x )",
343 | [(x: false)]
344 | ],
345 |
346 | op_add_Symbol_False: [
347 | "@abc + no => @x )",
348 | [(x: false)]
349 | ],
350 |
351 | op_add_Int_False: [
352 | "7 + no => @x )",
353 | [(x: false)]
354 | ],
355 |
356 | op_add_List_False: [
357 | "<0,1> + no => @x )",
358 | [(x: false)]
359 | ],
360 |
361 | op_add_Noat_False: [
362 | "c# + no => @x )",
363 | [(x: false )]
364 | ],
365 |
366 | op_add_Choard_False: [
367 | "A# + no => @x )",
368 | [(x: false)]
369 | ],
370 |
371 | op_add_False_Symbol: [
372 | "no + @abc=> @x )",
373 | [(x: false)]
374 | ],
375 |
376 | op_add_False_Choard: [
377 | "no + A# => @x )",
378 | [(x: false)]
379 | ],
380 |
381 | op_add_False_Freq: [
382 | "no + 2600Hz => @x )",
383 | [(x: false)]
384 | ],
385 |
386 | op_add_False_List: [
387 | "no + <0,1> => @x )",
388 | [(x: false)]
389 | ],
390 |
391 | op_add_False_Noat: [
392 | "no + c# => @x )",
393 | [(x: false)]
394 | ],
395 |
396 | op_add_False_String: [
397 | "no + 'ABC' => @x )",
398 | [(x: false)]
399 | ],
400 |
401 | op_add_False_False: [
402 | "no + no => @x )",
403 | [(x: false)]
404 | ],
405 |
406 | op_add_False_Int: [
407 | "no + 7 => @x )",
408 | [(x: false)]
409 | ],
410 |
411 | op_add_False_Float: [
412 | "no + 2.18 => @x )",
413 | [(x: false)]
414 | ],
415 |
416 | op_add_String_False: [
417 | "'ABC' + no => @x )",
418 | [(x: false)]
419 | ],
420 |
421 | // True
422 | op_add_Float_True: [
423 | "2.18 + yes => @x )",
424 | [(x: 2.18)]
425 | ],
426 |
427 | op_add_Symbol_True: [
428 | "@abc + yes => @x )",
429 | [(x: \abc)]
430 | ],
431 |
432 | op_add_Int_True: [
433 | "7 + yes => @x )",
434 | [(x: 7)]
435 | ],
436 |
437 | op_add_List_True: [
438 | "<0,1> + yes => @x )",
439 | [(x: [0,1])]
440 | ],
441 |
442 | op_add_Noat_True: [
443 | "c# + yes => @x )",
444 | [(x: nil )]
445 | ],
446 |
447 | op_add_Choard_True: [
448 | "A# + yes => @x )",
449 | [(x: nil)]
450 | ],
451 |
452 | op_add_True_Symbol: [
453 | "yes + @abc=> @x )",
454 | [(x: 'abc')]
455 | ],
456 |
457 | op_add_True_Choard: [
458 | "yes + A# => @x )",
459 | [(x: nil)]
460 | ],
461 |
462 | op_add_True_Freq: [
463 | "yes + 2600Hz => @x )",
464 | [(x: 2600)]
465 | ],
466 |
467 | op_add_True_List: [
468 | "yes + <0,1> => @x )",
469 | [(x: [0,1])]
470 | ],
471 |
472 | op_add_True_Noat: [
473 | "yes + c# => @x )",
474 | [(x: nil)]
475 | ],
476 |
477 | op_add_True_String: [
478 | "yes + 'ABC' => @x )",
479 | [(x: "ABC")]
480 | ],
481 |
482 | op_add_True_True: [
483 | "yes + yes => @x )",
484 | [(x: true)]
485 | ],
486 |
487 | op_add_True_Int: [
488 | "yes + 7 => @x )",
489 | [(x: 7)]
490 | ],
491 |
492 | op_add_True_Float: [
493 | "yes + 2.18 => @x )",
494 | [(x: 2.18)]
495 | ],
496 |
497 | op_add_String_True: [
498 | "'ABC' + yes => @x )",
499 | [(x: "ABC")]
500 | ],
501 |
502 | // ---------------------------------------------------
503 | // ---------------------------------------------------
504 | // Multiplication
505 | // ---------------------------------------------------
506 | // ---------------------------------------------------
507 | op_mul_Int_Int: [
508 | "7 * 7 => @x )",
509 | [(x: 49)]
510 | ],
511 |
512 | op_mul_Int_Freq: [
513 | "7 * 2600Hz )",
514 | [(freq: 18200)]
515 | ],
516 |
517 | op_mul_Int_Float: [
518 | "7 * 2.18 => @x )",
519 | [(x: 15.26)]
520 | ],
521 |
522 | op_mul_Freq_Int: [
523 | "2600Hz * 7 => @x )",
524 | [(x:18200)]
525 | ],
526 |
527 | op_mul_Freq_Freq: [
528 | "2600Hz * 2600Hz )",
529 | [(freq:6760000)]
530 | ],
531 |
532 | op_mul_Freq_Float: [
533 | "2600Hz * 2.18 => @x )",
534 | [(x: 5668 )]
535 | ],
536 |
537 | op_mul_Float_Int: [
538 | "2.18 * 7 => @x )",
539 | [(x: 15.26)]
540 | ],
541 |
542 | op_mul_Float_Float: [
543 | "2.18 * 2.18 => @x )",
544 | [(x: 4.7524)]
545 | ],
546 |
547 | op_mul_Hash_Int: [
548 | "[### ] * 7 => @x )",
549 | [(x: 4.2)]
550 | ],
551 |
552 | op_mul_Int_Hash: [
553 | "7 * [### ]=> @x )",
554 | [(x: 4.2)]
555 | ],
556 |
557 | op_mul_Hash_Hash: [
558 | "[### ] * [#### ] => @x )",
559 | [(x: 0.12)]
560 | ],
561 | ));
562 |
--------------------------------------------------------------------------------
/SuperCollider/Testing/regex.scd:
--------------------------------------------------------------------------------
1 |
2 | // These tests check for regex ambiguities
3 |
4 | var qrt = (\dur:1);
5 | var eth = (\dur:1/2);
6 |
7 | SkoarTestRunner((
8 |
9 | // i'm not sure how to test this stuff.
10 | forte: [
11 | "forte",
12 | [()]
13 | ],
14 |
15 | ));
16 |
--------------------------------------------------------------------------------
/SuperCollider/Testing/sanity.scd:
--------------------------------------------------------------------------------
1 |
2 | var qrt = (\dur:1);
3 | var eth = (\dur:1/2);
4 | var sxt = (\dur:1/4);
5 |
6 | SkoarTestRunner((
7 |
8 | long_beats: [
9 | ") ). )) )). ))) )))) .))))) )))))) )))))))",
10 | [(\dur:1),(\dur:1.5),(\dur:2),(\dur:3),(\dur:4),(\dur:8),(\dur:16),(\dur:32),(\dur:64)]
11 | ],
12 |
13 | short_beats: [
14 | "] ]] ]]] ]]]] ]]. ]]]. ]]]]] .]]]]]] ]]]]]]]",
15 | [(\dur:1/2), (\dur:1/4),(\dur:1/8),
16 | (\dur:1/16),(\dur:3/8), (\dur:3/16),
17 | (\dur:1/32),(\dur:1/64),(\dur:1/128)]
18 | ],
19 |
20 | long_rests: [
21 | "} }} }}} }}}} }. }}.",
22 | [(\dur:1,\isRest:true),(\dur:2,\isRest:true),
23 | (\dur:4,\isRest:true),(\dur:8,\isRest:true),
24 | (\dur:1.5,\isRest:true),(\dur:3,\isRest:true)]
25 | ],
26 |
27 | short_rests: [
28 | "o/ oo/ ooo/ oooo/ ooooo/ o/. oo/. ooo/.",
29 | [(\dur:1/2,\isRest:true),(\dur:1/4,\isRest:true),
30 | (\dur:1/8,\isRest:true), (\dur:1/16,\isRest:true),
31 | (\dur:1/32,\isRest:true),(\dur:3/4,\isRest:true),
32 | (\dur:3/8,\isRest:true),(\dur:3/16,\isRest:true)]
33 | ],
34 |
35 | fancy_beats: [
36 | ".] .]]. ]. .)__ .)__. ]__.",
37 | [(\dur:1/2),(\dur:3/8),(\dur:3/4),(\dur:1),(\dur:1.5),(\dur:3/4)]
38 | ],
39 |
40 | fancy_beats: [
41 | ".] .]]. ]. .)__ .)__. ]__.",
42 | [(\dur:1/2),(\dur:3/8),(\dur:3/4),(\dur:1),(\dur:1.5),(\dur:3/4)]
43 | ],
44 |
45 | listy_a: [
46 | "<0,1,2> => @food )",
47 | [( 'dur': 1.0, 'food': [ 0, 1, 2 ] )]
48 |
49 | ],
50 |
51 | listy_b: [
52 | "<0.0, -1, 2.2> => @food )",
53 | [( 'dur': 1.0, 'food': [ 0.0, -1, 2.2 ] )]
54 |
55 | ],
56 |
57 | listy_c: [
58 | "<<0,3>,1,2> => @food )",
59 | [( 'dur': 1.0, 'food': [ [0,3], 1, 2 ] )]
60 |
61 | ],
62 |
63 | listy_d: [
64 | "3 => @x <0,!x,2> => @food )",
65 | [( 'dur': 1.0, 'food': [ 0, 3, 2 ], 'x': 3 )]
66 |
67 | ],
68 |
69 | listy_e: [
70 | "<3,4> => @x <0,!x,2> => @food )",
71 | [( 'dur': 1.0, 'food': [ 0, [3,4], 2 ], 'x':[3, 4] )]
72 |
73 | ],
74 |
75 | numbers: [
76 | "-1 ) 0 ) 1 ) 2 ) 20 ] 0.1 ] 1.0 ] ",
77 | [(\degree:-1),(\degree:0),(\degree:1),(\degree:2),
78 | (\degree:20),(\degree:0.1),(\degree:1.0)]
79 | ],
80 |
81 | colons_simple: [
82 | "|: ) ) ) :| ] ] :|",
83 | [
84 | qrt,qrt,qrt,
85 | qrt,qrt,qrt, eth,eth,
86 | qrt,qrt,qrt, eth,eth
87 | ]
88 | ],
89 |
90 | colons_middle: [
91 | "|: ) ) ) |: ] ] :|",
92 | [
93 | qrt,qrt,qrt,
94 | eth,eth,eth,eth
95 | ]
96 | ],
97 |
98 | dal_segno_a: [
99 | ",segno` ) ) ) |: ] ] :| fine D.S. al fine",
100 | [
101 | qrt, qrt, qrt, eth, eth, eth, eth,
102 | qrt, qrt, qrt, eth, eth, eth, eth
103 | ]
104 | ],
105 |
106 | dal_segno_b: [
107 | ",segno` ) ,segno` ) ) |: ] ] :| fine Dal Segno al fine",
108 | [
109 | qrt, qrt, qrt, eth, eth, eth, eth,
110 | qrt, qrt, eth, eth, eth, eth,
111 | ]
112 | ],
113 |
114 | skoarpion_a: [
115 | ") {! f !! ] !} !f",
116 | [qrt, eth]
117 | ],
118 |
119 | skoarpion_b: [
120 | ") {! f !! !x ] !} ) !f<0>",
121 | [qrt, qrt, eth]
122 | ],
123 |
124 | skoarpion_c: [
125 | ") {! !! ] !} => @f ) !f<0>",
126 | [qrt, qrt, eth]
127 | ],
128 |
129 | skoarpion_d: [
130 | ") {! ] !} => @f ) !f",
131 | [qrt, qrt, eth]
132 | ],
133 |
134 | one_voice_a: [
135 | ")
136 | .a ]
137 | )
138 | .a ]
139 | ",
140 | [qrt, eth, qrt, eth]
141 | ],
142 |
143 | one_voice_b: [
144 | ") )
145 | .a ] ]
146 | ",
147 | [qrt, qrt, eth, eth]
148 | ],
149 |
150 | two_voices_a: [
151 | ") )
152 | .a ] ] ]
153 | .b ]] ]] )
154 | ",
155 | [[qrt,qrt], [qrt,qrt], [eth,sxt], sxt, [eth,qrt], eth]
156 | ],
157 |
158 | ));
159 |
--------------------------------------------------------------------------------
/SuperCollider/Testing/spawn_skeletons.scd:
--------------------------------------------------------------------------------
1 | x = SkoarOps.new;
2 |
3 | x.addition.keysValuesDo({
4 | | k, v |
5 |
6 | /*
7 | math_add_a: [
8 | "1 + 2 ) 3 + 4 + 5 )",
9 | [(\degree:3),(\degree:12)]
10 | ],*/
11 |
12 | v.keysValuesDo {
13 | | p, q |
14 | var a = k.asString;
15 | var b = p.asString;
16 | a = a[11..a.size-1];
17 | b = b[11..b.size-1];
18 | ("op_add_" ++ a ++ "_" ++ b ++": [\n \"" ++ a ++ " + " ++ b ++ " => @x )\",").postln;
19 | (" [(\x:inf)]\n],\n").postln;
20 | };
21 | "".postln;
22 |
23 | });
24 |
25 |
--------------------------------------------------------------------------------
/SuperCollider/Testing/unittests.sc:
--------------------------------------------------------------------------------
1 | SkoarTest : UnitTest {
2 |
3 | var <>tests_table;
4 |
5 | *report {
6 | super.report;
7 | Post.nl;
8 | if (failures.size > 0) {
9 | "SKOAR FAIL".inform;
10 | } {
11 | "SKOAR PASS".inform;
12 | };
13 | }
14 |
15 | setUp {
16 | // this will wait until the server is booted
17 | //this.bootServer;
18 | // if the server is already booted it will free all nodes
19 | // and create new allocators, giving you a clean slate
20 | }
21 |
22 | tearDown {
23 | // this will be called after each test
24 | }
25 |
26 | //this.assert( 6 == 6, "6 should equal 6");
27 | //this.assertEquals( 9, 9, "9 should equal 9");
28 | //this.assertFloatEquals( 4.0 , 1.0 * 4.0 / 4.0 * 4.0,
29 | // "floating point math should be close to equal");
30 |
31 | // will wait until the condition is true
32 | // will be considered a failure after 10 seconds
33 | //this.wait( { p.isPlaying }, "waiting for synth to play", 10);
34 |
35 | test_do {
36 |
37 | this.assert(tests_table.notNil == true, "You didn't set up the tests right.");
38 | if (tests_table.isNil) {
39 | ^nil;
40 | };
41 |
42 | tests_table.keysValuesDo {
43 | | test_name, test_meat |
44 |
45 | var s = test_meat[0];
46 | var a = test_meat[1];
47 | var msg = test_name.asString;
48 |
49 | ("Test: " ++ test_name).postln;
50 | "Test input: ".post; s.postln;
51 | "Expectations:".postln; a.do {
52 | | x |
53 | x.postln;
54 | };
55 |
56 | Expectoar.test(s, a, this, msg);
57 |
58 | };
59 | }
60 | }
61 |
62 | SkoarTestRunner {
63 |
64 | *new {
65 | | x |
66 | ^super.new.init(x);
67 | }
68 |
69 | init {
70 | | tests |
71 | var testoar = SkoarTest.new;
72 | testoar.tests_table = tests;
73 | testoar.run;
74 | }
75 | }
76 |
77 | Expectoar {
78 |
79 | var ").postln;
191 |
192 | testoar.assert(seen_event.isKindOf(Event), tag ++ "should be an event.");
193 |
194 | if (seen_event.notNil) {
195 | var seen_val = this.flatten(seen_event[ekey]);
196 | var x;
197 |
198 | // we send inf if we want to test that the value doesn't exist (because we can't send nil)
199 | if (eval == inf) {
200 | eval = nil;
201 | };
202 |
203 | if (eval.isKindOf(Float)) {
204 | x = eval - seen_val;
205 | if (x < 0) {
206 | x = -1 * x;
207 | };
208 | x = x < 0.0001;
209 | } {
210 | x = seen_val == eval;
211 | };
212 |
213 | testoar.assert(x, tag ++ "seen_event[" ++ ekey ++ "] = " ++ seen_val ++ " == " ++ eval ++ " expected :: <"
214 | ++ seen_val.class.asString ++ ", " ++ eval.class.asString ++ ">";
215 | );
216 | };
217 |
218 | };
219 | }
220 |
221 |
222 | matches {
223 | | exp_event, seen_events |
224 | seen_events.do {
225 | | seen_event |
226 | var seen = true;
227 |
228 | exp_event.keysValuesDo {
229 | | ekey, eval |
230 | if (seen_event.notNil) {
231 | var x = this.flatten(seen_event[ekey]);
232 |
233 | seen = seen && (x == eval);
234 | };
235 | };
236 |
237 | if (seen == true) {
238 | ^true;
239 | };
240 | };
241 |
242 | ^false;
243 | }
244 |
245 | flatten {
246 | | obj |
247 |
248 | if (obj.isKindOf(Skoarpuscle)) {
249 | obj = obj.val;
250 | };
251 |
252 | if (obj.isKindOf(Array)) {
253 | var a = [];
254 | obj.do {
255 | | x |
256 | a = a.add(this.flatten(x));
257 | };
258 | obj = a;
259 | };
260 |
261 | ^obj;
262 | }
263 | }
264 |
--------------------------------------------------------------------------------
/SuperCollider/examples/brandnewshoes.scd:
--------------------------------------------------------------------------------
1 | (x = "
2 | 80 => )
3 |
4 | => @key
5 | 5 => @transpose
6 |
7 | .melody @bass => @instrument pp o~
8 | .bass @bass => @instrument o~~ mp
9 | .wah @sillyvoice => @instrument o~~~ mf
10 |
11 | .tom @tom => @instrument ~o pp
12 | .kik @kik => @instrument ~~o pp
13 | .snare @kraftySnr => @instrument ff
14 |
15 | 0
16 |
17 | .wah {: }}} ))) :: 2 times :} {: ))) :: 20 times :}
18 | .bass oo/ {: ] ] :: 20 times :}
19 | .tom {: ] ] :: 20 times :} {: {? 4 times ?? o/ ]] oo/ ?? ] ] ?} :: 80 times :}
20 | .snare }}}} {: {? 5 times ?? o/ ] ?? ]] fff oo/ ]] ]] ff ?} :: 60 times :}
21 |
22 | .kik }}}} {: ] ] :: 7 times :}
23 | .kik {: {? 20 times ?? ] ]] ]] ?? oo/. ]]] ] oo/. ]]] ] oo/. ]]] ] oo/. ]]] ] ?} :: 70 times :}
24 |
25 | .bass {: {? 10 times ?? <0,0,2,3>.choose ] ] ?? <<0,1,0,1,0,1,0,1>,<0,1,0,2,0,3,5,5>>.choose.{: ]]] :} ?} :: 76 times :}
26 |
27 | .melody } ] } oo/ ]] ] }}}
28 | .melody {: 2.rand <$, $+1, $+2.rand>.{: $ => @x {? 3 times ?? !x ]] ]] $+2 ]] ]] $+3 ]] ]] ?? !x ]] ]] ]] o/ ?} :} :: 3 times :}
29 |
30 | .melody {: 3.rand <$, $+1, $+2.rand>.{: $ => @x {? 3 times ?? !x ] oo/ ]] ]] oo/ ]] oo/ ?? !x ] ] ] oo/ $+1 ]] ?} :} :: 6 times :}
31 |
32 | .melody {: 3.rand <$, $+1, $+2.rand>.{: $ => @x {? 3 times ?? !x ]] ]] $+2 ]] ]] $+3 ]] ]] ?? !x ]] ]] ]] ]] ]] ]] ?} :} :: 3 times :}
33 |
34 | .melody <0,1,2,3,4,5,6,7,8>.{: ]]] :} ooo/
35 | .melody {: 3.rand + 2 <$, $+1, $+2>.{: $ => @x {? 3 times ?? !x ]] ]] $+2 ]] ]] $+3 ]] ]] ?? !x ]] ]] ]] ]] ]] ]] ?} :} :: 3 times :}
36 |
37 | .melody {: 3.rand + 6 <$, $+1.rand+1, $+3>.{: $ => @x {? 3 times ?? !x ]]] ]]] ]] o/ ]]] ]]] ]] ?? !x ]] ]] o/ ]] ]] ?} :} :: 3 times :}
38 |
39 | .melody <0,1,2,3,4,5,6,7,8,9,10>.{: ]]] :} ooo/ )
40 |
41 | ".skoar.play;
42 | )
43 |
--------------------------------------------------------------------------------
/SuperCollider/examples/dungeontimes.scd:
--------------------------------------------------------------------------------
1 | // first boot the server (Ctrl-B)
2 | // then load the synthdefs from synthdefs.scd (run the entire file) (if you don't want to do that remove the @instrument line)
3 | // then run this.
4 |
5 | ("
6 |
7 | 80 => )
8 |
9 | @plucking => @instrument
10 |
11 | .high mf
12 | .low o~~ ff
13 |
14 | ,segno`
15 | 4/4
16 |
17 | .high | _g ]] _a# ]] d ]] d# ]] _g ]] _a# ]] d ]] d# ]] _g ]] _a# ]] d ]] d# ]] _g ]] _a# ]] d ]] d# ]] |
18 | .low | g )) a# ) ~o d ) |
19 |
20 | .high | _f# ]] _a# ]] d ]] d# ]] _f# ]] _a# ]] d ]] d# ]] _f# ]] _a# ]] d ]] d# ]] _f# ]] _a# ]] d ]] d# ]] |
21 | .low | c# ) o~ f# )). |
22 |
23 | .high | _f ]] _g# ]] d ]] d# ]] _f ]] _g# ]] d ]] d# ]] _f ]] _g# ]] d ]] d# ]] _f ]] _g# ]] d ]] d# ]] |
24 | .low | f )) f ]. g# ]. ~o c# ] |
25 |
26 | .high | _e ]] _g ]] d ]] d# ]] _e ]] _g ]] d ]] d# ]] _e ]] _g ]] d ]] d# ]] _e ]] _g ]] d ]] d# ]] |
27 | .low | c ) o~ e )). |
28 |
29 | .high | _d# ]] _g ]] c ]] d ]] _d# ]] _g ]] c ]] d ]] _d# ]] _g ]] c ]] d ]] _d# ]] _g ]] c ]] d ]] |
30 | .low | _d# ]] _d ]] _d# ). g ]. ~o d# ]. d ] o~ |
31 |
32 | .high | _d ]] _g ]] c ]] d ]] _d ]] _g ]] c ]] d ]] _d ]] _g ]] c ]] d ]] _d ]] _g ]] c ]] d ]] |
33 | .low | _d ]] _c# ]] _d ). g ]. ~o d ]. c# ] o~ |
34 |
35 | 5/4
36 |
37 | .low ~o
38 |
39 | .high | _c ]] _f# ]] _a ]] c ]] _f# ]] _a ]] c ]] d# ]] _a ]] c ]] d# ]] c ]] d# ]] f# ]] d# ]] f# ]] a ]] _f# ]] a ]] ~o c ]] | o~
40 | .low | _d ]] _f# ]] _a ]] _f# ]] _a ]] c ]] _a ]] c ]] d# ]] c ]] d# ]] ~o f# ]] a ]] f# ]] d# ]] c ]] d# ]] c ]] _a ]] _f# ]] | o~~
41 |
42 | D.S.
43 |
44 | ".skoar.play;
45 | )
46 |
47 |
--------------------------------------------------------------------------------
/SuperCollider/examples/synthdefs.scd:
--------------------------------------------------------------------------------
1 | // these are supercollider instruments. Gathered from around.
2 | // go see https://github.com/brunoruviaro/SynthDefs-for-Patterns for more.
3 |
4 | SynthDef(\blips, {arg out = 0, freq = 25, numharm = 10, att = 0.01, rel = 1, amp = 0.1, pan = 0.5;
5 | var snd, env;
6 | env = Env.perc(att, rel, amp).kr(doneAction: 2);
7 | snd = LeakDC.ar(Mix(Blip.ar([freq, freq*1.01], numharm, env)));
8 | Out.ar(out, Pan2.ar(snd, pan));
9 | }).add;
10 |
11 |
12 | SynthDef(\sawpulse, { |out, freq = 440, gate = 0.5, plfofreq = 6, mw = 0,
13 | ffreq = 2000, rq = 0.3, freqlag = 0.05, amp = 1|
14 | var sig, plfo, fcurve;
15 | plfo = SinOsc.kr(plfofreq, mul:mw, add:1);
16 | freq = Lag.kr(freq, freqlag) * plfo;
17 | fcurve = EnvGen.kr(Env.adsr(0, 0.3, 0.1, 20), gate);
18 | fcurve = (fcurve - 1).madd(0.7, 1) * ffreq;
19 | sig = Mix.ar([Pulse.ar(freq, 0.9), Saw.ar(freq*1.007)]);
20 | sig = RLPF.ar(sig, fcurve, rq)
21 | * EnvGen.kr(Env.adsr(0.04, 0.2, 0.6, 0.1), gate, doneAction:2)
22 | * amp;
23 | Out.ar(out, sig ! 2)
24 | }).add;
25 |
26 | // kick -------
27 | // http://www.soundonsound.com/sos/jan02/articles/synthsecrets0102.asp
28 | // increase mod_freq and mod_index for interesting electronic percussion
29 |
30 | SynthDef(\kick,
31 | { arg out = 0, freq = 50, mod_freq = 5, mod_index = 5, sustain = 0.4, amp = 0.8, beater_noise_level = 0.025;
32 | var pitch_contour, drum_osc, drum_lpf, drum_env;
33 | var beater_source, beater_hpf, beater_lpf, lpf_cutoff_contour, beater_env;
34 | var kick_mix;
35 |
36 | // hardcoding, otherwise skoar will set to the length of the noat ) ] ]]] etc
37 | sustain = 0.4;
38 | freq = 50;
39 |
40 | pitch_contour = Line.kr(freq*2, freq, 0.02);
41 | drum_osc = PMOsc.ar( pitch_contour,
42 | mod_freq,
43 | mod_index/1.3,
44 | mul: 1,
45 | add: 0);
46 | drum_lpf = LPF.ar(in: drum_osc, freq: 1000, mul: 1, add: 0);
47 | drum_env = drum_lpf * EnvGen.ar(Env.perc(0.005, sustain), 1.0, doneAction: 2);
48 | beater_source = WhiteNoise.ar(beater_noise_level);
49 | beater_hpf = HPF.ar(in: beater_source, freq: 500, mul: 1, add: 0);
50 | lpf_cutoff_contour = Line.kr(6000, 500, 0.03);
51 | beater_lpf = LPF.ar(in: beater_hpf, freq: lpf_cutoff_contour, mul: 1, add: 0);
52 | beater_env = beater_lpf * EnvGen.ar(Env.perc, 1.0, doneAction: 2);
53 | kick_mix = Mix.new([drum_env, beater_env]) * 2 * amp;
54 | Out.ar(out, [kick_mix, kick_mix])
55 | }).add;
56 |
57 |
58 | // snare -------
59 | // http://www.soundonsound.com/sos/Mar02/articles/synthsecrets0302.asp
60 | SynthDef(\snare,
61 | {arg out = 0, sustain = 0.1, drum_mode_level = 0.25,
62 | snare_level = 40, snare_tightness = 1000,
63 | freq = 405, amp = 0.8;
64 | var drum_mode_sin_1, drum_mode_sin_2, drum_mode_pmosc, drum_mode_mix, drum_mode_env;
65 | var snare_noise, snare_brf_1, snare_brf_2, snare_brf_3, snare_brf_4, snare_reson;
66 | var snare_env;
67 | var snare_drum_mix;
68 |
69 | sustain = 0.1;
70 | freq = 405;
71 |
72 | drum_mode_env = EnvGen.ar(Env.perc(0.005, sustain), 1.0, doneAction: 2);
73 | drum_mode_sin_1 = SinOsc.ar(freq*0.53, 0, drum_mode_env * 0.5);
74 | drum_mode_sin_2 = SinOsc.ar(freq, 0, drum_mode_env * 0.5);
75 | drum_mode_pmosc = PMOsc.ar( Saw.ar(freq*0.85),
76 | 184,
77 | 0.5/1.3,
78 | mul: drum_mode_env*5,
79 | add: 0);
80 | drum_mode_mix = Mix.new([drum_mode_sin_1, drum_mode_sin_2, drum_mode_pmosc]) * drum_mode_level;
81 |
82 | snare_noise = LFNoise0.ar(20000, 0.1);
83 | snare_env = EnvGen.ar(Env.perc(0.005, sustain), 1.0, doneAction: 2);
84 | snare_brf_1 = BRF.ar(in: snare_noise, freq: 8000, mul: 0.5, rq: 0.1);
85 | snare_brf_2 = BRF.ar(in: snare_brf_1, freq: 5000, mul: 0.5, rq: 0.1);
86 | snare_brf_3 = BRF.ar(in: snare_brf_2, freq: 3600, mul: 0.5, rq: 0.1);
87 | snare_brf_4 = BRF.ar(in: snare_brf_3, freq: 2000, mul: snare_env, rq: 0.0001);
88 | snare_reson = Resonz.ar(snare_brf_4, snare_tightness, mul: snare_level) ;
89 | snare_drum_mix = Mix.new([drum_mode_mix, snare_reson]) * 5 * amp;
90 | Out.ar(out, [snare_drum_mix, snare_drum_mix]);
91 | }).add;
92 |
93 | // hats -------
94 | // http://www.soundonsound.com/sos/Jun02/articles/synthsecrets0602.asp
95 | SynthDef(\hats,
96 | {arg out = 0, freq = 6000, sustain = 0.1, amp = 0.8;
97 | var root_cymbal, root_cymbal_square, root_cymbal_pmosc;
98 | var initial_bpf_contour, initial_bpf, initial_env;
99 | var body_hpf, body_env;
100 | var cymbal_mix;
101 |
102 | amp = amp * 0.5;
103 | sustain = 0.1;
104 | freq = 6000;
105 |
106 | root_cymbal_square = Pulse.ar(freq, 0.5, mul: 1);
107 | root_cymbal_pmosc = PMOsc.ar(root_cymbal_square,
108 | [freq*1.34, freq*2.405, freq*3.09, freq*1.309],
109 | [310/1.3, 26/0.5, 11/3.4, 0.72772],
110 | mul: 1,
111 | add: 0);
112 | root_cymbal = Mix.new(root_cymbal_pmosc);
113 | initial_bpf_contour = Line.kr(15000, 9000, 0.1);
114 | initial_env = EnvGen.ar(Env.perc(0.005, 0.1), 1.0);
115 | initial_bpf = BPF.ar(root_cymbal, initial_bpf_contour, mul:initial_env);
116 | body_env = EnvGen.ar(Env.perc(0.005, sustain, 1, -2), 1.0, doneAction: 2);
117 | body_hpf = HPF.ar(in: root_cymbal, freq: Line.kr(9000, 12000, sustain),mul: body_env, add: 0);
118 | cymbal_mix = Mix.new([initial_bpf, body_hpf]) * amp;
119 | Out.ar(out, [cymbal_mix, cymbal_mix])
120 | }).add;
121 |
122 | SynthDef("PMCrotale", {
123 | arg freq = 261, tone = 3, art = 1, amp = 0.8, pan = 0;
124 | var env, out, mod;
125 |
126 | env = Env.perc(0, art);
127 | mod = 5 + (1/IRand(2, 6));
128 |
129 | out = PMOsc.ar(freq, mod*freq,
130 | pmindex: EnvGen.kr(env, timeScale: art, levelScale: tone),
131 | mul: EnvGen.kr(env, timeScale: art, levelScale: 0.3));
132 |
133 | out = Pan2.ar(out, pan);
134 |
135 | out = out * EnvGen.kr(env, timeScale: 1.3*art,
136 | levelScale: Rand(0.1, 0.5), doneAction:2);
137 | Out.ar(0, out*amp); //Out.ar(bus, out);
138 |
139 | }).add;
140 |
141 |
142 |
143 |
144 |
145 | SynthDef("kick3", {arg punch = 1, amp = 1;
146 | var freq = EnvGen.kr(Env([400, 66], [0.08], -3)),
147 | sig = Normalizer.ar(SinOsc.ar(freq, 0.5pi, punch).distort, 1) * amp
148 | * EnvGen.kr(Env([0, 1, 0.8, 0], [0.01, 0.1, 0.2]), doneAction: 2);
149 | Out.ar(0, sig ! 2);
150 | }).add;
151 |
152 |
153 |
154 | SynthDef("ringkick", {arg freq = 40, decay = 0.25, amp = 1;
155 | var snd;
156 | snd = Ringz.ar(
157 | in: LPF.ar(
158 | in: Impulse.ar(0),
159 | freq: 1000),
160 | freq: freq,
161 | decaytime: decay,
162 | mul: 7 * amp).tanh.sin*2;
163 | Out.ar(0, snd!2);
164 | }).add;
165 |
166 |
167 |
168 | SynthDef("beating", {arg freq = 440, amp = 0.1, art = 1;
169 | var env, snd1, snd2;
170 | env = EnvGen.ar(Env.perc(0.01, art), doneAction: 2);
171 | snd1 = SinOsc.ar(freq);
172 | snd2 = SinOsc.ar(Line.kr(freq+15, freq, art));
173 | Out.ar(0, Pan2.ar(Mix([snd1, snd2]), 0, amp*env))
174 | }).add;
175 |
176 | SynthDef("bass", { |freq = 440, gate = 1, amp = 0.5, slideTime = 0.17, ffreq = 1100, width = 0.15, detune = 1.005, preamp = 4|
177 | var sig, env;
178 | env = Env.adsr(0.01, 0.3, 0.4, 0.1);
179 | freq = Lag.kr(freq, slideTime);
180 | sig = Mix(VarSaw.ar([freq, freq * detune], 0, width, preamp)).distort;
181 | sig = sig * amp * EnvGen.kr(env, gate, doneAction: 2);
182 | sig = LPF.ar(sig, ffreq);
183 | Out.ar(0, sig ! 2)
184 | }).add;
185 |
186 | SynthDef("kik", { |basefreq = 50, ratio = 7, sweeptime = 0.05, preamp = 1, amp = 1, decay1 = 0.3, decay1L = 0.8, decay2 = 0.15, out|
187 | var fcurve = EnvGen.kr(Env([basefreq * ratio, basefreq], [sweeptime], \exp)),
188 | env = EnvGen.kr(Env([1, decay1L, 0], [decay1, decay2], -4), doneAction: 2),
189 | sig = SinOsc.ar(fcurve, 0.5pi, preamp).distort * env * amp;
190 | Out.ar(out, sig ! 2)
191 | }).add;
192 |
193 | SynthDef("kraftySnr", { |amp = 1, freq = 2000, rq = 3, decay = 0.3, pan, out|
194 | var sig = PinkNoise.ar(amp),
195 | env = EnvGen.kr(Env.perc(0.01, decay), doneAction: 2);
196 | sig = BPF.ar(sig, freq, rq, env);
197 | Out.ar(out, Pan2.ar(sig, pan))
198 | }).add;
199 |
200 | SynthDef("sillyvoice", { arg
201 | freq = 220,
202 | amp = 0.5,
203 | vibratoSpeed = 6,
204 | vibratoDepth = 4,
205 | vowel = 0,
206 | att = 0.01,
207 | rel = 0.1,
208 | lag = 1,
209 | gate = 1;
210 |
211 | var in, vibrato, env, va, ve, vi, vo, vu, snd;
212 |
213 | vibrato = SinOsc.kr(vibratoSpeed, mul: vibratoDepth);
214 | in = Saw.ar(Lag.kr(freq, lag) + vibrato);
215 | env = EnvGen.kr(Env.asr(att, 1, rel), gate, doneAction: 2);
216 |
217 | va = BBandPass.ar(
218 | in: in,
219 | freq: [ 600, 1040, 2250, 2450, 2750 ],
220 | bw: [ 0.1, 0.067307692307692, 0.048888888888889, 0.048979591836735, 0.047272727272727 ],
221 | mul: [ 1, 0.44668359215096, 0.35481338923358, 0.35481338923358, 0.1 ]);
222 |
223 | ve = BBandPass.ar(
224 | in: in,
225 | freq: [ 400, 1620, 2400, 2800, 3100 ] ,
226 | bw: [ 0.1, 0.049382716049383, 0.041666666666667, 0.042857142857143, 0.038709677419355 ],
227 | mul: [ 1, 0.25118864315096, 0.35481338923358, 0.25118864315096, 0.12589254117942 ]);
228 |
229 | vi = BBandPass.ar(
230 | in: in,
231 | freq: [ 250, 1750, 2600, 3050, 3340 ] ,
232 | bw: [ 0.24, 0.051428571428571, 0.038461538461538, 0.039344262295082, 0.035928143712575 ],
233 | mul: [ 1, 0.031622776601684, 0.15848931924611, 0.079432823472428, 0.03981071705535 ] );
234 |
235 | vo = BBandPass.ar(
236 | in: in,
237 | freq:[ 400, 750, 2400, 2600, 2900 ] ,
238 | bw: [ 0.1, 0.10666666666667, 0.041666666666667, 0.046153846153846, 0.041379310344828 ],
239 | mul: [ 1, 0.28183829312645, 0.089125093813375, 0.1, 0.01 ]);
240 |
241 | vu = BBandPass.ar(
242 | in: in,
243 | freq: [ 350, 600, 2400, 2675, 2950 ],
244 | bw: [ 0.11428571428571, 0.13333333333333, 0.041666666666667, 0.044859813084112, 0.040677966101695 ],
245 | mul: [ 1, 0.1, 0.025118864315096, 0.03981071705535, 0.015848931924611 ]);
246 |
247 | snd = SelectX.ar(Lag.kr(vowel, lag), [va, ve, vi, vo, vu]);
248 | snd = Mix.new(snd);
249 | Out.ar(0, snd!2 * env * amp);
250 | }).add;
251 |
252 | SynthDef("plucking", {arg amp = 0.1, freq = 440, decay = 5, coef = 0.1;
253 | var env, snd;
254 | env = EnvGen.kr(Env.linen(0, decay, 0), doneAction: 2);
255 | snd = Pluck.ar(
256 | in: WhiteNoise.ar(amp),
257 | trig: Impulse.kr(0),
258 |
259 | maxdelaytime: 0.1,
260 | delaytime: freq.reciprocal,
261 | decaytime: decay,
262 | coef: coef);
263 | Out.ar(0, [snd, snd]);
264 | }).add;
265 |
266 | SynthDef("defaultB", { arg out=0, freq=440, amp=0.1, pan=0, gate=1;
267 | var z;
268 | z = LPF.ar(
269 | Mix.new(VarSaw.ar(freq + [0, Rand(-0.4,0.0), Rand(0.0,0.4)], 0, 0.3)),
270 | XLine.kr(Rand(4000,5000), Rand(2500,3200), 1)
271 | ) * Linen.kr(gate, 0.01, 0.7, 0.3, 2);
272 | OffsetOut.ar(out, Pan2.ar(z, pan, amp));
273 | }, [\ir]).add;
274 |
275 | SynthDef("trig_demo", { |freq = 440, gate = 1, t_trig = 1|
276 | var env, sig;
277 | env = Decay2.kr(t_trig, 0.01, 0.1);
278 | sig = SinOsc.ar(freq, 0, env);
279 | sig = sig * Linen.kr(gate, 0.01, 0.1, 0.1, doneAction: 2);
280 | Out.ar(0, sig ! 2)
281 | }).add;
282 |
283 | SynthDef("marimba1", {arg freq = 440, amp = 0.4;
284 | var snd, env;
285 | env = Env.linen(0.015, 1, 0.5, amp).kr(doneAction: 2);
286 | snd = BPF.ar(Saw.ar(0), freq, 0.02);
287 | snd = BLowShelf.ar(snd, 220, 0.81, 6);
288 | snd = snd * env;
289 | Out.ar(0, Splay.ar(snd));
290 | }).add;
291 |
292 | SynthDef("trianglewavebells",{
293 | arg out = 0, pan = 0.0, freq = 440, amp = 1.0, gate = 1, att = 0.01, dec = 0.1, sus = 1, rel = 0.5, lforate = 10, lfowidth = 0.0, cutoff = 100, rq = 0.5;
294 |
295 | var osc1, osc2, vibrato, filter, env;
296 | vibrato = SinOsc.ar(lforate, Rand(0, 2.0));
297 | osc1 = Saw.ar(freq * (1.0 + (lfowidth * vibrato)), 0.75);
298 | osc2 = Mix(LFTri.ar((freq.cpsmidi + [11.9, 12.1]).midicps));
299 | filter = RHPF.ar((osc1 + (osc2 * 0.5)) * 0.5, cutoff, rq);
300 | env = EnvGen.ar(
301 | envelope: Env.adsr(att, dec, sus, rel, amp),
302 | gate: gate,
303 | doneAction: 2);
304 | Out.ar(out, Pan2.ar(filter * env, pan));
305 | }).add;
306 |
307 |
308 | SynthDef("organdonor",{
309 | arg out = 0, pan = 0.0, freq = 440, amp = 0.1, gate = 1, att = 0.01, dec = 0.5, sus = 1, rel = 0.5, lforate = 10, lfowidth = 0.01, cutoff = 100, rq = 0.5;
310 |
311 | var vibrato, pulse, filter, env;
312 | vibrato = SinOsc.ar(lforate, Rand(0, 2.0));
313 | // up octave, detune by 4 cents
314 | // 11.96.midiratio = 1.9953843530485
315 | // up octave and a half, detune up by 10 cents
316 | // 19.10.midiratio = 3.0139733629359
317 | freq = freq * [1, 1.9953843530485, 3.0139733629359];
318 | freq = freq * (1.0 + (lfowidth * vibrato));
319 | pulse = VarSaw.ar(
320 | freq: freq,
321 | iphase: Rand(0.0, 1.0) ! 3,
322 | width: Rand(0.3, 0.5) ! 3,
323 | mul: [1.0,0.7,0.3]);
324 | pulse = Mix(pulse);
325 | filter = RLPF.ar(pulse, cutoff, rq);
326 | env = EnvGen.ar(
327 | envelope: Env.adsr(att, dec, sus, rel, amp),
328 | gate: gate,
329 | doneAction: 2);
330 | Out.ar(out, Pan2.ar(filter * env, pan));
331 | }).add;
332 |
333 | SynthDef(\mario, { |out, amp=0.3, freq=440, att=0.001, sustain=0.3, rel=0.03, dur=1|
334 | var snd;
335 | snd = LFPulse.ar(freq)!2;
336 | snd = snd * EnvGen.ar(Env.linen(att, sustain * 0.5, rel), doneAction:2);
337 | OffsetOut.ar(out, snd*amp*0.5);
338 | }).add;
339 |
--------------------------------------------------------------------------------
/SuperCollider/examples/windwaker.scd:
--------------------------------------------------------------------------------
1 | (
2 |
3 | //MIDIClient.init;
4 | //MIDIClient.destinations;
5 |
6 | b = "
7 | Zelda Wind Waker Theme - inspired by piano arrangement by Shinobu Amayake ?>
8 |
9 | Let's play the skoar on a midi device ?>
10 | @MIDIOut.new<0> => @midiout
11 | @midi => @type
12 |
13 |
14 | key is Db, so i flat everything and sharp c & f ?>
15 | -1 => @transpose
16 |
17 | 9/8 120 => ).
18 |
19 | mf
20 |
21 | .mel | ottava alta }}} o/ | }}} o/ | }}} o/ | }}} o/ |
22 |
23 | .mel | _a) d] f#) e] d) c#] | d) _b] _g) c#] _a] d] _b] |
24 | .mel | c#) _a] _g) d] _b) c#] | d) e]] ]] f#] d] e] _a) ] |
25 | .mel | _a) d]] e]] f#) e] d) c#] | d) _b] _g) c#] _a] d] _b] |
26 | .mel | c#) d] e) f#]] ]] g] e] c#] | d) oo/ e]] d). _a) ] |
27 |
28 | .mel | _a) d]] e]] f#) e] d) c#] | e]] d]. _b] _g) c#] _a] d] _b] | c#) _a] _g) d] _b) c#] | ]] d]] e]] ]] f#] d] e] _a) ] |
29 | .mel | _a) d]] e]] f#) e] d) c#] | d) _b] _g) c#] _a] d] _b] | c#) d] e) f#]] ]] g] e] c#] | d) oo/ e]] d). a) ] |
30 |
31 | .mel |: g] f#] e] f#) d] c#] d] e] | a] d] ] g] d] ] f#) ] | g] a] b] b] g] e] a) a] | g] f#] d] e] f#] e]] f#]] e) ] |
32 | .mel | d] c#] d] e) e] a] g] c#] | g] d] ] f#) ] e] c#] e] | d] b] d] g] a] b] f# d] g] | e). ] f#] e] a) ] :|
33 |
34 | .mel | <_a,_c#,d> )). }. | d )). }. | <_a,_c#,d> )). }. | <_a,_f#> )). _a ) ] |
35 |
36 | ".skoar;
37 |
38 |
39 |
40 |
41 |
42 | )
--------------------------------------------------------------------------------
/SuperCollider/examples/yay.scd:
--------------------------------------------------------------------------------
1 | ("
2 | pp
3 | 60 => )
4 | <_c, _e, _a, c, e, a, f> => @notes
5 |
6 | .b o~
7 | .c o~~ mf
8 |
9 | {! foo !!
10 | .a !notes.choose {: ] } } ]] :: !x times :}
11 | .b !notes.choose {: ] :: !x times :}
12 | .c !notes.choose {: ) :: !x times :}
13 | !}
14 |
15 | {: !foo<<1,2,3>.choose> :: true :}
16 |
17 | ".skoar.play;
18 | )
19 |
20 |
--------------------------------------------------------------------------------
/SuperCollider/examples/zelda.scd:
--------------------------------------------------------------------------------
1 | // First load the synthdefs from examples/synthdefs.scd"
2 |
3 | (
4 | x = "
5 | Zelda Theme - inspired by piano arrangement by Shinobu Amayake ?>
6 |
7 | 130 => )
8 |
9 | .alice @default => @instrument [##### ] => @amp
10 | .bob @default => @instrument [##### ] => @amp
11 | .bass @sawpulse => @instrument [### ] => @amp o~~~~
12 | .hats @hats => @instrument [## ] => @amp
13 | .snare @snare => @instrument [## ] => @amp
14 | .kick @kick => @instrument [### ] => @amp
15 |
16 | {! bass_end !! !x ) ) ) ] ] !}
17 | {! bass_climb !! | _e ]] _a# ]] c# ] e ]] a# ]] ~o c# ] e ) } | f ) o~ _f ]] ]] ] ) } | !}
18 |
19 | {! bassline_a !!
20 | .{: .) ]] ]] ] ) ) :}
21 | !bass_end
22 | !}
23 |
24 | {! bassline_b !!
25 | .{: ) ]] ]] ] ) ) :}
26 |
27 | !bass_climb !bass_climb
28 |
29 | .{: ) ]] ]] ] ) ) :} !bass_end
30 | !}
31 |
32 |
33 | {! intro !!
34 |
35 | .hats {: }}} :: 4 times :}
36 | .snare {: }}} :: 4 times :}
37 | .kick {: }}} :: 4 times :}
38 |
39 | .alice | _a# )) o/. ]] ]] ]] ] | ]. _g# ]] _a# ) o/. ]] ]] ]] ] |
40 | .bob | _d )) o/. ]] ]] ]] ] | _c ]. ]] ) o/. ]] ]] ]] ] |
41 | .bass | a# ) ]] ]] ] ) ]] ]] ] | g# ) ]] ]] ] ) ]] ]] ] |
42 |
43 | .alice | ]. _g# ]] _a# ) o/. ]] ]] ]] ] | ] _f ]] ]] ] ]] ]] ] ]] ]] ] ] |
44 | .bob | _c# ]. ]] ) o/. ]] ]] ]] ] | ] o~ _a ]] ]] ] ]] ]] ] ]] ]] ] ] |
45 | .bass | f# ) ]] ]] ] ) ]] ]] ] | f ) ) ) g ] a ] |
46 | !}
47 |
48 | {! melody_a !!
49 |
50 | .bass !bassline_a
51 |
52 | .hats {: }}} :: 7 times :} | ] ] ] ] ] ] ] ] |
53 | .snare {: }}} :: 8 times :}
54 | .kick {: }}} :: 8 times :}
55 |
56 | .alice | _a# ) _f )__ o/. _a# ]] ]] c ]] d ]] d# ]] |
57 | .bob | _d ) ]] ]] _c ] _d ]. ]] ]] _d# ]] _f ]] _g ]] |
58 |
59 | .alice | f )) o/ ] f ] f# ]] g# ]] |
60 | .bob | _g# ]. _a# ]] ]] c ]] d ]] d# ]] f ) _g# ] _a# ]] c ]] |
61 |
62 | .alice | a# )) o/ a# ] ] g# ]] f# ]] |
63 | .bob | c# ]. _f# ]] ]] _g# ]] _a# ]] c ]] c# ]. ]] ] c ]] _a# ]] |
64 |
65 | .alice | g# ]. f# ]] f )) ) |
66 | .bob | c# ]. _g# ]] ]] ]] _f# ] _g# ]. ]] ]] _f# ]] _g# ] |
67 |
68 | .alice | d# ] ]] f ]] f# )) f ] d# ] |
69 | .bob | _f# ] ]] _f ]] _f# ] ]] _g# ]] _a# ) _g# ] _f# ] |
70 |
71 | .alice | c# ] ]] d# ]] f )) d# ] c# ] |
72 | .bob | _f ] ]] _d# ]] _f ] ]] _f# ]] _g# ) _f# ] _d# ] |
73 |
74 | .alice | c ] ]] d ]] e )) g ) |
75 | .bob | _e ] ]] _d ]] _e ] ]] _g ] ]] _a ]] ]] _a# ] c ] |
76 |
77 | .alice | f ] _f ]] ]] ] ]] ]] ] ]] ]] ] ] |
78 | .bob | _a ] o~ _a ]] ]] ] ]] ]] ] ]] ]] ] ] ~o |
79 |
80 | !}
81 |
82 |
83 | {! melody_b !!
84 |
85 | .bass !bassline_b
86 |
87 | .hats {: ] ] ] ] ] ] ] ]] ]] :: 12 times :}
88 | .kick {: ) } ) } :: 12 times :}
89 | .snare {: } ) } ) :: 11 times :} | ] ]] ]] ] ]] ]] ] ] |
90 |
91 | .alice | _a# ) _f ) o/. _a# ]] ]] c ]] d ]] d# ]] |
92 | .bob | _d ) ]] ]] _c ] _d ]. ]] ]] _d# ]] _f ]] _g ]] |
93 |
94 | .alice | f )) o/ ] f ] f# ]] g# ]] |
95 | .bob | _g# ]. _a# ]] ]] c ]] d ]] d# ]] f ) _g# ] _a# ]] c ]] |
96 |
97 | .alice | a# )). ~o c# ) | c ) o~ a )) f ) | f# )). a# ) | a ) f )) ) |
98 | .bob | c# )). e ) | d# ) c )) _a ) | _b )). c# ) | c ) _a )) ) |
99 |
100 | .alice | f# )). a# ) | a ) f )) d ) | d# )). f# ) | f ) c# )) _a# ) |
101 | .bob | _b )). c# ) | c ) _a )) ) | _f# )). _b ) | _a# ) _f )) _c# ) |
102 |
103 | .alice | c ] ]] d ]] e )) g ) |
104 | .bob | _e ] ]] _d ]] _e ] ]] _f ]] _g ] ]] _a ]] _a# ] c ] |
105 |
106 | .alice | f ] _f ]] ]] ] ]] ]] ] ]] ]] ] ] |
107 | .bob | _a ] o~ _a ]] ]] ] ]] ]] ] ]] ]] ] ] ~o |
108 |
109 | !}
110 |
111 | {! fill !!
112 | .alice | f ] _f ]] ]] ] ]] ]] ] ]] ]] ] ] |
113 | .bob | _a ] o~ _a ]] ]] ] ]] ]] ] ]] ]] ] ] ~o |
114 | .snare | ] ]] ]] ] ]] ]] ] ]] ]] ] ] |
115 | .hats | ] ] ] ] ] ] ] ] |
116 | .kick | ) } ) ) |
117 | .bass !bass_end
118 | !}
119 |
120 | !intro
121 | !melody_a
122 | !fill
123 | !melody_b
124 | !fill
125 |
126 | ".skoar;
127 | )
128 |
129 | x.play;
130 |
--------------------------------------------------------------------------------
/SuperCollider/testing/bigskoar.scd:
--------------------------------------------------------------------------------
1 |
2 | SynthDef(\sawpulse, { |out, freq = 440, gate = 0.5, plfofreq = 6, mw = 0,
3 | ffreq = 2000, rq = 0.3, freqlag = 0.05, amp = 1|
4 | var sig, plfo, fcurve;
5 | plfo = SinOsc.kr(plfofreq, mul:mw, add:1);
6 | freq = Lag.kr(freq, freqlag) * plfo;
7 | fcurve = EnvGen.kr(Env.adsr(0, 0.3, 0.1, 20), gate);
8 | fcurve = (fcurve - 1).madd(0.7, 1) * ffreq;
9 | sig = Mix.ar([Pulse.ar(freq, 0.9), Saw.ar(freq*1.007)]);
10 | sig = RLPF.ar(sig, fcurve, rq)
11 | * EnvGen.kr(Env.adsr(0.04, 0.2, 0.6, 0.1), gate, doneAction:2)
12 | * amp;
13 | Out.ar(out, sig ! 2)
14 | }).add;
15 |
16 | // kick -------
17 | // http://www.soundonsound.com/sos/jan02/articles/synthsecrets0102.asp
18 | // increase mod_freq and mod_index for interesting electronic percussion
19 |
20 | SynthDef(\kick,
21 | { arg out = 0, freq = 50, mod_freq = 5, mod_index = 5, sustain = 0.4, amp = 0.8, beater_noise_level = 0.025;
22 | var pitch_contour, drum_osc, drum_lpf, drum_env;
23 | var beater_source, beater_hpf, beater_lpf, lpf_cutoff_contour, beater_env;
24 | var kick_mix;
25 |
26 | // hardcoding, otherwise skoar will set to the length of the noat ) ] ]]] etc
27 | sustain = 0.4;
28 | freq = 50;
29 |
30 | pitch_contour = Line.kr(freq*2, freq, 0.02);
31 | drum_osc = PMOsc.ar( pitch_contour,
32 | mod_freq,
33 | mod_index/1.3,
34 | mul: 1,
35 | add: 0);
36 | drum_lpf = LPF.ar(in: drum_osc, freq: 1000, mul: 1, add: 0);
37 | drum_env = drum_lpf * EnvGen.ar(Env.perc(0.005, sustain), 1.0, doneAction: 2);
38 | beater_source = WhiteNoise.ar(beater_noise_level);
39 | beater_hpf = HPF.ar(in: beater_source, freq: 500, mul: 1, add: 0);
40 | lpf_cutoff_contour = Line.kr(6000, 500, 0.03);
41 | beater_lpf = LPF.ar(in: beater_hpf, freq: lpf_cutoff_contour, mul: 1, add: 0);
42 | beater_env = beater_lpf * EnvGen.ar(Env.perc, 1.0, doneAction: 2);
43 | kick_mix = Mix.new([drum_env, beater_env]) * 2 * amp;
44 | Out.ar(out, [kick_mix, kick_mix])
45 | }).store;
46 |
47 |
48 | // snare -------
49 | // http://www.soundonsound.com/sos/Mar02/articles/synthsecrets0302.asp
50 | SynthDef(\snare,
51 | {arg out = 0, sustain = 0.1, drum_mode_level = 0.25,
52 | snare_level = 40, snare_tightness = 1000,
53 | freq = 405, amp = 0.8;
54 | var drum_mode_sin_1, drum_mode_sin_2, drum_mode_pmosc, drum_mode_mix, drum_mode_env;
55 | var snare_noise, snare_brf_1, snare_brf_2, snare_brf_3, snare_brf_4, snare_reson;
56 | var snare_env;
57 | var snare_drum_mix;
58 |
59 | sustain = 0.1;
60 | freq = 405;
61 |
62 | drum_mode_env = EnvGen.ar(Env.perc(0.005, sustain), 1.0, doneAction: 2);
63 | drum_mode_sin_1 = SinOsc.ar(freq*0.53, 0, drum_mode_env * 0.5);
64 | drum_mode_sin_2 = SinOsc.ar(freq, 0, drum_mode_env * 0.5);
65 | drum_mode_pmosc = PMOsc.ar( Saw.ar(freq*0.85),
66 | 184,
67 | 0.5/1.3,
68 | mul: drum_mode_env*5,
69 | add: 0);
70 | drum_mode_mix = Mix.new([drum_mode_sin_1, drum_mode_sin_2, drum_mode_pmosc]) * drum_mode_level;
71 |
72 | snare_noise = LFNoise0.ar(20000, 0.1);
73 | snare_env = EnvGen.ar(Env.perc(0.005, sustain), 1.0, doneAction: 2);
74 | snare_brf_1 = BRF.ar(in: snare_noise, freq: 8000, mul: 0.5, rq: 0.1);
75 | snare_brf_2 = BRF.ar(in: snare_brf_1, freq: 5000, mul: 0.5, rq: 0.1);
76 | snare_brf_3 = BRF.ar(in: snare_brf_2, freq: 3600, mul: 0.5, rq: 0.1);
77 | snare_brf_4 = BRF.ar(in: snare_brf_3, freq: 2000, mul: snare_env, rq: 0.0001);
78 | snare_reson = Resonz.ar(snare_brf_4, snare_tightness, mul: snare_level) ;
79 | snare_drum_mix = Mix.new([drum_mode_mix, snare_reson]) * 5 * amp;
80 | Out.ar(out, [snare_drum_mix, snare_drum_mix]);
81 | }).store;
82 |
83 | // hats -------
84 | // http://www.soundonsound.com/sos/Jun02/articles/synthsecrets0602.asp
85 | SynthDef(\hats,
86 | {arg out = 0, freq = 6000, sustain = 0.1, amp = 0.8;
87 | var root_cymbal, root_cymbal_square, root_cymbal_pmosc;
88 | var initial_bpf_contour, initial_bpf, initial_env;
89 | var body_hpf, body_env;
90 | var cymbal_mix;
91 |
92 | amp = amp * 0.5;
93 | sustain = 0.1;
94 | freq = 6000;
95 |
96 | root_cymbal_square = Pulse.ar(freq, 0.5, mul: 1);
97 | root_cymbal_pmosc = PMOsc.ar(root_cymbal_square,
98 | [freq*1.34, freq*2.405, freq*3.09, freq*1.309],
99 | [310/1.3, 26/0.5, 11/3.4, 0.72772],
100 | mul: 1,
101 | add: 0);
102 | root_cymbal = Mix.new(root_cymbal_pmosc);
103 | initial_bpf_contour = Line.kr(15000, 9000, 0.1);
104 | initial_env = EnvGen.ar(Env.perc(0.005, 0.1), 1.0);
105 | initial_bpf = BPF.ar(root_cymbal, initial_bpf_contour, mul:initial_env);
106 | body_env = EnvGen.ar(Env.perc(0.005, sustain, 1, -2), 1.0, doneAction: 2);
107 | body_hpf = HPF.ar(in: root_cymbal, freq: Line.kr(9000, 12000, sustain),mul: body_env, add: 0);
108 | cymbal_mix = Mix.new([initial_bpf, body_hpf]) * amp;
109 | Out.ar(out, [cymbal_mix, cymbal_mix])
110 | }).store;
111 |
112 | x = "
113 |
114 | 130 => )
115 |
116 | .alice <0,3,5> => @detune mp
117 | .bob <0,3,5> => @detune mp
118 | .bass @sawpulse => @instrument mp o~~~~
119 | .hats @hats => @instrument pp
120 | .snare @snare => @instrument mf
121 | .kick @kick => @instrument mf
122 |
123 | {! four_bars_rest !! }}}}} !}
124 | {! eight_bars_rest !! }}}}}} !}
125 | {! twelve_bars_rest !! !four_bars_rest !eight_bars_rest !}
126 |
127 | {! bass_fun !! !x ) ]] ]] ] ) ) !}
128 |
129 | {! bass_end !! !x ) ) ) ] ] !}
130 | {! bass_climb !! | _e ]] _a# ]] c# ] e ]] a# ]] ~o c# ] e ) } | f ) o~ _f ]] ]] ] ) } | !}
131 |
132 | {! bassline_a !!
133 | !bass_fun
134 | !bass_fun
135 | !bass_fun
136 | !bass_fun
137 |
138 | !bass_fun
139 | !bass_fun
140 | !bass_fun
141 | !bass_end
142 | !}
143 |
144 | {! bassline_b !!
145 | !bass_fun
146 | !bass_fun
147 | !bass_fun
148 | !bass_fun
149 |
150 | !bass_climb
151 | !bass_climb
152 |
153 | !bass_fun
154 | !bass_fun
155 | !bass_fun
156 | !bass_end
157 |
158 | !}
159 |
160 | {! intro !!
161 |
162 | .hats !four_bars_rest
163 | .snare !four_bars_rest
164 | .kick !four_bars_rest
165 |
166 | .alice | _a# )) o/. ]] ]] ]] ] | ]. _g# ]] _a# ) o/. ]] ]] ]] ] |
167 | .bob | _d )) o/. ]] ]] ]] ] | _c ]. ]] ) o/. ]] ]] ]] ] |
168 | .bass | a# ) ]] ]] ] ) ]] ]] ] | g# ) ]] ]] ] ) ]] ]] ] |
169 |
170 | .alice | ]. _g# ]] _a# ) o/. ]] ]] ]] ] | ] _f ]] ]] ] ]] ]] ] ]] ]] ] ] |
171 | .bob | _c# ]. ]] ) o/. ]] ]] ]] ] | ] o~ _a ]] ]] ] ]] ]] ] ]] ]] ] ] |
172 | .bass | f# ) ]] ]] ] ) ]] ]] ] | f ) ) ) g ] a ] |
173 | !}
174 |
175 | {! melody_a !! .bass !bassline_a
176 |
177 | .alice | _a# ) _f )__ o/. _a# ]] ]] c ]] d ]] d# ]] |
178 | .bob | _d ) ]] ]] _c ] _d ]. ]] ]] _d# ]] _f ]] _g ]] |
179 |
180 | .alice | f )) o/ ] f ] f# ]] g# ]] |
181 | .bob | _g# ]. _a# ]] ]] c ]] d ]] d# ]] f ) _g# ] _a# ]] c ]] |
182 |
183 | .alice | a# )) o/ a# ] ] g# ]] f# ]] |
184 | .bob | c# ]. _f# ]] ]] _g# ]] _a# ]] c ]] c# ]. ]] ] c ]] _a# ]] |
185 |
186 | .alice | g# ]. f# ]] f )) ) |
187 | .bob | c# ]. _g# ]] ]] ]] _f# ] _g# ]. ]] ]] _f# ]] _g# ] |
188 |
189 | .alice | d# ] ]] f ]] f# )) f ] d# ] |
190 | .bob | _f# ] ]] _f ]] _f# ] ]] _g# ]] _a# ) _g# ] _f# ] |
191 |
192 | .alice | c# ] ]] d# ]] f )) d# ] c# ] |
193 | .bob | _f ] ]] _d# ]] _f ] ]] _f# ]] _g# ) _f# ] _d# ] |
194 |
195 | .alice | c ] ]] d ]] e )) g ) |
196 | .bob | _e ] ]] _d ]] _e ] ]] _g ] ]] _a ]] _a# ] c ] |
197 |
198 | .alice | f ] _f ]] ]] ] ]] ]] ] ]] ]] ] ] |
199 | .bob | _a ] o~ _a ]] ]] ] ]] ]] ] ]] ]] ] ] ~o |
200 |
201 | !}
202 |
203 | {! melody_b !! .bass !bassline_b
204 |
205 | .alice | _a# ) _f )__ o/. _a# ]] ]] c ]] d ]] d# ]] |
206 | .bob | _d ) ]] ]] _c ] _d ]. ]] ]] _d# ]] _f ]] _g ]] |
207 |
208 | .alice | f )) o/ ] f ] f# ]] g# ]] |
209 | .bob | _g# ]. _a# ]] ]] c ]] d ]] d# ]] f ) _g# ] _a# ]] c ]] |
210 |
211 | .alice | a# )). ~o c# ) | c ) o~ a )) f ) | f# )). a# ) | a ) f )) ) |
212 | .bob | c# )). e ) | d# ) c )) _a ) | _b )). c# ) | c ) _a )) ) |
213 |
214 | .alice | f# )). a# ) | a ) f )) d ) | d# )). f# ) | f ) c# )) _a# ) |
215 | .bob | _b )). c# ) | c ) _a )) ) | _f# )). _b ) | _a# ) _f )) _c# ) |
216 |
217 | .alice | c ] ]] d ]] e )) g ) |
218 | .bob | _e ] ]] _d ]] _e ] ]] _f ]] _g ] ]] _a ]] _a# ] c ] |
219 |
220 | .alice | f ] _f ]] ]] ] ]] ]] ] ]] ]] ] ] |
221 | .bob | _a ] o~ _a ]] ]] ] ]] ]] ] ]] ]] ] ] ~o |
222 |
223 | !}
224 |
225 | {! fill !!
226 | .alice | f ] _f ]] ]] ] ]] ]] ] ]] ]] ] ] |
227 | .bob | _a ] o~ _a ]] ]] ] ]] ]] ] ]] ]] ] ] ~o |
228 | .snare | ] ]] ]] ] ]] ]] ] ]] ]] ] ] |
229 | .hats | ] ] ] ] ] ] ] ] |
230 | .kick | ) } ) } |
231 | .bass !bass_end
232 | !}
233 |
234 | {! drums !!
235 | .hats |: ] ] ] ] ] ] ] ]] ]] :| :| :| :| :| :| :| :| :| :| :|
236 | .snare |: } ) } ) :| :| :| :| :| :| :| :| :| :| ] ]] ]] ] ]] ]] ] ]] ]] ] ] |
237 | .kick |: ) } ) } :| :| :| :| :| :| :| :| :| :| :|
238 | !}
239 |
240 | !intro
241 | !melody_a
242 |
243 | .kick !eight_bars_rest
244 | .hats !four_bars_rest }}} }}} }}} ] ] ] ] ] ] ] ]
245 | .snare !eight_bars_rest
246 | !fill
247 |
248 | !melody_b
249 | !drums
250 |
251 | !fill
252 |
253 | ";
254 |
255 | for (0, 60, {x.skoar;});
256 |
257 |
--------------------------------------------------------------------------------
/SuperCollider/testing/conditionals.scd:
--------------------------------------------------------------------------------
1 | (
2 | "
3 | {: _a, _c, c, _e, e, _a :: ]]] ooo/ :}
4 |
5 | <_a, _c, c, _e, e, _a>.{: ]]] ooo/ :}
6 |
7 |
8 | ".skoar.play;
9 | )
10 |
11 | (
12 | "
13 | .h @hats => @instrument ]] D.C.
14 | .s @snare => @instrument } ) D.C.
15 | .k @kick => @instrument ) D.C.
16 |
17 | .a {: _a, _c, c, _e, e, _a :: ]]] ooo/ :}
18 |
19 | .a {? 10.rand <= 5 ?? 0 ]] ]] ?? 4 ] ?} ]
20 |
21 |
22 | .a {? 10.rand == 5 ?? a ] ] ] ] ]] ] ]] ?? ] c] }} ?}
23 |
24 | .a {? 10.rand >= 5 ?? e] ] ] ] ]] ] ]] ?? }}
25 | 10.rand <= 6 ?? ] ] ] f] ]] ] ]] ?? } )
26 | 11.rand <= 3 ?? ] c] }} ?}
27 |
28 | ".skoar.play;
29 | )
30 |
31 | ArrayedCollection
32 | (
33 | "{? 5 <= 10.rand ?? a] ?? c] ?}".skoar.play;
34 | )
35 |
36 |
37 | ("{? 10.rand >= 5 ?? ] ] ] o/ ]] ] ]] ?? }}
38 | 10.rand <= 6 ?? ] ] ] ] ]] ] ]] ?? } )
39 | 11.rand <= 3 ?? ] ] }} ?} D.C.".skoar.play;
40 | )
41 |
42 |
43 | ("
44 | 120 => )
45 |
46 | .hats @hats => @instrument
47 | .snare @snare => @instrument
48 | .kick @kick => @instrument
49 |
50 | .hats |: ] ] ] ] ] ] ] ]] ]] :| :| :| :| :| :| :| :| :| :| :|
51 | .snare |: } ) } ) :| :| :| :| :| :| :| :| :| :| ] ]] ]] ] ]] ]] ] ]] ]] ] ] |
52 | .kick |: ) } ) } :| :| :| :| :| :| :| :| :| :| :|
53 |
54 | ".skoar.play)
55 |
56 |
57 |
58 | (
59 | "
60 | ,segno`
61 | {! f !!
62 | |: a ] |
63 | | c# ]] ]]
64 | | b ] | fine D.S. al fine !}
65 |
66 | !f
67 | ".skoar.draw_skoarpions.play;
68 | )
69 |
70 | (
71 | "
72 | {! f !! !x ] 2 ] 4 ]!}
73 |
74 | !f<4>
75 | ".skoar.draw_skoarpions.play;
76 | )
77 |
--------------------------------------------------------------------------------
/Testing/SC_tests.playlist:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Testing/Skoarcery.playlist:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/build.py:
--------------------------------------------------------------------------------
1 | from Skoarcery.factoary.Build_Sc import Build_Sc
2 |
3 | if __name__ == '__main__':
4 | b = Build_Sc()
5 | b.build()
6 |
7 | #b.sanity()
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/examples.md:
--------------------------------------------------------------------------------
1 | Skoar Examples
2 | ==============
3 |
4 | # MIDI example - [listen on soundcloud](https://soundcloud.com/lucas-cornelisse/windwaker-sv1)
5 |
6 | Zelda Wind Waker Theme - inspired by piano arrangement by Shinobu Amayake ?>
7 |
8 | @midi => @type
9 | -1 => @transpose
10 |
11 | 9/8 120 => ).
12 | mp
13 |
14 | | <_a,_c#,d> )). }. | d )). }. | <_a,_c#,d> )). }. | _a )). }. |
15 |
16 | | _a) d] f#) e] d) c#] | d) _b] _g) c#] _a] d] _b] | c#) _a] _g) d] _b) c#] | d) e]] ]] f#] d] e] _a) ] |
17 | | _a) d]] e]] f#) e] d) c#] | d) _b] _g) c#] _a] d] _b] | c#) d] e) f#]] ]] g] e] c#] | d) oo/ e]] d). _a) ] |
18 | | _a) d]] e]] f#) e] d) c#] | e]] d]. _b] _g) c#] _a] d] _b] | c#) _a] _g) d] _b) c#] | ]] d]] e]] ]] f#] d] e] _a) ] |
19 | | _a) d]] e]] f#) e] d) c#] | d) _b] _g) c#] _a] d] _b] | c#) d] e) f#]] ]] g] e] c#] | d) oo/ e]] d). a) ] |
20 |
21 | |: g] f#] e] f#) d] c#] d] e] | a] d] ] g] d] ] f#) ] | g] a] b] b] g] e] a) a] | g] f#] d] e] f#] e]] f#]] e) ] |
22 | | d] c#] d] e) e] a] g] c#] | g] d] ] f#) ] e] c#] e] | d] b] d] g] a] b] f# d] g] | e). ] f#] e] a) ] :|
23 |
24 | | <_a,_c#,d> )). }. | d )). }. | <_a,_c#,d> )). }. | <_a,_f#> )). _a ) ] |
25 |
26 | This was played over MIDI to my Korg SV1.
27 |
28 | # Drumming example - [listen on soundcloud](https://soundcloud.com/lucas-cornelisse/beets)
29 |
30 | 4/4 time, 70 beats per min. No voice label on this line, all voices will read it ?>
31 |
32 | 4/4 70 => )
33 |
34 |
35 | each line begins with a voice label, we are using three voices ?>
36 | .h @hats => @instrument
37 | .s @snare => @instrument forte
38 | .k @kick => @instrument
39 |
40 | .h | }}} |
41 | .s | } ) } ) |
42 | .k | ) } ) } |
43 |
44 |
45 | .h |: ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] :|
46 | .s |: } ) } ) :|
47 | .k |: ) o/. ]] oo/ ]] ]] oo/ } :|
48 |
49 | .h |: ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] :|
50 | .s |: } ) } ) :|
51 | .k |: ]]. ]]. ]] o/ ]] ]] } o/ ] :|
52 |
53 |
54 | .h |: ]] ]] ]] ]] ]] ]] ]] ]]] ]]] ]] ]]] ]]] ]] ]] ]] ]] ]] ]] :|
55 | .s |: } ) } ]. ]] :|
56 | .k |: ] ]] ]] o/ ]] ]] o/ ] o/ ] :|
57 |
58 | .h |: ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]]] ]]] ]]] ]]] :|
59 | .s |: } ) } ]. ]] :|
60 | .k |: ]. ]] oo/ ]. o/ ] } :|
61 |
62 |
63 | .h |: ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] :|
64 | .s |: } ) } ]]. ]]. ]] :|
65 | .k |: ]]. ]]. ]] } ]]. ]]. ]] } :|
66 |
67 | .h |: ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] :|
68 | .s |: } ) } ) :|
69 | .k |: ]]. ]]. ]] o/. ]] ]] o/ ]] } :|
70 |
71 |
72 | .h |: ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] ]] :|
73 | .s |: } ]]. ]]. ]] } ]. ]] :|
74 | .k |: ) } ] ] } :|
75 |
76 | .h |: ]]] ]]] ]]] ]]] ]] ]] ]] ]] ]] ]]] ]]] ]] ]]] ]]] ]] ]] ]] ]] ]] ]] :|
77 | .s |: } ) } ) :|
78 | .k |: ] ] } o/ ] oo/ ]. :|
79 |
80 |
81 | .h | ))) |
82 | .s | ))) |
83 | .k | ))) |
84 |
--------------------------------------------------------------------------------
/sanity.py:
--------------------------------------------------------------------------------
1 | from Skoarcery.factoary.Build_Sc import Build_Sc
2 |
3 | if __name__ == '__main__':
4 | b = Build_Sc()
5 | b.sanity()
6 |
--------------------------------------------------------------------------------
/skoarcery.el:
--------------------------------------------------------------------------------
1 | (require 'json)
2 |
3 | (make-face 'skoarcery-sanity-fail)
4 | (set-face-foreground 'skoarcery-sanity-fail "black")
5 | (set-face-background 'skoarcery-sanity-fail "lightred")
6 |
7 | (make-face 'skoarcery-sanity-pass)
8 | (set-face-foreground 'skoarcery-sanity-pass "black")
9 | (set-face-background 'skoarcery-sanity-pass "lightgreen")
10 |
11 | (defun re-seq (regexp string group)
12 | "Get a list of all regexp matches in a string"
13 | (save-match-data
14 | (let ((pos 0)
15 | matches)
16 | (while (string-match regexp string pos)
17 | (push (match-string group string) matches)
18 | (setq pos (match-end 0))
19 | )
20 | matches)
21 | )
22 | )
23 |
24 | (defun skoar-build ()
25 | (interactive)
26 | (let ((default-directory "~/Documents/GitHub/Skoarcery/"))
27 | (let ((result (shell-command-to-string "python build.py")))
28 | (with-current-buffer (get-buffer-create "*skoar build*")
29 | (erase-buffer)
30 | (insert "--- skoar build ---")
31 | (insert result)
32 | )
33 | )
34 | )
35 |
36 | (skoar-sanity)
37 | )
38 |
39 | (defun skoar-sanity ()
40 | (interactive)
41 | (let ((default-directory "~/Documents/GitHub/Skoarcery/"))
42 | (let ((result (shell-command-to-string "python sanity.py"))
43 | (outbuf (get-buffer-create "*skoar tests*"))
44 | )
45 |
46 | (with-current-buffer (get-buffer-create "*skoar sanity*")
47 | (erase-buffer)
48 | (insert "\n--- skoar sanity ---\n")
49 | (insert result)
50 | )
51 |
52 | ;; clear output buffer and turn on colours
53 | (with-current-buffer outbuf
54 | (font-lock-mode)
55 | (erase-buffer)
56 | )
57 |
58 | (dolist (jsrc (re-seq "JSON: \\(.*\\)" result 1))
59 | (with-current-buffer outbuf
60 | (let ((json-object-type 'plist)
61 | (json-array-type 'list))
62 | (let ((o (json-read-from-string jsrc)))
63 |
64 | (setq test-name (nth 0 (re-seq ".*/testing/\\(.*\\)\\.scd" (plist-get o :test) 1)))
65 | (insert (propertize test-name 'font-lock-face '(:foreground "black" :background "red")))
66 | (insert "\n")
67 |
68 | ;; make it red
69 | (dolist (failure-line (plist-get o :failures))
70 | (setq failure (nth 0 (re-seq ".*test_do - \\(.*\\)
" failure-line 1)))
71 |
72 | (insert (propertize failure 'font-lock-face '(:foreground "red" :background "black")))
73 | (insert "\n")
74 | )
75 | )
76 | )
77 | )
78 | )
79 |
80 | (dolist (yay (re-seq "Sanity Tests: . OK ." result 0))
81 | (with-current-buffer outbuf
82 | (insert (propertize yay 'font-lock-face '(:foreground "black" :background "green")))
83 | (insert "\n")
84 | )
85 | )
86 |
87 | )
88 | )
89 | )
90 |
91 | (provide 'skoarcery)
92 |
--------------------------------------------------------------------------------