Added repeats

This commit is contained in:
2023-02-04 21:12:13 +02:00
parent 6597ca3f17
commit 26d3825ffb
3 changed files with 84 additions and 39 deletions

View File

@ -16,6 +16,10 @@ class Item(Meta):
''' Class for all Ziffers text based items '''
text: str
@dataclass
class Whitespace(Item):
''' Class for whitespace '''
@dataclass
class DurationChange(Item):
''' Class for changing duration '''
@ -73,8 +77,8 @@ class dataclass_property(property): # pylint: disable=invalid-name
@dataclass
class Sequence(Meta):
''' Class for sequences of items'''
values: list
text: str = None
values: list[Item]
text: str = field(init=False)
_text: str = field(default=None, init=False, repr=False)
@dataclass_property
@ -85,23 +89,11 @@ class Sequence(Meta):
def text(self, text: str) -> None:
self._text = text
wrapper: str = None
_wrapper: str = field(default=None, init=False, repr=False)
@dataclass_property
def wrapper(self) -> str:
return self._wrapper
@wrapper.setter
def wrapper(self, wrapper: str) -> None:
self._wrapper = wrapper
if self.text != None:
self.text = self.wrapper[0] + self.text + self.wrapper[1]
wrap_start: str = field(default=None, repr=False)
wrap_end: str = field(default=None, repr=False)
def __post_init__(self):
self.text = self.collect_text()
if self.text != None and self.wrapper != None:
self.text = self.wrapper[0] + self.text + self.wrapper[1]
def update_values(self, new_values):
''' Update value attributes from dict '''
@ -111,8 +103,13 @@ class Sequence(Meta):
setattr(obj, key, value)
def collect_text(self) -> str:
return "".join([val.text for val in self.values])
text = "".join([val.text for val in self.values])
if self.wrap_start != None:
text = self.wrap_start + text
if self.wrap_end != None:
text = text + self.wrap_end
return text
def pcs(self) -> list[int]:
return [val.pc for val in self.values if type(val) is Pitch]
@ -125,12 +122,15 @@ class Sequence(Meta):
@dataclass
class ListSequence(Sequence):
''' Class for Ziffers list sequences '''
prefix: dict = None
values: list = None
def __init__(self):
super.__init__()
if self.prefix!=None:
self.update(self.prefix)
wrap_start: str = field(default="(", repr=False)
wrap_end: str = field(default=")", repr=False)
@dataclass
class RepeatedListSequence(Sequence):
''' Class for Ziffers list sequences '''
repeats: Item = None
wrap_start: str = field(default="(:", repr=False)
wrap_end: str = field(default=":)", repr=False)
@dataclass
class Subdivision(Item):
@ -141,6 +141,9 @@ class Subdivision(Item):
class Cyclic(Sequence):
''' Class for cyclic sequences'''
cycle: int = 0
wrap_start: str = field(default="<", repr=False)
wrap_end: str = field(default=">", repr=False)
def __post_init__(self):
super().__post_init__()
# TODO: Do spaced need to be filtered out?
@ -189,6 +192,8 @@ class Operation(Item):
class Eval(Sequence):
''' Class for evaluation notation '''
result: ... = None
wrap_start: str = field(default="{", repr=False)
wrap_end: str = field(default="}", repr=False)
def __post_init__(self):
super().__post_init__()
self.result = eval(self.text)
@ -210,4 +215,12 @@ class Euclid(Item):
length: int
onset: list
offset: list = None
rotate: int = None
rotate: int = None
@dataclass
class RepeatedSequence(Sequence):
''' Class for repeats '''
repeats: Item = None
wrap_start: str = field(default="[:", repr=False)
wrap_end: str = field(default=":]", repr=False)

View File

@ -6,8 +6,11 @@ import operator
class ZiffersTransformer(Transformer):
def start(self,items):
return Sequence(values=items[0])
def sequence(self,items):
return Sequence(values=flatten(items))
return flatten(items)
def random_integer(self,s):
val = s[0][1:-1].split(",")
@ -18,8 +21,8 @@ class ZiffersTransformer(Transformer):
return Range(start=val[0],end=val[1],text=s[0])
def cycle(self, items):
values = items[0].values
return Cyclic(values=values, wrapper="<>")
values = items[0]
return Cyclic(values=values)
def pc(self, s):
if(len(s)>1):
@ -95,7 +98,7 @@ class ZiffersTransformer(Transformer):
return chardur
def WS(self,s):
return Item(text=s[0])
return Whitespace(text=s[0])
def subdivision(self,items):
values = flatten(items[0])
@ -108,7 +111,7 @@ class ZiffersTransformer(Transformer):
def eval(self,s):
val = s[0]
return Eval(values=val,wrapper="{}")
return Eval(values=val)
def operation(self,s):
return s
@ -122,14 +125,28 @@ class ZiffersTransformer(Transformer):
def list(self,items):
if len(items)>1:
prefixes = sum_dict(items[0:-1])
seq = items[-1]
seq.wrapper = "()"
seq.text = prefixes["text"] + seq.text
values = items[-1]
seq = ListSequence(values=values,wrap_start=prefixes["text"]+"(")
seq.update_values(prefixes)
return seq
else:
seq = items[0]
seq.wrapper = "()"
seq = ListSequence(values=items[0])
return seq
def repeated_list(self,items):
if len(items)>2:
prefixes = sum_dict(items[0:-2]) # If there are prefixes
if items[-1]!=None:
seq = RepeatedListSequence(values=items[-2],repeats=items[-1],wrap_end=":"+items[-1].text+")")
else:
seq = RepeatedListSequence(values=items[-2],repeats=Integer(text='1', value=1))
seq.update_values(prefixes)
return seq
else:
if items[-1]!=None:
seq = RepeatedListSequence(values=items[-2],repeats=items[-1],wrap_end=":"+items[-1].text+")")
else:
seq = RepeatedListSequence(values=items[-2],repeats=Integer(text='1', value=1))
return seq
def SIGNED_NUMBER(self, s):
@ -139,6 +156,9 @@ class ZiffersTransformer(Transformer):
def number(self,s):
return s
def cyclic_number(self,s):
return Cyclic(values=s)
def lisp_operation(self,s):
op = s[0]
values = s[1:]
@ -167,4 +187,10 @@ class ZiffersTransformer(Transformer):
return Euclid(**init)
def euclid_operator(self,s):
return s.value
return s.value
def repeat(self,s):
if s[-1]!=None:
return RepeatedSequence(values=s[0],repeats=s[-1],wrap_end=":"+s[-1].text+"]")
else:
return RepeatedSequence(values=s[0],repeats=Integer(value=1,text='1'))

View File

@ -1,6 +1,6 @@
// Root for the rules
?root: sequence
sequence: (pc | dur_change | oct_mod | oct_change | WS | chord | cycle | random_integer | random_pitch | random_percent | range | list | lisp_operation | list_op | subdivision | eval | euclid)*
?root: sequence -> start
sequence: (pc | dur_change | oct_mod | oct_change | WS | chord | cycle | random_integer | random_pitch | random_percent | range | list | repeated_list | lisp_operation | list_op | subdivision | eval | euclid | repeat)*
// Pitch classes
pc: prefix* pitch
@ -14,15 +14,21 @@
chord: pc pc+
// Valid as integer
?number: SIGNED_NUMBER | random_integer
?number: SIGNED_NUMBER | random_integer | cyclic_number
cyclic_number: "<" number (WS number)* ">"
// Repeats
repeat: "[:" sequence ":" [number] "]"
// List
list: prefix* "(" sequence ")"
repeated_list: prefix* "(:" sequence ":" [number] ")"
// Right recursive list operation
list_op: list (operator (list | number))+
operator: /([\+\-\*\/%]|<<|>>)/
// Euclidean cycles
euclid: list euclid_operator list?
?euclid_operator: /<[0-9]+,[0-9]+(,[0-9])?>/