Modify tokenizer to parse notes
This commit is contained in:
74
grammar
74
grammar
@@ -1,42 +1,42 @@
|
||||
integer := ...
|
||||
string := ...
|
||||
note := ...
|
||||
identifier := ...
|
||||
# Tokenizer
|
||||
DIGIT = [0-9]
|
||||
ID = [a-zA-Z_]
|
||||
CHAR = ... \ '"'
|
||||
PITCH = 'c' | 'd' | 'e' | 'f' | 'g' | 'a' | 'h'
|
||||
PITCH_MODIFIER = 'b' | '#'
|
||||
|
||||
expr := integer
|
||||
expr := string
|
||||
expr := note
|
||||
expr := identifier
|
||||
expr := access
|
||||
expr := assignment
|
||||
expr := functionCall
|
||||
integer := '-' DIGIT+ | DIGIT+
|
||||
string := '"' CHAR* '"'
|
||||
note := '@' PITCH PITCH_MODIFIER? DIGIT? ['.' DIGIT+ 'd'?]?
|
||||
identifier := ID [ID|DIGIT]*
|
||||
percent := DIGIT+ '%'
|
||||
|
||||
# left associative
|
||||
access := expr '.' expr
|
||||
|
||||
# right associative
|
||||
asterisk := expr '*' stmt
|
||||
|
||||
stmt := asterisk
|
||||
stmt := block
|
||||
stmt := return
|
||||
stmt := functionDefinition
|
||||
|
||||
# right associative
|
||||
assignment := identifier '=' expr
|
||||
|
||||
list := '(' ')'
|
||||
list := '(' expr listTail
|
||||
|
||||
listTail := expr ', ' listTail
|
||||
listTail := ')'
|
||||
|
||||
percent := integer '%'
|
||||
|
||||
return := 'return' expr
|
||||
|
||||
block := '{' stmt* '}'
|
||||
# Parser
|
||||
expr := integer accessTail | integer
|
||||
expr := percent accessTail | percent
|
||||
expr := string accessTail | string
|
||||
expr := note accessTail | note
|
||||
expr := identifier accessTail | identifier '=' expr | functionCall | identifier
|
||||
expr := list accessTail | list
|
||||
expr := functionCall accessTail | functionCall
|
||||
|
||||
functionCall := identifier list
|
||||
|
||||
functionDefinition := 'function' identifier list block
|
||||
accessTail := '.' expr accessTail | e
|
||||
|
||||
list := '[' ']' | '[' expr listTail
|
||||
listTail := expr ', ' listTail | ']'
|
||||
|
||||
argList := '(' ')' | '(' expr argListTail
|
||||
argListTail := expr ', ' argListTail | ')'
|
||||
|
||||
block := '{' stmt* '}'
|
||||
|
||||
stmt := expr asteriskTail | expr #nie wiem czy zamiast 'expr asteriskTail' nie powinno być wprost co może wyprodukować iterator dla asterisk
|
||||
asteriskTail := '*' stmt | e
|
||||
stmt := block
|
||||
stmt := 'return' expr
|
||||
stmt := 'function' identifier list block
|
||||
|
||||
program := stmt*
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
# Tokenizer
|
||||
DIGIT = [0-9]
|
||||
ID = [a-zA-Z_]
|
||||
CHAR = ... \ '"'
|
||||
PITCH = 'c' | 'd' | 'e' | 'f' | 'g' | 'a' | 'h'
|
||||
PITCH_MODIFIER = 'b' | '#'
|
||||
|
||||
integer := '-' DIGIT+ | DIGIT+
|
||||
string := '"' CHAR* '"'
|
||||
note := '@' PITCH PITCH_MODIFIER? DIGIT? ['.' DIGIT+ 'd'?]?
|
||||
identifier := ID [ID|DIGIT]*
|
||||
percent := DIGIT+ '%'
|
||||
|
||||
# Parser
|
||||
expr := integer accessTail | integer
|
||||
expr := percent accessTail | percent
|
||||
expr := string accessTail | string
|
||||
expr := note accessTail | note
|
||||
expr := identifier accessTail | identifier '=' expr | functionCall | identifier
|
||||
expr := list accessTail | list
|
||||
expr := functionCall accessTail | functionCall
|
||||
|
||||
functionCall := identifier list
|
||||
|
||||
accessTail := '.' expr accessTail | e
|
||||
|
||||
list := '[' ']' | '[' expr listTail
|
||||
listTail := expr ', ' listTail | ']'
|
||||
|
||||
argList := '(' ')' | '(' expr argListTail
|
||||
argListTail := expr ', ' argListTail | ')'
|
||||
|
||||
block := '{' stmt* '}'
|
||||
|
||||
stmt := expr asteriskTail | expr #nie wiem czy zamiast 'expr asteriskTail' nie powinno być wprost co może wyprodukować iterator dla asterisk
|
||||
asteriskTail := '*' stmt | e
|
||||
stmt := block
|
||||
stmt := 'return' expr
|
||||
stmt := 'function' identifier list block
|
||||
|
||||
program := stmt*
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
from smnp.error.base import SmnpException
|
||||
|
||||
|
||||
class NoteException(SmnpException):
|
||||
class NoteException(Exception):
|
||||
def __init__(self, msg):
|
||||
super().__init__(msg)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ def main():
|
||||
ast = Program.parse(tokens)
|
||||
ast.node.print()
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
env = createEnvironment()
|
||||
|
||||
evaluate(ast, env)
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
from smnp.note.pitch import NotePitch
|
||||
|
||||
class Note:
|
||||
def __init__(self, note, octave = 4, duration = 4, dot = False):
|
||||
def __init__(self, note, octave, duration, dot = False):
|
||||
if octave is None:
|
||||
octave = 4
|
||||
|
||||
if duration is None:
|
||||
duration = 4
|
||||
|
||||
if type(note) == str:
|
||||
self.note = NotePitch.toPitch(note)
|
||||
else:
|
||||
|
||||
0
smnp/note/note.py
Normal file
0
smnp/note/note.py
Normal file
@@ -47,6 +47,7 @@ class NotePitch(Enum):
|
||||
raise NoteException(f"Note '{string}' does not exist")
|
||||
|
||||
stringToPitch = {
|
||||
'cb': NotePitch.H,
|
||||
'c': NotePitch.C,
|
||||
'c#': NotePitch.CIS,
|
||||
'db': NotePitch.CIS,
|
||||
|
||||
@@ -4,7 +4,7 @@ class Token:
|
||||
self.value = value
|
||||
self.pos = pos
|
||||
def __str__(self):
|
||||
return "Token(" + str(self.type) + ", '" + self.value + "', " + str(self.pos) + ")"
|
||||
return "Token(" + str(self.type) + ", '" + str(self.value) + "', " + str(self.pos) + ")"
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
|
||||
@@ -1,37 +1,44 @@
|
||||
import re
|
||||
from smnp.token.type import TokenType
|
||||
|
||||
from smnp.note.model import Note
|
||||
from smnp.token.model import Token
|
||||
from smnp.token.type import TokenType
|
||||
|
||||
|
||||
def tokenizeNote(input, current, line):
|
||||
consumedChars = 0
|
||||
value = ''
|
||||
notePitch = None
|
||||
octave = None
|
||||
duration = None
|
||||
dot = False
|
||||
if input[current] == '@':
|
||||
consumedChars += 1
|
||||
value += input[current]
|
||||
if input[current+consumedChars] in ('C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g', 'A', 'a', 'H', 'h', 'B', 'b'):
|
||||
value += input[current+consumedChars]
|
||||
notePitch = input[current+consumedChars]
|
||||
consumedChars += 1
|
||||
|
||||
if current+consumedChars < len(input) and input[current+consumedChars] in ('b', '#'):
|
||||
value += input[current+consumedChars]
|
||||
notePitch += input[current+consumedChars]
|
||||
consumedChars += 1
|
||||
|
||||
if current+consumedChars < len(input) and re.match(r'\d', input[current+consumedChars]):
|
||||
value += input[current+consumedChars]
|
||||
octave = input[current+consumedChars]
|
||||
consumedChars += 1
|
||||
|
||||
if current+consumedChars < len(input) and input[current+consumedChars] == '.':
|
||||
duration = input[current+consumedChars]
|
||||
if current+consumedChars < len(input) and input[current+consumedChars] == '.':
|
||||
duration = ''
|
||||
consumedChars += 1
|
||||
while current+consumedChars < len(input) and re.match(r'\d', input[current+consumedChars]):
|
||||
duration += input[current+consumedChars]
|
||||
consumedChars += 1
|
||||
if current+consumedChars < len(input) and input[current+consumedChars] == 'd':
|
||||
duration += input[current+consumedChars]
|
||||
consumedChars += 1
|
||||
if len(duration) > 1:
|
||||
value += duration
|
||||
else:
|
||||
consumedChars -= 1
|
||||
if len(duration) == 0:
|
||||
return (0, None)
|
||||
dot = (current+consumedChars) < len(input) and input[current+consumedChars] == 'd'
|
||||
consumedChars += 1
|
||||
|
||||
octave = int(octave) if octave is not None else None
|
||||
duration = int(duration) if duration is not None else None
|
||||
value = Note(notePitch, octave, duration, dot)
|
||||
|
||||
return (consumedChars, Token(TokenType.NOTE, value, (line, current)))
|
||||
return (0, None)
|
||||
|
||||
Reference in New Issue
Block a user