99 lines
3.5 KiB
Plaintext
99 lines
3.5 KiB
Plaintext
// Root for the rules
|
|
?root: sequence -> start
|
|
sequence: (pitch_class | repeat_item | assignment | variable | variablelist | rest | dur_change | oct_mod | oct_change | WS | measure | chord | named_roman | cycle | random_integer | random_pitch | random_percent | range | list | repeated_list | lisp_operation | list_op | subdivision | eval | euclid | repeat)*
|
|
|
|
// Pitch classes
|
|
pitch_class: prefix* (pitch | escaped_pitch)
|
|
prefix: (octave | duration_chars | escaped_decimal | escaped_octave | modifier)
|
|
pitch: /-?[0-9TE]/
|
|
escaped_decimal: "<" decimal ">"
|
|
escaped_octave: /<-?[0-9]>/
|
|
octave: /[_^]+/
|
|
modifier: /[#b]/
|
|
|
|
measure: "|"
|
|
|
|
// Variable assignment
|
|
assignment: variable ass_op (list | pitch_class | random_integer | random_pitch | cycle | list_op | repeat_item)
|
|
ass_op: /[=~]/
|
|
variable: prefix* variable_char
|
|
variable_char: /[A-Z]/
|
|
|
|
variablelist: variable variable+
|
|
|
|
// Durations
|
|
duration_chars: dotted_dur+
|
|
dotted_dur: dchar dot*
|
|
decimal: /-?[0-9]+\.[0-9]+/
|
|
dchar: /[mklpdcwyhnqaefsxtgujzo]/
|
|
dot: "."
|
|
|
|
rest: prefix* "r"
|
|
|
|
// Chords
|
|
chord: pitch_class pitch_class+ invert?
|
|
named_roman: roman_number (("^" chord_name))? invert? // TODO: Add | ("+" number)
|
|
chord_name: /[a-zA-Z0-9]+/
|
|
!roman_number: "i" | "ii" | "iii" | "iv" | "v" | "vi" | "vii"
|
|
|
|
invert: /%-?[0-9][0-9]*/
|
|
|
|
// Valid as integer
|
|
number: integer | random_integer | cycle
|
|
integer: pitch+
|
|
escaped_pitch: /{-?[0-9]+}/
|
|
|
|
// Repeats
|
|
repeat: "[:" sequence ":" [number] "]"
|
|
repeat_item: (pitch_class | list | list_op | random_integer | cycle | rest | subdivision | chord | named_roman | variable | range) ":" number
|
|
|
|
// List
|
|
list: prefix* "(" sequence ")"
|
|
repeated_list: prefix* "(:" sequence ":" [number] ")"
|
|
|
|
// Right recursive list operation
|
|
list_op: list ((operator | list_operator) right_op)+
|
|
right_op: list | number
|
|
// Operators that work only on lists: | << >>
|
|
list_operator: /(\||<<|>>|<>|#|@)(?=[(\d])/
|
|
// /(\||<<|>>|<>|#|@)(?=[(\d])/
|
|
// Common operators that works with numbers 3+5 3-5 etc.
|
|
operator: /(\+|-|\*|\/|%|&|\?|~)/
|
|
|
|
// Euclidean cycles
|
|
// TODO: Support randomization etc.
|
|
//euclid_operator: (">" | "<") number "," number ["," number] (">" | "<")
|
|
euclid: list euclid_operator list?
|
|
?euclid_operator: /<[0-9]+,[0-9]+(,[0-9])?>/
|
|
|
|
// Lisp like list operation
|
|
lisp_operator: /([\+\-\*\/%\&])/
|
|
lisp_operation: "(" lisp_operator WS sequence ")"
|
|
|
|
// Subdivision
|
|
subdivision: "[" subitems "]"
|
|
subitems: (pitch_class | random_integer | random_pitch | rest | oct_mod | oct_change | WS | chord | named_roman | cycle | subdivision | list | list_op | range | repeat_item)*
|
|
|
|
// Control characters modifying future events
|
|
oct_mod: octave WS
|
|
oct_change: escaped_octave WS
|
|
dur_change: (decimal | char_change)
|
|
char_change: dchar_not_prefix+
|
|
dchar_not_prefix: /([mklpdcwyhnqaefsxtgujzo](\.)*)(?=[ >)])/
|
|
|
|
// Generative rules
|
|
random_integer: prefix* random_integer_re
|
|
random_integer_re: /\(-?[0-9]+,-?[0-9]+\)/
|
|
range: prefix* range_re
|
|
range_re: /-?[0-9]+\.\.-?[0-9]+/
|
|
cycle: "<" sequence ">"
|
|
random_pitch: /(\?)(?!\d)/
|
|
random_percent: /(%)(?!\d)/
|
|
|
|
// Rules for evaluating clauses inside {}
|
|
eval: "{" ((operation | rest) WS?)+ "}"
|
|
operation: prefix? atom (operator (sub_operations | operation))*
|
|
sub_operations: "(" operation ")"
|
|
atom: number
|
|
|
|
%import common.WS |