Added parentheses support to eval and some formatting
This commit is contained in:
@ -112,6 +112,7 @@ class Chord(Event):
|
|||||||
"""Set notes to the class"""
|
"""Set notes to the class"""
|
||||||
self.notes = notes
|
self.notes = notes
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class RomanNumeral(Event):
|
class RomanNumeral(Event):
|
||||||
"""Class for roman numbers"""
|
"""Class for roman numbers"""
|
||||||
@ -228,17 +229,25 @@ class Ziffers(Sequence):
|
|||||||
key = self.options["key"]
|
key = self.options["key"]
|
||||||
scale = self.options["scale"]
|
scale = self.options["scale"]
|
||||||
if isinstance(self.current, (Pitch, RandomPitch)):
|
if isinstance(self.current, (Pitch, RandomPitch)):
|
||||||
note = note_from_pc(root=key,pitch_class=self.current.pitch_class,intervals=scale,modifier=self.current.modifier)
|
note = note_from_pc(
|
||||||
|
root=key,
|
||||||
|
pitch_class=self.current.pitch_class,
|
||||||
|
intervals=scale,
|
||||||
|
modifier=self.current.modifier,
|
||||||
|
)
|
||||||
self.current.set_note(note)
|
self.current.set_note(note)
|
||||||
elif isinstance(self.current,Chord):
|
elif isinstance(self.current, Chord):
|
||||||
pcs = self.current.pitch_classes
|
pcs = self.current.pitch_classes
|
||||||
notes = [pc.set_note(note_from_pc(key, pc.pitch_class, scale)) for pc in pcs]
|
notes = [
|
||||||
|
pc.set_note(note_from_pc(key, pc.pitch_class, scale)) for pc in pcs
|
||||||
|
]
|
||||||
self.current.set_notes(notes)
|
self.current.set_notes(notes)
|
||||||
elif isinstance(self.current,RomanNumeral):
|
elif isinstance(self.current, RomanNumeral):
|
||||||
pitch_classes = [midi_to_pitch_class(note, key, scale) for note in self.current.notes]
|
pitch_classes = [
|
||||||
|
midi_to_pitch_class(note, key, scale) for note in self.current.notes
|
||||||
|
]
|
||||||
self.current.set_pitch_classes(pitch_classes)
|
self.current.set_pitch_classes(pitch_classes)
|
||||||
|
|
||||||
|
|
||||||
self.loop_i += 1
|
self.loop_i += 1
|
||||||
return self.current
|
return self.current
|
||||||
|
|
||||||
@ -342,13 +351,13 @@ class Cyclic(Sequence):
|
|||||||
wrap_end: str = field(default=">", repr=False)
|
wrap_end: str = field(default=">", repr=False)
|
||||||
|
|
||||||
def __next__(self):
|
def __next__(self):
|
||||||
yield self.values[self.cycle%len(self.cycle)]
|
yield self.values[self.cycle % len(self.cycle)]
|
||||||
self.cycle+=1
|
self.cycle += 1
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
|
|
||||||
def value(self):
|
def value(self):
|
||||||
"""Get the value for the current cycle"""
|
"""Get the value for the current cycle"""
|
||||||
return self.values[self.cycle%len(self.cycle)]
|
return self.values[self.cycle % len(self.cycle)]
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
@ -37,7 +37,7 @@ from .scale import parse_roman, chord_from_roman_numeral
|
|||||||
class ZiffersTransformer(Transformer):
|
class ZiffersTransformer(Transformer):
|
||||||
"""Rules for transforming Ziffers expressions into tree."""
|
"""Rules for transforming Ziffers expressions into tree."""
|
||||||
|
|
||||||
def __init__(self, options: Optional[dict]=None):
|
def __init__(self, options: Optional[dict] = None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.options = options
|
self.options = options
|
||||||
|
|
||||||
@ -114,21 +114,27 @@ class ZiffersTransformer(Transformer):
|
|||||||
"""Parses chord"""
|
"""Parses chord"""
|
||||||
return Chord(pitch_classes=items, text="".join([val.text for val in items]))
|
return Chord(pitch_classes=items, text="".join([val.text for val in items]))
|
||||||
|
|
||||||
def named_roman(self,items) -> RomanNumeral:
|
def named_roman(self, items) -> RomanNumeral:
|
||||||
"""Parse chord from roman numeral"""
|
"""Parse chord from roman numeral"""
|
||||||
numeral = items[0].value
|
numeral = items[0].value
|
||||||
if len(items)>1:
|
if len(items) > 1:
|
||||||
name = items[1]
|
name = items[1]
|
||||||
chord_notes = chord_from_roman_numeral(numeral,name)
|
chord_notes = chord_from_roman_numeral(numeral, name)
|
||||||
parsed_number = parse_roman(numeral)
|
parsed_number = parse_roman(numeral)
|
||||||
return RomanNumeral(text=numeral, value=parsed_number, chord_type=name, notes=chord_notes)
|
return RomanNumeral(
|
||||||
return RomanNumeral(value=parse_roman(numeral), text=numeral, notes=chord_from_roman_numeral(numeral))
|
text=numeral, value=parsed_number, chord_type=name, notes=chord_notes
|
||||||
|
)
|
||||||
|
return RomanNumeral(
|
||||||
|
value=parse_roman(numeral),
|
||||||
|
text=numeral,
|
||||||
|
notes=chord_from_roman_numeral(numeral),
|
||||||
|
)
|
||||||
|
|
||||||
def chord_name(self,item):
|
def chord_name(self, item):
|
||||||
"""Return name for chord"""
|
"""Return name for chord"""
|
||||||
return item[0].value
|
return item[0].value
|
||||||
|
|
||||||
def roman_number(self,item):
|
def roman_number(self, item):
|
||||||
"""Return roman numeral"""
|
"""Return roman numeral"""
|
||||||
return item.value
|
return item.value
|
||||||
|
|
||||||
@ -147,7 +153,7 @@ class ZiffersTransformer(Transformer):
|
|||||||
val = val * (2.0 - (1.0 / (2 * dots)))
|
val = val * (2.0 - (1.0 / (2 * dots)))
|
||||||
chars = chars + (dchar + "." * dots)
|
chars = chars + (dchar + "." * dots)
|
||||||
durs = durs + val
|
durs = durs + val
|
||||||
return {"text":chars, "duration":durs}
|
return {"text": chars, "duration": durs}
|
||||||
|
|
||||||
def dchar_not_prefix(self, items):
|
def dchar_not_prefix(self, items):
|
||||||
"""Return partial duration char info"""
|
"""Return partial duration char info"""
|
||||||
@ -222,9 +228,13 @@ class ZiffersTransformer(Transformer):
|
|||||||
val = items[0]
|
val = items[0]
|
||||||
return Eval(values=val)
|
return Eval(values=val)
|
||||||
|
|
||||||
|
def sub_operations(self, items):
|
||||||
|
"""Returns list of operations"""
|
||||||
|
return Eval(values=items[0], wrap_start="(", wrap_end=")")
|
||||||
|
|
||||||
def operation(self, items):
|
def operation(self, items):
|
||||||
"""Return partial eval operations"""
|
"""Return partial eval operations"""
|
||||||
return items
|
return flatten(items)
|
||||||
|
|
||||||
def atom(self, token):
|
def atom(self, token):
|
||||||
"""Return partial eval item"""
|
"""Return partial eval item"""
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
?roman_number: /iv|v|v?i{1,3}/
|
?roman_number: /iv|v|v?i{1,3}/
|
||||||
|
|
||||||
// Valid as integer
|
// Valid as integer
|
||||||
?number: SIGNED_NUMBER | random_integer | cyclic_number
|
?number: NUMBER | random_integer | cyclic_number
|
||||||
cyclic_number: "<" number (WS number)* ">"
|
cyclic_number: "<" number (WS number)* ">"
|
||||||
|
|
||||||
// Repeats
|
// Repeats
|
||||||
@ -69,11 +69,12 @@
|
|||||||
|
|
||||||
// Rules for evaluating clauses inside {}
|
// Rules for evaluating clauses inside {}
|
||||||
// TODO: Support for parenthesis?
|
// TODO: Support for parenthesis?
|
||||||
eval: "{" operation "}"
|
eval: "{" operation+ "}"
|
||||||
operation: atom (operator atom)+
|
operation: atom (operator (sub_operations | operation))*
|
||||||
atom: (number | DECIMAL)
|
sub_operations: "(" operation ")"
|
||||||
|
atom: (NUMBER | DECIMAL)
|
||||||
|
|
||||||
%import common.NUMBER
|
%import common.NUMBER
|
||||||
%import common.SIGNED_NUMBER
|
//%import common.SIGNED_NUMBER
|
||||||
%import common.DECIMAL
|
%import common.DECIMAL
|
||||||
%import common.WS
|
%import common.WS
|
||||||
Reference in New Issue
Block a user