// 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