Added more rules and tests
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -5,11 +5,15 @@ class Meta:
|
||||
text: str
|
||||
|
||||
@dataclass
|
||||
class Duration(Meta):
|
||||
class DurationChange(Meta):
|
||||
dur: float
|
||||
|
||||
@dataclass
|
||||
class Octave(Meta):
|
||||
class OctaveChange(Meta):
|
||||
oct: int
|
||||
|
||||
@dataclass
|
||||
class OctaveMod(Meta):
|
||||
oct: int
|
||||
|
||||
@dataclass
|
||||
@ -25,7 +29,6 @@ class Pitch(Event):
|
||||
@dataclass
|
||||
class RandomPitch(Event):
|
||||
pc: int = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class Chord(Event):
|
||||
@ -42,8 +45,10 @@ class Ziffers:
|
||||
text: str = None
|
||||
def __post_init__(self):
|
||||
self.text = self.collect_text()
|
||||
def collect_text(self):
|
||||
def collect_text(self) -> str:
|
||||
return "".join([val.text for val in self.values])
|
||||
def pcs(self) -> list[int]:
|
||||
return [val.pc for val in self.values if type(val) is Pitch]
|
||||
|
||||
@dataclass
|
||||
class Sequence(Meta):
|
||||
|
||||
@ -2,7 +2,6 @@ from lark import Transformer
|
||||
from .classes import *
|
||||
from .common import flatten
|
||||
from .defaults import default_durs
|
||||
from collections import Counter
|
||||
|
||||
class ZiffersTransformer(Transformer):
|
||||
|
||||
@ -28,11 +27,14 @@ class ZiffersTransformer(Transformer):
|
||||
|
||||
def pc(self, s):
|
||||
if(len(s)>1):
|
||||
counter = Counter()
|
||||
for d in s:
|
||||
counter.update(d)
|
||||
result = dict(counter)
|
||||
result["text"] = result["text"][::-1]
|
||||
# Collect&sum prefixes from any order: _qee^s4 etc.
|
||||
result = s[0]
|
||||
for hash in s[1:]:
|
||||
for key in hash.keys():
|
||||
if key in result:
|
||||
result[key] = result[key] + hash[key]
|
||||
else:
|
||||
result[key] = hash[key]
|
||||
return Pitch(**result)
|
||||
else:
|
||||
val = s[0]
|
||||
@ -46,7 +48,15 @@ class ZiffersTransformer(Transformer):
|
||||
|
||||
def oct_change(self,s):
|
||||
octave = s[0]
|
||||
return [Octave(oct=octave["oct"],text=octave["text"]),s[1]]
|
||||
return [OctaveChange(oct=octave["oct"],text=octave["text"]),s[1]]
|
||||
|
||||
def oct_mod(self,s):
|
||||
octave = s[0]
|
||||
return [OctaveMod(oct=octave["oct"],text=octave["text"]),s[1]]
|
||||
|
||||
def escaped_octave(self,s):
|
||||
value = s[0][1:-1]
|
||||
return {"oct": int(value), "text":s[0].value}
|
||||
|
||||
def octave(self,s):
|
||||
value = sum([1 if char=='^' else -1 for char in s[0].value])
|
||||
@ -57,14 +67,19 @@ class ZiffersTransformer(Transformer):
|
||||
|
||||
def dur_change(self,s):
|
||||
duration = s[0]
|
||||
return [Duration(dur=duration["dur"], text=duration["text"]),s[1]]
|
||||
return [DurationChange(dur=duration["dur"], text=duration["text"]),s[1]]
|
||||
|
||||
def duration(self,s):
|
||||
def escaped_decimal(self,s):
|
||||
val = s[0]
|
||||
val["text"] = "<"+val["text"]+">"
|
||||
return val
|
||||
|
||||
def duration_chars(self,s):
|
||||
durations = [val[1] for val in s]
|
||||
characters = "".join([val[0] for val in s])
|
||||
return {"dur": sum(durations), "text":characters[::-1]}
|
||||
return {"dur": sum(durations), "text":characters}
|
||||
|
||||
def dur(self,s):
|
||||
def dotted_dur(self,s):
|
||||
key = s[0]
|
||||
val = default_durs[key]
|
||||
dots = len(s)-1
|
||||
@ -72,6 +87,10 @@ class ZiffersTransformer(Transformer):
|
||||
val = val * (2.0-(1.0/(2*dots)))
|
||||
return [key+"."*dots,val]
|
||||
|
||||
def decimal(self,s):
|
||||
val = s[0]
|
||||
return {"dur": float(val),"text": val.value}
|
||||
|
||||
def dot(self,s):
|
||||
return "."
|
||||
|
||||
|
||||
@ -9,13 +9,4 @@ grammar = grammar_path / "ziffers.lark"
|
||||
ziffers_parser = Lark.open(grammar, rel_to=__file__, start='value', parser='lalr', transformer=ZiffersTransformer())
|
||||
|
||||
def parse_expression(expr):
|
||||
return ziffers_parser.parse(expr)
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(ziffers_parser.parse("[1 [2 3]]"))
|
||||
#print(ziffers_parser.parse("(1 (1,3) 1..3)"))
|
||||
#print(ziffers_parser.parse("_^ q _qe^3 qww_4 _123 <1 2>"))
|
||||
#print(ziffers_parser.parse("q _2 _ 3 ^ 343"))
|
||||
#print(ziffers_parser.parse("2 qe2 e4").values)
|
||||
#print(ziffers_parser.parse("q 2 <3 343>"))
|
||||
#print(ziffers_parser.parse("q (2 <3 343 (3 4)>)"))
|
||||
return ziffers_parser.parse(expr)
|
||||
@ -1,19 +1,23 @@
|
||||
|
||||
?value: root
|
||||
root: (pc | dur_change | oct_change | WS | chord | cycle | randompitch | range | list | subdivision)*
|
||||
root: (pc | dur_change | oct_mod | oct_change | WS | chord | cycle | randompitch | range | list | subdivision)*
|
||||
list: "(" root ")"
|
||||
randompitch: /[\(][-?0-9][,][-?0-9][\)]/
|
||||
range: /[-?0-9]\.\.[-?0-9]/
|
||||
randompitch: /\(-?[0-9],-?[0-9]\)/
|
||||
range: /-?[0-9]\.\.-?[0-9]/
|
||||
cycle: "<" root ">"
|
||||
pc: prefix* pitch
|
||||
pitch: /[-?0-9TE]/
|
||||
prefix: octave | duration
|
||||
oct_change: octave WS
|
||||
pitch: /-?[0-9TE]/
|
||||
prefix: (octave | duration_chars | escaped_decimal | escaped_octave)
|
||||
oct_change: escaped_octave WS
|
||||
escaped_octave: /<-?[0-9]>/
|
||||
oct_mod: octave WS
|
||||
octave: /[_^]+/
|
||||
chord: pc pc+
|
||||
dur_change: duration WS
|
||||
duration: dur+
|
||||
dur: dchar dot*
|
||||
escaped_decimal: "<" decimal ">"
|
||||
dur_change: (duration_chars | decimal) WS
|
||||
duration_chars: dotted_dur+
|
||||
dotted_dur: dchar dot*
|
||||
decimal: /-?[0-9]+\.[0-9]+/
|
||||
dchar: /[mklpdcwyhnqaefsxtgujzo]/
|
||||
dot: "."
|
||||
subitems: (pc | WS | chord | cycle | subdivision)*
|
||||
|
||||
Reference in New Issue
Block a user