Reformat evaluator #1
This commit is contained in:
@@ -1,204 +0,0 @@
|
|||||||
from AST import *
|
|
||||||
from Note import Note
|
|
||||||
from Error import RuntimeException
|
|
||||||
|
|
||||||
def evaluateProgram(program, environment):
|
|
||||||
for node in program.children:
|
|
||||||
evaluate(node, environment)
|
|
||||||
|
|
||||||
def evaluateInteger(integer, environment):
|
|
||||||
return integer.value
|
|
||||||
|
|
||||||
def evaluatePercent(percent, environment):
|
|
||||||
return percent.value.value * 0.01
|
|
||||||
|
|
||||||
def evaluateIdentifier(identifier, environment):
|
|
||||||
value = environment.findVariable(identifier.identifier)
|
|
||||||
return value
|
|
||||||
|
|
||||||
def evaluateString(string, environment):
|
|
||||||
value = string.value
|
|
||||||
for scope in reversed(environment.scopes):
|
|
||||||
for k, v in scope.items():
|
|
||||||
value = value.replace('{' + k + '}', objectString(v)) #TODO: poprawic
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def evaluateNote(note, environment):
|
|
||||||
return note.value
|
|
||||||
|
|
||||||
def evaluateFunctionDefinition(definition, environment):
|
|
||||||
name = definition.name
|
|
||||||
params = list([p for p in flatListNode(definition.parameters) if not isinstance(p, CommaNode)])
|
|
||||||
body = definition.body
|
|
||||||
|
|
||||||
if not isinstance(definition.parent, Program):
|
|
||||||
raise RuntimeException(name.pos, f"Functions can be defined only on the top level of script")
|
|
||||||
|
|
||||||
for p in params:
|
|
||||||
if not isinstance(p, IdentifierNode):
|
|
||||||
raise RuntimeException(p.pos, "Parameter of function definition must be an identifier")
|
|
||||||
|
|
||||||
if name.identifier in environment.customFunctions or name.identifier in environment.functions:
|
|
||||||
raise RuntimeException(name.pos, f"Function '{name.identifier}' already exists")
|
|
||||||
|
|
||||||
environment.customFunctions[name.identifier] = {
|
|
||||||
'params': params,
|
|
||||||
'body': flatListNode(body)
|
|
||||||
}
|
|
||||||
|
|
||||||
def flatListNode(listNode):
|
|
||||||
if len(listNode.children[0].children) == 1:
|
|
||||||
return []
|
|
||||||
return _flatListNode(listNode.children[0], [])
|
|
||||||
|
|
||||||
def _flatListNode(listItemNode, list = []):
|
|
||||||
if len(listItemNode.children) == 2:
|
|
||||||
child1 = listItemNode.children[0]
|
|
||||||
child2 = listItemNode.children[1]
|
|
||||||
list.append(child1)
|
|
||||||
_flatListNode(child2, list)
|
|
||||||
return list
|
|
||||||
|
|
||||||
def evaluateAccess(access, environment):
|
|
||||||
|
|
||||||
element = evaluate(access.element, environment)
|
|
||||||
#TODO: narazie tylko metody działają
|
|
||||||
e = evaluateMethodCall(element, access.property, environment)
|
|
||||||
return e
|
|
||||||
|
|
||||||
def evaluateMethodCall(element, functionCall, environment):
|
|
||||||
funcName = functionCall.identifier.identifier
|
|
||||||
arguments = evaluateList(functionCall.arguments, environment)
|
|
||||||
arguments.insert(0, element)
|
|
||||||
#for name, function in environment.customFunctions.items():
|
|
||||||
#if funcName == name:
|
|
||||||
#if len(function['params']) != len(arguments):
|
|
||||||
#raise RuntimeException(functionCall.pos, f"Calling '{funcName}' requires {len(function['params'])} and {len(arguments)} was passed")
|
|
||||||
#environment.scopes.append({ function['params'][i].identifier: v for i, v in enumerate(arguments) })
|
|
||||||
#returnValue = None
|
|
||||||
#for node in function['body']:
|
|
||||||
#if not isinstance(node, ReturnNode):
|
|
||||||
#evaluate(node, environment)
|
|
||||||
#else:
|
|
||||||
#returnValue = evaluateReturn(node, environment)
|
|
||||||
#environment.scopes.pop(-1)
|
|
||||||
#return returnValue
|
|
||||||
for name, definition in environment.methods[type(element)].items():
|
|
||||||
if name == funcName:
|
|
||||||
return definition(arguments, environment)
|
|
||||||
raise RuntimeException(functionCall.pos, f"Method '{funcName}' does not exist")
|
|
||||||
|
|
||||||
def evaluateFunctionCall(functionCall, environment):
|
|
||||||
funcName = functionCall.identifier.identifier
|
|
||||||
arguments = evaluateList(functionCall.arguments, environment)
|
|
||||||
for name, function in environment.customFunctions.items():
|
|
||||||
if funcName == name:
|
|
||||||
if len(function['params']) != len(arguments):
|
|
||||||
raise RuntimeException(functionCall.pos, f"Calling '{funcName}' requires {len(function['params'])} and {len(arguments)} was passed")
|
|
||||||
environment.scopes.append({ function['params'][i].identifier: v for i, v in enumerate(arguments) })
|
|
||||||
returnValue = None
|
|
||||||
for node in function['body']:
|
|
||||||
if not isinstance(node, ReturnNode):
|
|
||||||
evaluate(node, environment)
|
|
||||||
else:
|
|
||||||
returnValue = evaluateReturn(node, environment)
|
|
||||||
environment.scopes.pop(-1)
|
|
||||||
return returnValue
|
|
||||||
for name, definition in environment.functions.items():
|
|
||||||
if name == funcName:
|
|
||||||
return definition(arguments, environment)
|
|
||||||
raise RuntimeException(functionCall.pos, f"Function '{funcName}' does not exist")
|
|
||||||
|
|
||||||
def evaluateReturn(returnNode, environment):
|
|
||||||
return evaluate(returnNode.value, environment)
|
|
||||||
|
|
||||||
def evaluateComma(comma, environment):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def evaluateBlock(block, environment):
|
|
||||||
environment.scopes.append({})
|
|
||||||
for node in flatListNode(block):
|
|
||||||
evaluate(node, environment)
|
|
||||||
environment.scopes.pop(-1)
|
|
||||||
|
|
||||||
def evaluateList(list, environment):
|
|
||||||
return [evaluate(e, environment) for e in flatListNode(list) if not isinstance(e, CommaNode)]
|
|
||||||
|
|
||||||
def evaluateAssignment(assignment, environment):
|
|
||||||
target = assignment.target.identifier
|
|
||||||
value = evaluate(assignment.value, environment)
|
|
||||||
scopeOfExistingVariable = environment.findVariableScope(target)
|
|
||||||
if scopeOfExistingVariable is not None:
|
|
||||||
scopeOfExistingVariable[target] = value
|
|
||||||
else:
|
|
||||||
environment.scopes[-1][target] = value
|
|
||||||
|
|
||||||
def evaluateAsterisk(asterisk, environment):
|
|
||||||
count = evaluate(asterisk.iterator, environment)
|
|
||||||
if isinstance(count, int):
|
|
||||||
for i in range(count):
|
|
||||||
if isinstance(asterisk.iterator, IdentifierNode):
|
|
||||||
environment.scopes[-1][f"_{asterisk.iterator.identifier}"] = i+1
|
|
||||||
else:
|
|
||||||
environment.scopes[-1]["_"] = i+1
|
|
||||||
evaluate(asterisk.statement, environment)
|
|
||||||
if isinstance(asterisk.iterator, IdentifierNode):
|
|
||||||
del environment.scopes[-1][f"_{asterisk.iterator.identifier}"]
|
|
||||||
else:
|
|
||||||
environment.scopes[-1]["_"] = i+1
|
|
||||||
elif isinstance(count, list):
|
|
||||||
for i, v in enumerate(count):
|
|
||||||
if isinstance(asterisk.iterator, IdentifierNode):
|
|
||||||
environment.scopes[-1][f"_{asterisk.iterator.identifier}"] = i+1
|
|
||||||
environment.scopes[-1][f"{asterisk.iterator.identifier}_"] = v
|
|
||||||
else:
|
|
||||||
environment.scopes[-1]["_"] = i+1
|
|
||||||
environment.scopes[-1]["__"] = v
|
|
||||||
evaluate(asterisk.statement, environment)
|
|
||||||
if isinstance(asterisk.iterator, IdentifierNode):
|
|
||||||
del environment.scopes[-1][f"_{asterisk.iterator.identifier}"]
|
|
||||||
del environment.scopes[-1][f"{asterisk.iterator.identifier}_"]
|
|
||||||
else:
|
|
||||||
del environment.scopes[-1]["_"]
|
|
||||||
del environment.scopes[-1]["__"]
|
|
||||||
|
|
||||||
def evaluateColon(colon, environment):
|
|
||||||
if isinstance(colon.a, NoteLiteralNode) and isinstance(colon.b, NoteLiteralNode):
|
|
||||||
return Note.range(colon.a.value, colon.b.value)
|
|
||||||
elif isinstance(colon.a, IntegerLiteralNode) and isinstance(colon.b, IntegerLiteralNode):
|
|
||||||
return list(range(colon.a.value, colon.b.value+1))
|
|
||||||
raise RuntimeException(colon.pos, "Invalid colon arguments")
|
|
||||||
|
|
||||||
def evaluate(input, environment):
|
|
||||||
if isinstance(input, Program):
|
|
||||||
return evaluateProgram(input, environment)
|
|
||||||
if isinstance(input, IntegerLiteralNode):
|
|
||||||
return evaluateInteger(input, environment)
|
|
||||||
if isinstance(input, PercentNode):
|
|
||||||
return evaluatePercent(input, environment)
|
|
||||||
if isinstance(input, StringLiteralNode):
|
|
||||||
return evaluateString(input, environment)
|
|
||||||
if isinstance(input, NoteLiteralNode):
|
|
||||||
return evaluateNote(input, environment)
|
|
||||||
if isinstance(input, FunctionDefinitionNode):
|
|
||||||
return evaluateFunctionDefinition(input, environment)
|
|
||||||
if isinstance(input, FunctionCallNode):
|
|
||||||
return evaluateFunctionCall(input, environment)
|
|
||||||
if isinstance(input, AccessNode):
|
|
||||||
return evaluateAccess(input, environment)
|
|
||||||
if isinstance(input, CommaNode):
|
|
||||||
return evaluateComma(input, environment)
|
|
||||||
if isinstance(input, BlockNode):
|
|
||||||
return evaluateBlock(input, environment)
|
|
||||||
if isinstance(input, ListNode):
|
|
||||||
return evaluateList(input, environment)
|
|
||||||
if isinstance(input, AssignmentNode):
|
|
||||||
return evaluateAssignment(input, environment)
|
|
||||||
if isinstance(input, AsteriskNode):
|
|
||||||
return evaluateAsterisk(input, environment)
|
|
||||||
if isinstance(input, ColonNode):
|
|
||||||
return evaluateColon(input, environment)
|
|
||||||
if isinstance(input, IdentifierNode):
|
|
||||||
return evaluateIdentifier(input, environment)
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
from smnp.ast.node.block import BlockNode, CloseBlockNode, BlockItemNode
|
from smnp.ast.node.block import BlockNode, CloseBlockNode, BlockItemNode
|
||||||
|
from smnp.ast.parsers.statement import parseStatement
|
||||||
from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from smnp.ast.node.colon import ColonNode
|
from smnp.ast.node.colon import ColonNode
|
||||||
|
from smnp.ast.parsers.expression import parseExpression
|
||||||
from smnp.error.syntax import SyntaxException
|
from smnp.error.syntax import SyntaxException
|
||||||
from smnp.token.type import TokenType
|
from smnp.token.type import TokenType
|
||||||
|
|
||||||
@@ -11,7 +12,7 @@ def parseColon(expr1, input, parent):
|
|||||||
expr2 = parseExpression(input, parent)
|
expr2 = parseExpression(input, parent)
|
||||||
|
|
||||||
if expr2 is None:
|
if expr2 is None:
|
||||||
raise SyntaxException(input.current().pos, f"Expected expression '{input.current().value}'")
|
raise SyntaxException(f"Expected expression '{input.current().value}'", input.current().pos)
|
||||||
colon = ColonNode(expr1, expr2, parent, token.pos)
|
colon = ColonNode(expr1, expr2, parent, token.pos)
|
||||||
expr1.parent = colon
|
expr1.parent = colon
|
||||||
expr2.parent = colon
|
expr2.parent = colon
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ def parseToken(input, parent):
|
|||||||
value = combineParsers([ parseStatement ])(input, parent)
|
value = combineParsers([ parseStatement ])(input, parent)
|
||||||
|
|
||||||
if value is None:
|
if value is None:
|
||||||
raise SyntaxException(None, "Unknown statement") # TODO
|
raise SyntaxException("Unknown statement") # TODO
|
||||||
|
|
||||||
return value
|
return value
|
||||||
@@ -15,9 +15,9 @@ def rollup(parser):
|
|||||||
|
|
||||||
def assertToken(expected, input):
|
def assertToken(expected, input):
|
||||||
if not input.hasCurrent():
|
if not input.hasCurrent():
|
||||||
raise SyntaxException(None, f"Expected '{expected}'")
|
raise SyntaxException(f"Expected '{expected}'")
|
||||||
if expected != input.current().type:
|
if expected != input.current().type:
|
||||||
raise SyntaxException(input.current().pos, f"Expected '{expected}', found '{input.current().value}'")
|
raise SyntaxException(f"Expected '{expected}', found '{input.current().value}'", input.current().pos)
|
||||||
|
|
||||||
|
|
||||||
def combineParsers(parsers):
|
def combineParsers(parsers):
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ class Environment():
|
|||||||
return value
|
return value
|
||||||
else:
|
else:
|
||||||
return value
|
return value
|
||||||
raise RuntimeException(pos, f"Variable '{name}' is not declared" + (
|
raise RuntimeException(f"Variable '{name}' is not declared" + (
|
||||||
"" if type is None else f" (expected type: {type})"))
|
"" if type is None else f" (expected type: {type})"), pos)
|
||||||
|
|
||||||
def findVariableScope(self, name, type=None):
|
def findVariableScope(self, name, type=None):
|
||||||
for scope in reversed(self.scopes):
|
for scope in reversed(self.scopes):
|
||||||
@@ -46,4 +46,20 @@ class Environment():
|
|||||||
if isinstance(scope[name], type):
|
if isinstance(scope[name], type):
|
||||||
return scope
|
return scope
|
||||||
else:
|
else:
|
||||||
return scope
|
return scope
|
||||||
|
|
||||||
|
def scopesToString(self):
|
||||||
|
return "Scopes:\n" + ("\n".join([ f" [{i}]: {scope}" for i, scope in enumerate(self.scopes) ]))
|
||||||
|
|
||||||
|
def functionsToString(self):
|
||||||
|
return "Functions:\n" + ("\n".join([ f" {function.name}(...)" for function in self.functions ]))
|
||||||
|
|
||||||
|
def methodsToString(self):
|
||||||
|
return "Methods:\n" + ("\n".join([f" {function.name}(...)" for function in self.methods]))
|
||||||
|
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.scopesToString() + self.functionsToString() + self.methodsToString()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.__str__()
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
from smnp.environment.environment import Environment
|
from smnp.environment.environment import Environment
|
||||||
from smnp.library.function import display, sleep, semitones, interval, combine, flat, wait, rand, tuplet, synth, pause, \
|
from smnp.library.function import display, sleep, semitones, interval, combine, flat, wait, rand, tuplet, synth, pause, \
|
||||||
transpose, type, exit, duration, octave
|
transpose, type, exit, duration, octave, debug
|
||||||
|
from smnp.type.model import Type
|
||||||
|
from smnp.type.value import Value
|
||||||
|
|
||||||
|
|
||||||
def createEnvironment():
|
def createEnvironment():
|
||||||
@@ -18,7 +20,8 @@ def createEnvironment():
|
|||||||
tuplet.function,
|
tuplet.function,
|
||||||
synth.function,
|
synth.function,
|
||||||
pause.function,
|
pause.function,
|
||||||
transpose.function
|
transpose.function,
|
||||||
|
debug.function
|
||||||
]
|
]
|
||||||
|
|
||||||
methods = [
|
methods = [
|
||||||
@@ -27,7 +30,7 @@ def createEnvironment():
|
|||||||
]
|
]
|
||||||
|
|
||||||
variables = {
|
variables = {
|
||||||
"bpm": 120
|
"bpm": Value(Type.INTEGER, 120)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Environment([ variables ], functions, methods)
|
return Environment([ variables ], functions, methods)
|
||||||
|
|||||||
@@ -1,2 +1,13 @@
|
|||||||
class SmnpException(Exception):
|
class SmnpException(Exception):
|
||||||
pass
|
def __init__(self, msg, pos):
|
||||||
|
self.msg = msg
|
||||||
|
self.pos = pos
|
||||||
|
|
||||||
|
def _title(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _position(self):
|
||||||
|
return "" if self.pos is None else f" [line {self.pos[0]+1}, col {self.pos[1]+1}]"
|
||||||
|
|
||||||
|
def message(self):
|
||||||
|
return f"{self._title()}{self._position()}:\n{self.msg}"
|
||||||
|
|||||||
@@ -2,20 +2,32 @@ from smnp.error.base import SmnpException
|
|||||||
|
|
||||||
|
|
||||||
class IllegalFunctionInvocationException(SmnpException):
|
class IllegalFunctionInvocationException(SmnpException):
|
||||||
def __init__(self, expected, found):
|
def __init__(self, expected, found, pos=None):
|
||||||
self.msg = f"Illegal function invocation\n\nExpected signature:\n{expected}\n\nFound:\n{found}"
|
super().__init__(f"Expected signature:\n{expected}\n\nFound:\n{found}", pos)
|
||||||
|
|
||||||
|
def _title(self):
|
||||||
|
return "Invocation Error"
|
||||||
|
|
||||||
|
|
||||||
class FunctionNotFoundException(SmnpException):
|
class FunctionNotFoundException(SmnpException):
|
||||||
def __init__(self, function):
|
def __init__(self, function, pos=None):
|
||||||
self.msg = f"Function '{function}' not found"
|
super().__init__(f"Function '{function}' not found", pos)
|
||||||
|
|
||||||
|
def _title(self):
|
||||||
|
return "Invocation Error"
|
||||||
|
|
||||||
|
|
||||||
class MethodNotFoundException(SmnpException):
|
class MethodNotFoundException(SmnpException):
|
||||||
def __init__(self, object, method):
|
def __init__(self, object, method, pos=None):
|
||||||
self.msg = f"Method '{method}' of type '{object}' not found"
|
super().__init__(f"Method '{method}' of type '{object}' not found", pos)
|
||||||
|
|
||||||
|
def _title(self):
|
||||||
|
return "Invocation Error"
|
||||||
|
|
||||||
|
|
||||||
class IllegalArgumentException(SmnpException):
|
class IllegalArgumentException(SmnpException):
|
||||||
def __init__(self, msg):
|
def __init__(self, msg, pos=None):
|
||||||
self.msg = msg
|
super().__init__(msg, pos)
|
||||||
|
|
||||||
|
def _title(self):
|
||||||
|
return "Argument Error"
|
||||||
@@ -2,6 +2,12 @@ from smnp.error.base import SmnpException
|
|||||||
|
|
||||||
|
|
||||||
class RuntimeException(SmnpException):
|
class RuntimeException(SmnpException):
|
||||||
def __init__(self, pos, msg):
|
def __init__(self, msg, pos):
|
||||||
posStr = "" if pos is None else f" [line {pos[0]+1}, col {pos[1]+1}]"
|
super().__init__(msg, pos)
|
||||||
self.msg = f"Runtime error{posStr}:\n{msg}"
|
|
||||||
|
def _title(self):
|
||||||
|
return "Runtime Error"
|
||||||
|
|
||||||
|
# def message(self):
|
||||||
|
# posStr = "" if self.pos is None else f" [line {self.pos[0] + 1}, col {self.pos[1] + 1}]"
|
||||||
|
# return f"Runtime error{posStr}:\n{self.mmsg}"
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ from smnp.error.base import SmnpException
|
|||||||
|
|
||||||
|
|
||||||
class SyntaxException(SmnpException):
|
class SyntaxException(SmnpException):
|
||||||
def __init__(self, pos, msg):
|
def __init__(self, msg, pos=None):
|
||||||
posStr = "" if pos is None else f" [line {pos[0]+1}, col {pos[1]+1}]"
|
super().__init__(msg, pos)
|
||||||
self.msg = f"Syntax error{posStr}:\n{msg}"
|
|
||||||
|
def _title(self):
|
||||||
|
return "Syntax Error"
|
||||||
|
|
||||||
|
|||||||
24
smnp/library/function/debug.py
Normal file
24
smnp/library/function/debug.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
from smnp.error.function import IllegalArgumentException
|
||||||
|
from smnp.library.model import Function
|
||||||
|
from smnp.library.signature import signature, ofTypes
|
||||||
|
from smnp.type.model import Type
|
||||||
|
|
||||||
|
_signature = signature(ofTypes(Type.STRING))
|
||||||
|
def _function(env, parameter):
|
||||||
|
if parameter.value == "environment":
|
||||||
|
print(env)
|
||||||
|
return
|
||||||
|
elif parameter.value == "variables":
|
||||||
|
print(env.scopesToString())
|
||||||
|
return
|
||||||
|
elif parameter.value == "functions":
|
||||||
|
print(env.functionsToString())
|
||||||
|
return
|
||||||
|
elif parameter.value == "methods":
|
||||||
|
print(env.methodsToString())
|
||||||
|
return
|
||||||
|
|
||||||
|
raise IllegalArgumentException(f"Unknown parameter '{parameter.value}'")
|
||||||
|
|
||||||
|
|
||||||
|
function = Function(_signature, _function, 'debug')
|
||||||
@@ -7,7 +7,7 @@ from smnp.type.model import Type
|
|||||||
_signature = signature(ofTypes(Type.INTEGER))
|
_signature = signature(ofTypes(Type.INTEGER))
|
||||||
def _function(env, value):
|
def _function(env, value):
|
||||||
bpm = env.findVariable('bpm')
|
bpm = env.findVariable('bpm')
|
||||||
player.pause(value.value, bpm)
|
player.pause(value.value, bpm.value)
|
||||||
|
|
||||||
|
|
||||||
function = Function(_signature, _function, 'pause')
|
function = Function(_signature, _function, 'pause')
|
||||||
@@ -8,7 +8,7 @@ _signature1 = varargSignature(ofTypes(Type.NOTE, Type.INTEGER))
|
|||||||
def _function1(env, vararg):
|
def _function1(env, vararg):
|
||||||
notes = [arg.value for arg in vararg]
|
notes = [arg.value for arg in vararg]
|
||||||
bpm = env.findVariable('bpm')
|
bpm = env.findVariable('bpm')
|
||||||
playNotes(notes, bpm)
|
playNotes(notes, bpm.value)
|
||||||
|
|
||||||
|
|
||||||
_signature2 = varargSignature(listOf(Type.NOTE, Type.INTEGER))
|
_signature2 = varargSignature(listOf(Type.NOTE, Type.INTEGER))
|
||||||
|
|||||||
@@ -18,6 +18,6 @@ def _function2(env, n, m, notes):
|
|||||||
|
|
||||||
function = CombinedFunction(
|
function = CombinedFunction(
|
||||||
'tuplet',
|
'tuplet',
|
||||||
Function(_function1, _function1),
|
Function(_signature1, _function1),
|
||||||
Function(_function2, _function2)
|
Function(_signature2, _function2)
|
||||||
)
|
)
|
||||||
|
|||||||
27
smnp/main.py
27
smnp/main.py
@@ -1,29 +1,26 @@
|
|||||||
import sys
|
import sys
|
||||||
from smnp.error.syntax import SyntaxException
|
|
||||||
from smnp.error.runtime import RuntimeException
|
|
||||||
from smnp.token.tokenizer import tokenize
|
|
||||||
from smnp.ast.parser import parse
|
from smnp.ast.parser import parse
|
||||||
#from Tokenizer import tokenize
|
from smnp.environment.factory import createEnvironment
|
||||||
#from Evaluator import evaluate
|
from smnp.error.base import SmnpException
|
||||||
#from Environment import createEnvironment
|
from smnp.runtime.evaluator import evaluate
|
||||||
#from Error import SyntaxException, RuntimeException
|
from smnp.token.tokenizer import tokenize
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
try:
|
try:
|
||||||
with open(sys.argv[1], 'r') as source:
|
with open(sys.argv[1], 'r') as source:
|
||||||
lines = [line.rstrip('\n') for line in source.readlines()]
|
lines = [line.rstrip('\n') for line in source.readlines()]
|
||||||
|
|
||||||
#env = createEnvironment()
|
|
||||||
|
|
||||||
tokens = tokenize(lines)
|
tokens = tokenize(lines)
|
||||||
|
|
||||||
ast = parse(tokens)
|
ast = parse(tokens)
|
||||||
|
|
||||||
#evaluate(ast, env)
|
env = createEnvironment()
|
||||||
except SyntaxException as e:
|
|
||||||
print(e.msg)
|
evaluate(ast, env)
|
||||||
except RuntimeException as e:
|
|
||||||
print(e.msg)
|
except SmnpException as e:
|
||||||
|
print(e.message())
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("Program interrupted")
|
print("Program interrupted")
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
from smnp.error.syntax import SyntaxException
|
from smnp.error.syntax import SyntaxException
|
||||||
|
|
||||||
|
|
||||||
class NotePitch(Enum):
|
class NotePitch(Enum):
|
||||||
C = 0
|
C = 0
|
||||||
CIS = 1
|
CIS = 1
|
||||||
@@ -46,7 +48,7 @@ class NotePitch(Enum):
|
|||||||
try:
|
try:
|
||||||
return stringToPitch[string.lower()]
|
return stringToPitch[string.lower()]
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
raise SyntaxException(None, f"Note '{string}' does not exist")
|
raise SyntaxException(f"Note '{string}' does not exist") #TODO jakis inny exception
|
||||||
|
|
||||||
stringToPitch = {
|
stringToPitch = {
|
||||||
'c': NotePitch.C,
|
'c': NotePitch.C,
|
||||||
|
|||||||
57
smnp/runtime/evaluator.py
Normal file
57
smnp/runtime/evaluator.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
from smnp.ast.node.access import AccessNode
|
||||||
|
from smnp.ast.node.assignment import AssignmentNode
|
||||||
|
from smnp.ast.node.asterisk import AsteriskNode
|
||||||
|
from smnp.ast.node.block import BlockNode
|
||||||
|
from smnp.ast.node.colon import ColonNode
|
||||||
|
from smnp.ast.node.function import FunctionDefinitionNode, FunctionCallNode
|
||||||
|
from smnp.ast.node.identifier import IdentifierNode
|
||||||
|
from smnp.ast.node.integer import IntegerLiteralNode
|
||||||
|
from smnp.ast.node.list import ListNode
|
||||||
|
from smnp.ast.node.note import NoteLiteralNode
|
||||||
|
from smnp.ast.node.percent import PercentNode
|
||||||
|
from smnp.ast.node.program import Program
|
||||||
|
from smnp.ast.node.string import StringLiteralNode
|
||||||
|
|
||||||
|
def evaluate(input, environment):
|
||||||
|
from smnp.runtime.evaluators.access import evaluateAccess
|
||||||
|
from smnp.runtime.evaluators.assignment import evaluateAssignment
|
||||||
|
from smnp.runtime.evaluators.asterisk import evaluateAsterisk
|
||||||
|
from smnp.runtime.evaluators.block import evaluateBlock
|
||||||
|
from smnp.runtime.evaluators.colon import evaluateColon
|
||||||
|
from smnp.runtime.evaluators.function import evaluateFunctionDefinition, evaluateFunctionCall
|
||||||
|
from smnp.runtime.evaluators.identifier import evaluateIdentifier
|
||||||
|
from smnp.runtime.evaluators.integer import evaluateInteger
|
||||||
|
from smnp.runtime.evaluators.list import evaluateList
|
||||||
|
from smnp.runtime.evaluators.note import evaluateNote
|
||||||
|
from smnp.runtime.evaluators.percent import evaluatePercent
|
||||||
|
from smnp.runtime.evaluators.program import evaluateProgram
|
||||||
|
from smnp.runtime.evaluators.string import evaluateString
|
||||||
|
|
||||||
|
if isinstance(input, Program):
|
||||||
|
return evaluateProgram(input, environment)
|
||||||
|
if isinstance(input, IntegerLiteralNode):
|
||||||
|
return evaluateInteger(input, environment)
|
||||||
|
if isinstance(input, PercentNode):
|
||||||
|
return evaluatePercent(input, environment)
|
||||||
|
if isinstance(input, StringLiteralNode):
|
||||||
|
return evaluateString(input, environment)
|
||||||
|
if isinstance(input, NoteLiteralNode):
|
||||||
|
return evaluateNote(input, environment)
|
||||||
|
if isinstance(input, FunctionDefinitionNode):
|
||||||
|
return evaluateFunctionDefinition(input, environment)
|
||||||
|
if isinstance(input, FunctionCallNode):
|
||||||
|
return evaluateFunctionCall(input, environment)
|
||||||
|
if isinstance(input, AccessNode):
|
||||||
|
return evaluateAccess(input, environment)
|
||||||
|
if isinstance(input, BlockNode):
|
||||||
|
return evaluateBlock(input, environment)
|
||||||
|
if isinstance(input, ListNode):
|
||||||
|
return evaluateList(input, environment)
|
||||||
|
if isinstance(input, AssignmentNode):
|
||||||
|
return evaluateAssignment(input, environment)
|
||||||
|
if isinstance(input, AsteriskNode):
|
||||||
|
return evaluateAsterisk(input, environment)
|
||||||
|
if isinstance(input, ColonNode):
|
||||||
|
return evaluateColon(input, environment)
|
||||||
|
if isinstance(input, IdentifierNode):
|
||||||
|
return evaluateIdentifier(input, environment)
|
||||||
0
smnp/runtime/evaluators/__init__.py
Normal file
0
smnp/runtime/evaluators/__init__.py
Normal file
33
smnp/runtime/evaluators/access.py
Normal file
33
smnp/runtime/evaluators/access.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
from smnp.error.runtime import RuntimeException
|
||||||
|
from smnp.runtime.evaluators.list import evaluateList
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateAccess(access, environment):
|
||||||
|
pass
|
||||||
|
#element = evaluate(access.element, environment)
|
||||||
|
# TODO: narazie tylko metody działają
|
||||||
|
#e = evaluateMethodCall(element, access.property, environment)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateMethodCall(element, functionCall, environment):
|
||||||
|
funcName = functionCall.identifier.identifier
|
||||||
|
arguments = evaluateList(functionCall.arguments, environment)
|
||||||
|
arguments.insert(0, element)
|
||||||
|
# for name, library in environment.customFunctions.items():
|
||||||
|
# if funcName == name:
|
||||||
|
# if len(library['params']) != len(arguments):
|
||||||
|
# raise RuntimeException(functionCall.pos, f"Calling '{funcName}' requires {len(library['params'])} and {len(arguments)} was passed")
|
||||||
|
# environment.scopes.append({ library['params'][i].identifier: v for i, v in enumerate(arguments) })
|
||||||
|
# returnValue = None
|
||||||
|
# for node in library['body']:
|
||||||
|
# if not isinstance(node, ReturnNode):
|
||||||
|
# evaluate(node, environment)
|
||||||
|
# else:
|
||||||
|
# returnValue = evaluateReturn(node, environment)
|
||||||
|
# environment.scopes.pop(-1)
|
||||||
|
# return returnValue
|
||||||
|
for name, definition in environment.methods[type(element)].items():
|
||||||
|
if name == funcName:
|
||||||
|
return definition(arguments, environment)
|
||||||
|
raise RuntimeException(f"Method '{funcName}' does not exist", functionCall.pos)
|
||||||
15
smnp/runtime/evaluators/assignment.py
Normal file
15
smnp/runtime/evaluators/assignment.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from smnp.error.runtime import RuntimeException
|
||||||
|
from smnp.runtime.evaluator import evaluate
|
||||||
|
from smnp.type.model import Type
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateAssignment(assignment, environment):
|
||||||
|
target = assignment.target.identifier
|
||||||
|
value = evaluate(assignment.value, environment)
|
||||||
|
if value.type == Type.VOID:
|
||||||
|
raise RuntimeException(f"Expected expression, found '{value.type.name}'", assignment.value.pos)
|
||||||
|
scopeOfExistingVariable = environment.findVariableScope(target)
|
||||||
|
if scopeOfExistingVariable is not None:
|
||||||
|
scopeOfExistingVariable[target] = value
|
||||||
|
else:
|
||||||
|
environment.scopes[-1][target] = value
|
||||||
48
smnp/runtime/evaluators/asterisk.py
Normal file
48
smnp/runtime/evaluators/asterisk.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
from smnp.ast.node.identifier import IdentifierNode
|
||||||
|
from smnp.runtime.evaluator import evaluate
|
||||||
|
from smnp.type.model import Type
|
||||||
|
from smnp.type.value import Value
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateAsterisk(asterisk, environment):
|
||||||
|
iterator = evaluate(asterisk.iterator, environment)
|
||||||
|
if iterator.type == Type.INTEGER:
|
||||||
|
evaluateAsteriskForNumber(asterisk, environment, iterator)
|
||||||
|
|
||||||
|
if iterator.type == Type.LIST:
|
||||||
|
evaluateAsteriskForList(asterisk, environment, iterator)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateAsteriskForNumber(asterisk, environment, count):
|
||||||
|
for i in range(count.value):
|
||||||
|
if type(asterisk.iterator) == IdentifierNode:
|
||||||
|
environment.scopes[-1][f"_{asterisk.iterator.identifier}"] = Value(Type.INTEGER, i+1)
|
||||||
|
else:
|
||||||
|
environment.scopes[-1]["_"] = Value(Type.INTEGER, i+1)
|
||||||
|
|
||||||
|
evaluate(asterisk.statement, environment)
|
||||||
|
|
||||||
|
if type(asterisk.iterator) == IdentifierNode:
|
||||||
|
del environment.scopes[-1][f"_{asterisk.iterator.identifier}"]
|
||||||
|
else:
|
||||||
|
del environment.scopes[-1]["_"]
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateAsteriskForList(asterisk, environment, list):
|
||||||
|
for i, v in enumerate(list.value):
|
||||||
|
if type(asterisk.iterator) == IdentifierNode:
|
||||||
|
environment.scopes[-1][f"_{asterisk.iterator.identifier}"] = Value(Type.INTEGER, i+1)
|
||||||
|
environment.scopes[-1][f"{asterisk.iterator.identifier}_"] = v
|
||||||
|
else:
|
||||||
|
environment.scopes[-1]["_"] = Value(Type.INTEGER, i+1)
|
||||||
|
environment.scopes[-1]["__"] = v
|
||||||
|
|
||||||
|
evaluate(asterisk.statement, environment)
|
||||||
|
|
||||||
|
if type(asterisk.iterator) == IdentifierNode:
|
||||||
|
del environment.scopes[-1][f"_{asterisk.iterator.identifier}"]
|
||||||
|
del environment.scopes[-1][f"{asterisk.iterator.identifier}_"]
|
||||||
|
else:
|
||||||
|
del environment.scopes[-1]["_"]
|
||||||
|
del environment.scopes[-1]["__"]
|
||||||
11
smnp/runtime/evaluators/block.py
Normal file
11
smnp/runtime/evaluators/block.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from smnp.runtime.evaluator import evaluate
|
||||||
|
from smnp.runtime.tools import flatListNode
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateBlock(block, environment):
|
||||||
|
environment.scopes.append({})
|
||||||
|
for node in flatListNode(block):
|
||||||
|
evaluate(node, environment)
|
||||||
|
environment.scopes.pop(-1)
|
||||||
|
|
||||||
|
|
||||||
16
smnp/runtime/evaluators/colon.py
Normal file
16
smnp/runtime/evaluators/colon.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from smnp.ast.node.integer import IntegerLiteralNode
|
||||||
|
from smnp.ast.node.note import NoteLiteralNode
|
||||||
|
from smnp.error.runtime import RuntimeException
|
||||||
|
from smnp.note.model import Note
|
||||||
|
from smnp.type.model import Type
|
||||||
|
from smnp.type.value import Value
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateColon(colon, environment):
|
||||||
|
if isinstance(colon.a, NoteLiteralNode) and isinstance(colon.b, NoteLiteralNode):
|
||||||
|
return Value(Type.LIST, [Value(Type.NOTE, n) for n in Note.range(colon.a.value, colon.b.value)])
|
||||||
|
|
||||||
|
elif isinstance(colon.a, IntegerLiteralNode) and isinstance(colon.b, IntegerLiteralNode):
|
||||||
|
return Value(Type.LIST, [Value(Type.INTEGER, i) for i in range(colon.a.value, colon.b.value + 1)])
|
||||||
|
|
||||||
|
raise RuntimeException("Invalid colon arguments", colon.pos)
|
||||||
54
smnp/runtime/evaluators/function.py
Normal file
54
smnp/runtime/evaluators/function.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
from smnp.ast.node.identifier import IdentifierNode
|
||||||
|
from smnp.ast.node.program import Program
|
||||||
|
from smnp.error.runtime import RuntimeException
|
||||||
|
from smnp.runtime.evaluators.list import evaluateList
|
||||||
|
from smnp.runtime.tools import flatListNode
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateFunctionDefinition(definition, environment):
|
||||||
|
name = definition.name
|
||||||
|
params = list([p for p in flatListNode(definition.parameters)])
|
||||||
|
body = definition.body
|
||||||
|
|
||||||
|
if not isinstance(definition.parent, Program):
|
||||||
|
raise RuntimeException(f"Functions can be defined only on the top level of script", name.pos)
|
||||||
|
|
||||||
|
for p in params:
|
||||||
|
if not isinstance(p, IdentifierNode):
|
||||||
|
raise RuntimeException("Parameter of function definition must be an identifier", p.pos, )
|
||||||
|
|
||||||
|
if name.identifier in environment.customFunctions or name.identifier in environment.functions:
|
||||||
|
raise RuntimeException(f"Function '{name.identifier}' already exists", name.pos)
|
||||||
|
|
||||||
|
environment.customFunctions[name.identifier] = {
|
||||||
|
'params': params,
|
||||||
|
'body': flatListNode(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateFunctionCall(functionCall, environment):
|
||||||
|
functionName = functionCall.identifier.identifier
|
||||||
|
arguments = evaluateList(functionCall.arguments, environment).value
|
||||||
|
return environment.invokeFunction(functionName, arguments)
|
||||||
|
|
||||||
|
|
||||||
|
# def evaluateFunctionCall(functionCall, environment):
|
||||||
|
# funcName = functionCall.identifier.identifier
|
||||||
|
# arguments = evaluateList(functionCall.arguments, environment)
|
||||||
|
# for name, function in environment.customFunctions.items():
|
||||||
|
# if funcName == name:
|
||||||
|
# if len(function['params']) != len(arguments):
|
||||||
|
# raise RuntimeException(functionCall.pos, f"Calling '{funcName}' requires {len(function['params'])} and {len(arguments)} was passed")
|
||||||
|
# environment.scopes.append({ function['params'][i].identifier: v for i, v in enumerate(arguments) })
|
||||||
|
# returnValue = None
|
||||||
|
# for node in function['body']:
|
||||||
|
# if not isinstance(node, ReturnNode):
|
||||||
|
# evaluate(node, environment)
|
||||||
|
# else:
|
||||||
|
# returnValue = evaluateReturn(node, environment)
|
||||||
|
# environment.scopes.pop(-1)
|
||||||
|
# return returnValue
|
||||||
|
# for name, definition in environment.functions.items():
|
||||||
|
# if name == funcName:
|
||||||
|
# return definition(arguments, environment)
|
||||||
|
# raise RuntimeException(functionCall.pos, f"Function '{funcName}' does not exist")
|
||||||
10
smnp/runtime/evaluators/identifier.py
Normal file
10
smnp/runtime/evaluators/identifier.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from smnp.error.runtime import RuntimeException
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateIdentifier(identifier, environment):
|
||||||
|
try:
|
||||||
|
value = environment.findVariable(identifier.identifier)
|
||||||
|
return value
|
||||||
|
except RuntimeException as e:
|
||||||
|
e.pos = identifier.pos
|
||||||
|
raise e
|
||||||
6
smnp/runtime/evaluators/integer.py
Normal file
6
smnp/runtime/evaluators/integer.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from smnp.type.model import Type
|
||||||
|
from smnp.type.value import Value
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateInteger(integer, environment):
|
||||||
|
return Value(Type.INTEGER, integer.value)
|
||||||
17
smnp/runtime/evaluators/list.py
Normal file
17
smnp/runtime/evaluators/list.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from smnp.error.runtime import RuntimeException
|
||||||
|
from smnp.runtime.evaluator import evaluate
|
||||||
|
from smnp.runtime.tools import flatListNode
|
||||||
|
from smnp.type.model import Type
|
||||||
|
from smnp.type.value import Value
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateList(list, environment):
|
||||||
|
newList = []
|
||||||
|
for elem in flatListNode(list):
|
||||||
|
item = evaluate(elem, environment)
|
||||||
|
if item.type == Type.VOID:
|
||||||
|
raise RuntimeException(f"Expected expression, found '{item.type.name}'", elem.pos)
|
||||||
|
newList.append(item)
|
||||||
|
return Value(Type.LIST, newList)
|
||||||
|
|
||||||
|
|
||||||
6
smnp/runtime/evaluators/note.py
Normal file
6
smnp/runtime/evaluators/note.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from smnp.type.model import Type
|
||||||
|
from smnp.type.value import Value
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateNote(note, environment):
|
||||||
|
return Value(Type.NOTE, note.value)
|
||||||
6
smnp/runtime/evaluators/percent.py
Normal file
6
smnp/runtime/evaluators/percent.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from smnp.type.model import Type
|
||||||
|
from smnp.type.value import Value
|
||||||
|
|
||||||
|
|
||||||
|
def evaluatePercent(percent, environment):
|
||||||
|
return Value(Type.PERCENT, percent.value.value * 0.01)
|
||||||
6
smnp/runtime/evaluators/program.py
Normal file
6
smnp/runtime/evaluators/program.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from smnp.runtime.evaluator import evaluate
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateProgram(program, environment):
|
||||||
|
for node in program.children:
|
||||||
|
evaluate(node, environment)
|
||||||
5
smnp/runtime/evaluators/ret.py
Normal file
5
smnp/runtime/evaluators/ret.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
from smnp.runtime.evaluator import evaluate
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateReturn(returnNode, environment):
|
||||||
|
return evaluate(returnNode.value, environment)
|
||||||
28
smnp/runtime/evaluators/string.py
Normal file
28
smnp/runtime/evaluators/string.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
from smnp.error.runtime import RuntimeException
|
||||||
|
from smnp.type.model import Type
|
||||||
|
from smnp.type.value import Value
|
||||||
|
|
||||||
|
|
||||||
|
def evaluateString(string, environment):
|
||||||
|
value = interpolate(string, environment)
|
||||||
|
return Value(Type.STRING, value)
|
||||||
|
|
||||||
|
|
||||||
|
def interpolate(string, environment):
|
||||||
|
interpolated = string.value
|
||||||
|
for scope in reversed(environment.scopes):
|
||||||
|
for name, value in scope.items():
|
||||||
|
interpolated = interpolated.replace('{' + name + '}', value.stringify())
|
||||||
|
|
||||||
|
nonMatchedVariables = re.findall(r"\{\w+\}", interpolated)
|
||||||
|
if len(nonMatchedVariables) > 0:
|
||||||
|
raise RuntimeException(f"Variable '{nonMatchedVariables[0][1:len(nonMatchedVariables[0])-1]}' is not declared",
|
||||||
|
(string.pos[0], string.pos[1] + string.value.find(nonMatchedVariables[0])+1))
|
||||||
|
|
||||||
|
return interpolated
|
||||||
|
|
||||||
|
# or scope in reversed(environment.scopes):
|
||||||
|
# for k, v in scope.items():
|
||||||
|
# value = value.replace('{' + k + '}', v) #TODO: poprawic
|
||||||
13
smnp/runtime/tools.py
Normal file
13
smnp/runtime/tools.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
def flatListNode(listNode):
|
||||||
|
if len(listNode.children[0].children) == 1:
|
||||||
|
return []
|
||||||
|
return _flatListNode(listNode.children[0], [])
|
||||||
|
|
||||||
|
|
||||||
|
def _flatListNode(listItemNode, list = []):
|
||||||
|
if len(listItemNode.children) == 2:
|
||||||
|
value = listItemNode.children[0]
|
||||||
|
next = listItemNode.children[1]
|
||||||
|
list.append(value)
|
||||||
|
_flatListNode(next, list)
|
||||||
|
return list
|
||||||
@@ -1,27 +1,24 @@
|
|||||||
import sys
|
|
||||||
import time
|
|
||||||
import re
|
|
||||||
from smnp.error.syntax import SyntaxException
|
from smnp.error.syntax import SyntaxException
|
||||||
from smnp.token.type import TokenType
|
from smnp.error.syntax import SyntaxException
|
||||||
from smnp.token.model import Token, TokenList
|
from smnp.token.model import TokenList
|
||||||
from smnp.token.tools import tokenizeChar, tokenizeRegexPattern
|
|
||||||
from smnp.token.tokenizers.paren import tokenizeOpenParen, tokenizeCloseParen
|
|
||||||
from smnp.token.tokenizers.asterisk import tokenizeAsterisk
|
|
||||||
from smnp.token.tokenizers.whitespace import tokenizeWhitespaces
|
|
||||||
from smnp.token.tokenizers.identifier import tokenizeIdentifier
|
|
||||||
from smnp.token.tokenizers.comma import tokenizeComma
|
|
||||||
from smnp.token.tokenizers.string import tokenizeString
|
|
||||||
from smnp.token.tokenizers.integer import tokenizeInteger
|
|
||||||
from smnp.token.tokenizers.bracket import tokenizeOpenBracket, tokenizeCloseBracket
|
|
||||||
from smnp.token.tokenizers.assign import tokenizeAssign
|
from smnp.token.tokenizers.assign import tokenizeAssign
|
||||||
|
from smnp.token.tokenizers.asterisk import tokenizeAsterisk
|
||||||
|
from smnp.token.tokenizers.bracket import tokenizeOpenBracket, tokenizeCloseBracket
|
||||||
from smnp.token.tokenizers.colon import tokenizeColon
|
from smnp.token.tokenizers.colon import tokenizeColon
|
||||||
|
from smnp.token.tokenizers.comma import tokenizeComma
|
||||||
from smnp.token.tokenizers.comment import tokenizeComment
|
from smnp.token.tokenizers.comment import tokenizeComment
|
||||||
from smnp.token.tokenizers.note import tokenizeNote
|
|
||||||
from smnp.token.tokenizers.function import tokenizeFunction
|
|
||||||
from smnp.token.tokenizers.ret import tokenizeReturn
|
|
||||||
from smnp.token.tokenizers.percent import tokenizePercent
|
|
||||||
from smnp.token.tokenizers.minus import tokenizeMinus
|
|
||||||
from smnp.token.tokenizers.dot import tokenizeDot
|
from smnp.token.tokenizers.dot import tokenizeDot
|
||||||
|
from smnp.token.tokenizers.function import tokenizeFunction
|
||||||
|
from smnp.token.tokenizers.identifier import tokenizeIdentifier
|
||||||
|
from smnp.token.tokenizers.integer import tokenizeInteger
|
||||||
|
from smnp.token.tokenizers.minus import tokenizeMinus
|
||||||
|
from smnp.token.tokenizers.note import tokenizeNote
|
||||||
|
from smnp.token.tokenizers.paren import tokenizeOpenParen, tokenizeCloseParen
|
||||||
|
from smnp.token.tokenizers.percent import tokenizePercent
|
||||||
|
from smnp.token.tokenizers.ret import tokenizeReturn
|
||||||
|
from smnp.token.tokenizers.string import tokenizeString
|
||||||
|
from smnp.token.tokenizers.whitespace import tokenizeWhitespaces
|
||||||
|
from smnp.token.type import TokenType
|
||||||
|
|
||||||
tokenizers = (
|
tokenizers = (
|
||||||
tokenizeOpenParen,
|
tokenizeOpenParen,
|
||||||
@@ -58,7 +55,7 @@ def tokenize(lines):
|
|||||||
consumedChars, token = combinedTokenizer(line, current, lineNumber)
|
consumedChars, token = combinedTokenizer(line, current, lineNumber)
|
||||||
|
|
||||||
if consumedChars == 0:
|
if consumedChars == 0:
|
||||||
raise SyntaxException((lineNumber, current), f"Unknown symbol '{line[current]}'")
|
raise SyntaxException(f"Unknown symbol '{line[current]}'", (lineNumber, current))
|
||||||
|
|
||||||
current += consumedChars
|
current += consumedChars
|
||||||
tokens.append(token)
|
tokens.append(token)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class Type(Enum):
|
|||||||
|
|
||||||
|
|
||||||
def _failStringify(t):
|
def _failStringify(t):
|
||||||
raise RuntimeException(None, f"Not able to interpret {t.name}'")
|
raise RuntimeException(f"Not able to interpret {t.name}'")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user