Initialise
This commit is contained in:
40
main.py
Normal file
40
main.py
Normal file
@ -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': "[: <q e> (1,4) <(2 3) (3 (1,7))> :]",
|
||||||
|
'Lists': "h 1 q(0 1 2 3) 2",
|
||||||
|
'List cycles': "(: <q e> (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)<r> (0 1 2)<i>(-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}")
|
||||||
1
ziffers/__init__.py
Normal file
1
ziffers/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from .parser import *
|
||||||
BIN
ziffers/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
ziffers/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
ziffers/__pycache__/ebnf.cpython-310.pyc
Normal file
BIN
ziffers/__pycache__/ebnf.cpython-310.pyc
Normal file
Binary file not shown.
BIN
ziffers/__pycache__/example.cpython-310.pyc
Normal file
BIN
ziffers/__pycache__/example.cpython-310.pyc
Normal file
Binary file not shown.
BIN
ziffers/__pycache__/parser.cpython-310.pyc
Normal file
BIN
ziffers/__pycache__/parser.cpython-310.pyc
Normal file
Binary file not shown.
29
ziffers/ebnf.py
Normal file
29
ziffers/ebnf.py
Normal file
@ -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+
|
||||||
|
"""
|
||||||
40
ziffers/parser.py
Normal file
40
ziffers/parser.py
Normal file
@ -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)
|
||||||
|
|
||||||
Reference in New Issue
Block a user