From b2ea4e16ddcf5807ac682400c99f9e09d1dfa145 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Sat, 3 Dec 2022 01:44:04 +0100 Subject: [PATCH] Initialise --- main.py | 40 +++++++++++++++++++ ziffers/__init__.py | 1 + ziffers/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 162 bytes ziffers/__pycache__/ebnf.cpython-310.pyc | Bin 0 -> 846 bytes ziffers/__pycache__/example.cpython-310.pyc | Bin 0 -> 1361 bytes ziffers/__pycache__/parser.cpython-310.pyc | Bin 0 -> 1794 bytes ziffers/ebnf.py | 29 ++++++++++++++ ziffers/parser.py | 40 +++++++++++++++++++ 8 files changed, 110 insertions(+) create mode 100644 main.py create mode 100644 ziffers/__init__.py create mode 100644 ziffers/__pycache__/__init__.cpython-310.pyc create mode 100644 ziffers/__pycache__/ebnf.cpython-310.pyc create mode 100644 ziffers/__pycache__/example.cpython-310.pyc create mode 100644 ziffers/__pycache__/parser.cpython-310.pyc create mode 100644 ziffers/ebnf.py create mode 100644 ziffers/parser.py diff --git a/main.py b/main.py new file mode 100644 index 0000000..8f103e1 --- /dev/null +++ b/main.py @@ -0,0 +1,40 @@ +from ziffers import * +from rich import print + +if __name__ == "__main__": + expressions = { + 'Pitches': "-2 -1 0 1 2", + 'Chords': "0 024 2 246", + 'Note lengths': "w 0 h 1 q 2 e 3 s 4", + 'Subdivision': "[1 2 [3 4]]", + 'Decimal durations': "0.25 0 1 [0.333]2 3", + 'Octaves': "^ 0 ^ 1 _ 2 _ 3", + 'Escaped octave': "<2> 1 <1>1<-2>3", + 'Roman chords': "i ii iii+4 iv+5 v+8 vi+10 vii+20", + 'Named chords': "i^7 i^min i^dim i^maj7", + 'Modal interchange (a-g)': "iiia ig ivf^7", + 'Escape/eval': "{10 11} {1.2 2.43} {3+1*2}", + 'Randoms': "% ? % ? % ?", + 'Random between': "(-3,6)", + 'Random selections': "[q 1 2, q 3 e 4 6]", + 'Repeat': "[: 1 (2,6) 3 :4]", + 'Repeat cycles': "[: (1,4) <(2 3) (3 (1,7))> :]", + 'Lists': "h 1 q(0 1 2 3) 2", + 'List cycles': "(: (1,4) <(2 3) (3 (1,7))> :)", + 'Loop cycles (for zloop or z0-z9)': "<0 <1 <2 <3 <4 5>>>>>", + 'Basic operations': "(1 2 (3 4)+2)*2 ((1 2 3)+(0 9 13))-2 ((3 4 {10})*(2 9 3))%7", + 'Product operations': "(0 1 2 3)+(1 4 2 3) (0 1 2)-(0 2 1)+2", + 'Euclid cycles': "(q1)<6,7>(q4 (e3 e4) q2) or (q1)<6,7<(q4 q3 q2)", + 'Transformations': "(0 1 2) (0 1 2)(-2 1)", + 'List assignation': "A=(0 (1,6) 3) B=(3 ? 2) B A B B A", + 'Random repeat': "(: 1 (2,6) 3 :4)", + 'Conditionals': "1 {%<0.5?3} 3 4 (: 1 2 {%<0.2?3:2} :3)", + 'Functions': "(0 1 2 3){x%3==0?x-2:x+2}", + 'Polynomials': "(-10..10){(x**3)*(x+1)%12}", + } + for expression in expressions: + try: + print(f"[green]== Parsing: [yellow]{expression}[/yellow] ==[/green]") + parse_expression(expression) + except Exception as e: + print(f"[red]Failed parsing {expression}[/red]: {e}") diff --git a/ziffers/__init__.py b/ziffers/__init__.py new file mode 100644 index 0000000..bd753cc --- /dev/null +++ b/ziffers/__init__.py @@ -0,0 +1 @@ +from .parser import * diff --git a/ziffers/__pycache__/__init__.cpython-310.pyc b/ziffers/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f84025ede8d029fa3af714bffde1175d0f9f3bfd GIT binary patch literal 162 zcmd1j<>g`k0;Snq$znkIF^Gc(44TX@8G%BYjJFuI z{4^P(*a{Mhic^bLG88cbg~7xxJ^fIiP_ceeX;Qv^Rc2ZmkfU2rS(1^T2jl9;$7kkc cmc+;F6;$5hu*uC&Da}c>1DRY5vYLkh0AcwgumAu6 literal 0 HcmV?d00001 diff --git a/ziffers/__pycache__/ebnf.cpython-310.pyc b/ziffers/__pycache__/ebnf.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..83138c08cc72e54205f43574b8d0d1cbaec56d10 GIT binary patch literal 846 zcmZ9LOHRWu6h+gDK~<@Husn(r(lAA8S|&`HASNvZ<>MAhaT3`{OZhE;C9nh5zz$eK zr|g0e&!3clrC56B-go_MwdH6ubYRWjUenLM<9w;2yLwQZ!6yf>WzO8mdY2CA#~)xG zB3Sgk5-37$(eQ){w3RdBA+1;vp;esLr9g3(v6^kDr`5Jnz1YVg4luD!t=pyuRf6$Y z>=1AAnpHVVma$+jxwEAO^eGDhLy-Rb>Yu zz-{ioOS&#xvBG9)V+AKnLOzf?O9V?&c zK)aTn86}51v=}DUR?%g4yE(9|+!jEA-5Qp}LbA1GPli=_BbCKBC1-`H15?+GQ?1+Q$=Jq3 zhDN8ns&_dnC}eD$AR literal 0 HcmV?d00001 diff --git a/ziffers/__pycache__/example.cpython-310.pyc b/ziffers/__pycache__/example.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..31be1f4b0b4ca249fe4e9f25590bc69b6e5a6ad1 GIT binary patch literal 1361 zcmZ8gyK>V&6y06h#0d@Bccoz1nZ1v5j*fQkNZ$PX9D>z<|8}rcMChw%rdJ7?b=cu| z2qrSIjU3#=7@4F;EMyiqF^e_y4x1&Y&eaganL1h!NEzx`$<0A^UUCr6_=-Y7InT+| za~C)P>|%~B3a_fr)2yGpSw+VOPYQPm`b=ABE{Q~rhvcC@14O!Kp zx+yBix9Z~Lx4~oS1Nn%11&&Sn2KS2Qoo%GE6mE}noXl(nhT|B)Nc0GO>n7Mq%TOiw zX)0!w7Gz_mFiZgbl*nu*c#z<6f+q<+Ot72aX9+eE%o98uZSRWp8N9-@D&@!NqRdfB zA*U-MtV7UAf=3CCjW1w3M`7_}KcF3|xv|sd0Ud{3y+I|DAssq229Xy~!!)hPI^qq< z=AC$!HCdarn4T#mpFPx}eqh0UC)A1U$ntG#VEi@t7n4>EM%xtZ^!!2TmYaZ`5pXvI zjmt+O%3~{yVkp=!jb#jFI+LuB1JPo+?|+xnwAXBJrFCzgH7Q$WU7EKI9bTgWbcQr_ zooX86aLNrhrv|2N7=b<|=*oAFLos2oI>0>+8|o-F+#!eIq*5A8W7(1IeqfyG_A=cx zwx9V8au6=~BGXM{uQFYv+~kB-6*ij2))Y4I;0u*f@Vl!pZxF?Pjy*ZUOmFN03c3S@ z^^G93Mj7@}VZI%QLef;NW4WqtsXnqCF8ORcrgfw&+luFoA5Cn_<=`<6n{r%RdZ|}~ zk%gAyxt14)%Omw)1?qRX->Ymr+SxdGxUsdl^I$uf$>>igVDKBr@T1k<4S5i@`*GiE zKevWMXj=XxI`rJUZS!Np@om2BPm=PgLU4Bge`KpL{7x6l*%V$7Q9aX0HXXz6aWAK literal 0 HcmV?d00001 diff --git a/ziffers/__pycache__/parser.cpython-310.pyc b/ziffers/__pycache__/parser.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..433c0adc103e28e928283e4b5c6a2020775fad15 GIT binary patch literal 1794 zcmZ`(&2rl|5C%Z-N0j8MnKW(Uc8bpQP|mp0CC5ygOgrO~eQ?_xIBhtz0L64DQUOR$ ztf5Z!sjtwBbL=be+EX5&m!7%{N{!^Wn86a*U4Y+yyV!C#3<->bKYpM7%?bGnH`@br zQoo~}nXA)c7O{3O&So>E z&Dz|K7O6HWQEwJn8IzU86z|&}3^q?;n#Uj%iK!$plT@;65<7?sBl)ej;*E1d8ZPNW@)pQ?4STqREx!;a zs;YHiM0KV_d7*Tg=c25uMO}@BUI*&c3z=3ba$9axK5KaaWVE9Tq(jMMdY0uK^{9=He$!UFBPL>^2-!3kzv$EK1CzdfiUR<`Jz15P3m0$u8oCS15 zIbA;7WqSPH_X8%78Oy|dSTyWcwsMe#3Rt+J8HMQS@_TWVzEVb{LT1xSlrzhMQPT>N zCca6Hc%?2QkrvV#U^BT$^IC~TnrSl@P!}9eMy~F`Uo-;NeGsh!zO84Sjb)(|AEB+k zMqO0;@?%gKtm%La=n5NgovRLXrQX~D znkKQo_PvdH*kN8y5=z}1m=D<}FMXf;A_U7MKOF|I2QbGr{- zHZ6OYmbyezV^HshCF$JfYhd~e5uP0wfquCdLwev&}5OcMPSs_^F4 lF_qT%rtR%pDE{NF4W4uv_zoE{s2`949Z=|TY{VYy{|mWWqjLZN literal 0 HcmV?d00001 diff --git a/ziffers/ebnf.py b/ziffers/ebnf.py new file mode 100644 index 0000000..486b026 --- /dev/null +++ b/ziffers/ebnf.py @@ -0,0 +1,29 @@ +ebnf = r""" + expr = (number ws?)* + number = factor additive* + additive = ("+"/"-") factor + factor = primary multiplicative* + multiplicative = ("*" / "/") primary + primary = parens / neg / number + parens = "(" number ")" + neg = "-" primary + number = ((~"[0-9]"+ "."? ~"[0-9]"*) / ("." ~"[0-9]"+)) (("e"/"E") ("-"/"+") ~"[0-9]"+)? + ws = ~"\s*" + lpar = "(" + rpar = ")" + lbra = "[" + rbra = "]" + lcbra = "{" + rcbra = "}" + lt = "<" + gt = ">" + comma = "," + octup = "^" + octdown = "_" + barsign = "|" + plus = "+" + minus = "-" + times = "*" + div = "/" + emptyline = ws+ + """ diff --git a/ziffers/parser.py b/ziffers/parser.py new file mode 100644 index 0000000..8ee931a --- /dev/null +++ b/ziffers/parser.py @@ -0,0 +1,40 @@ +from parsimonious.grammar import Grammar +from parsimonious.nodes import NodeVisitor +from .ebnf import ebnf + +__all__ = ('ZiffersVisitor', 'parse_expression',) + +GRAMMAR = Grammar(ebnf) + +class ZiffersVisitor(NodeVisitor): + def visit_expr(self, node, visited_children): + """ Returns the overall output. """ + output = {} + for child in visited_children: + output.update(child[0]) + return output + + def visit_entry(self, node, visited_children): + """ Makes a dict of the section (as key) and the key/value pairs. """ + key, values = visited_children + return {key: dict(values)} + + def visit_section(self, node, visited_children): + """ Gets the section name. """ + _, section, *_ = visited_children + return section.text + + def visit_pair(self, node, visited_children): + """ Gets each key/value pair, returns a tuple. """ + key, _, value, *_ = node.children + return key.text, value.text + + def generic_visit(self, node, visited_children): + """ The generic visit method. """ + return visited_children or node + +def parse_expression(expression: str) -> dict: + tree = GRAMMAR.parse(expression) + visitor = ZiffersVisitor() + return visitor.visit(tree) +