class DEFAULTING(Token): must_be_subtoken = True EXPECTED_TOKENS = [ExpectedToken((TO, ), 0), ExpectedToken((VALUE, ), 1)] def run(self, interpreter: Interpreter): for token in self.tokens: interpreter.run(token)
class WRITE(Token): EXPECTED_TOKENS = [ ExpectedToken((VALUE, ), 0), ExpectedToken((TO, ), 1), ExpectedTokenCombination(ExpectedToken((END, ), 3), ExpectedToken((OF, ), 4), optional=True), ExpectedToken((VALUE, ), 2), ] def _run(self, interpreter: Interpreter): mode = "w" if self.has_all_optionals: interpreter.stack_pop() mode = "a" filename = interpreter.stack_pop().get_value() if not isinstance(filename, str): raise exceptions.TypeException( f"Value of type {filename.__class__.__name__} is not a valid file identifier!" ) value = interpreter.stack_pop().get_value() try: with open(filename, mode=mode, encoding="utf-8") as file: file.write(value) except Exception as exc: raise exceptions.RunTimeException( f"Failed to read file {filename}!") from exc
class FOR(Token): EXPECTED_TOKENS = [ ExpectedToken((EACH, ), 0), ExpectedToken((CONDITION, ), 1, optional=True), ExpectedToken((CLAUSE, ), 2), ] def run(self, interpreter: Interpreter): while True: try: for token in self.tokens: interpreter.run(token) except exceptions.BreakIterationException: break clause = interpreter.stack_pop() try: if self._check_condition(interpreter): clause.get_value()(interpreter) except exceptions.SkipElementException: pass except exceptions.BreakIterationException: break def _check_condition(self, interpreter: Interpreter) -> bool: value = interpreter.stack_pop() if not self.has_all_optionals: return True return value.get_value()
class FIRST(VALUE): EXPECTED_TOKENS = [ ExpectedToken((VARNAME, ), 1), ExpectedToken((IN, ), 2), ExpectedToken((VALUE, ), 0), ] RETURN_TOKEN_INDEX = 0 def run(self, interpreter: Interpreter): interpreter.run(self.tokens[-1]) collection = interpreter.stack_pop().get_value() try: collection_value = collection[self.RETURN_TOKEN_INDEX] except IndexError: raise exceptions.ValueException( "Cannot extract value from empty collection!") from None except TypeError: raise exceptions.TypeException( f"Cannot extract from value of type {collection.__class__.__name__}!", ) from None value = self.TOKEN_FACTORY.create_any_value(collection_value) interpreter.stack_append(value) # ignore collection (last token), as it was previously run for token in self.tokens[:-1]: interpreter.run(token) # append it again, previous stack append gets consumed by IN token interpreter.stack_append(value)
class GET(Token): EXPECTED_TOKENS = [ ExpectedToken((VARNAME), 3), ExpectedToken((FROM, ), 1), ExpectedToken((VALUE), 2), ExpectedToken((AT, ), 0), ] def _run(self, interpreter: Interpreter): variable = interpreter.stack_pop() collection = interpreter.stack_pop().get_value() index = interpreter.stack_pop().get_value() try: variable.value = collection[index] except IndexError: raise exceptions.ValueException( f"Collection index {index} out of range!") from None except TypeError: raise exceptions.TypeException( f"Cannot index value of type {collection.__class__.__name__}!" ) from None interpreter.set_variable(variable.name, variable)
class CollectionLogicToken(VALUE): EXPECTED_TOKENS = [ ExpectedToken((VALUE, ), 0), ExpectedToken((CONDITION, ), 1, optional=True), ] initial_condition_value = True def run(self, interpreter: Interpreter): interpreter.run(self.tokens[0]) collection = interpreter.stack_pop().get_value() for value in collection: result = self._get_condition_result(value, interpreter) if self._check_if_should_break(result): # pylint: disable=no-member condition_value = not self.initial_condition_value break else: condition_value = self.initial_condition_value result = self.TOKEN_FACTORY.create_value(condition_value) interpreter.stack_append(result) def _get_condition_result(self, value: Any, interpreter: Interpreter) -> bool: if not self.has_all_optionals: return bool(value) interpreter.stack_append(self.TOKEN_FACTORY.create_any_value(value)) interpreter.run(self.tokens[1]) # type: ignore return interpreter.stack_pop().get_value()
class CHECK(VALUE): EXPECTED_TOKENS = [ ExpectedToken((VALUE, ), 0), ExpectedToken((CONDITION, ), 1), ] def _run(self, interpreter: Interpreter): pass
class MULTIPLY(OperatorToken): EXPECTED_TOKENS = [ ExpectedToken((VARNAME, ), 2), ExpectedToken((BY, ), 1), ExpectedToken((VALUE, ), 0), ] def do_operation(self, variable: Variable, value: Value) -> None: variable.value = variable.get_value() * value.get_value()
class SUBTRACT(OperatorToken): EXPECTED_TOKENS = [ ExpectedToken((VALUE, ), 0), ExpectedToken((FROM, ), 1), ExpectedToken((VARNAME, ), 2), ] def do_operation(self, variable: Variable, value: Value) -> None: variable.value = variable.get_value() - value.get_value()
class DIVIDE(OperatorToken): EXPECTED_TOKENS = [ ExpectedToken((VARNAME, ), 2), ExpectedToken((BY, ), 1), ExpectedToken((VALUE, ), 0), ] def do_operation(self, variable: Variable, value: Value) -> None: variable.value = variable.get_value() / value.get_value() if variable.value == int(variable.value): variable.value = int(variable.value)
class RESULT(VARNAME): EXPECTED_TOKENS = [ ExpectedTokenCombination(ExpectedToken((OF, ), 0), ExpectedToken((CALL, ), 1), optional=True) ] def _run(self, interpreter: Interpreter): variable = interpreter.get_variable("result") interpreter.remove_variable("result") interpreter.set_variable("it", variable) interpreter.stack_append(variable)
class SET(Token): EXPECTED_TOKENS = [ ExpectedToken((QualifierToken), 3, optional=True), ExpectedToken((VARNAME, ), 2), ExpectedToken((TO, ), 1), ExpectedToken((VALUE, ), 0), ] def _run(self, interpreter: Interpreter): variable = interpreter.stack_pop() value = interpreter.stack_pop() variable.value = value.get_value() interpreter.set_variable(variable.name, variable)
class RANGE(VALUE): EXPECTED_TOKENS = [ ExpectedToken((FROM, ), 0), ExpectedToken((VALUE, ), 1), ExpectedToken((TO, ), 2), ExpectedToken((VALUE, ), 3), ] def _run(self, interpreter: Interpreter): end = interpreter.stack_pop().get_value() start = interpreter.stack_pop().get_value() interpreter.stack_append( self.TOKEN_FACTORY.create_iterable_value( value=list(range(start, end))))
class CATCH(Token): EXPECTED_TOKENS = [ ExpectedToken((ExceptionToken, ), 0), ExpectedToken((THEN, ), 1), ExpectedToken((CLAUSE, ), 2), ] def _run(self, interpreter: Interpreter): try_clause = interpreter.stack_pop().get_value() else_clause = interpreter.stack_pop().get_value() exception = interpreter.stack_pop().get_value() try: try_clause(interpreter) except exception: else_clause(interpreter)
class EXIT(Token): EXPECTED_TOKENS = [ExpectedToken((VALUE, ), optional=True)] def _run(self, interpreter: Interpreter): values = interpreter.stack_pop().get_value( ) if self.has_all_optionals else [] raise SystemExit(*values)
class NOT(CONDITION): EXPECTED_TOKENS = [ExpectedToken((VALUE, ))] def _run(self, interpreter: Interpreter): value = interpreter.stack_pop() value.negate_value() interpreter.stack_append(value)
class PRINT(Token): EXPECTED_TOKENS = [ExpectedToken((Token, ))] def _run(self, interpreter: Interpreter): value = interpreter.stack_pop() print(value.convert_to_str())
class EXPECTING(Token): must_be_subtoken = True EXPECTED_TOKENS = [ExpectedToken((COLLECTION, ), 0)] def _run(self, interpreter: Interpreter): collection = interpreter.stack_pop() interpreter.stack_pop() # default empty args interpreter.stack_append(collection)
class LENGTH(VALUE): EXPECTED_TOKENS = [ExpectedToken((OF, ), 0), ExpectedToken((VALUE, ), 1)] def _run(self, interpreter: Interpreter): collection = interpreter.stack_pop().get_value() try: len_ = len(collection) except TypeError: raise exceptions.TypeException( f"Value of type {collection.__class__.__name__} has no length!", token=self, ) from None length = self.TOKEN_FACTORY.create_value(len_) interpreter.stack_append(length)
class IF(Token): EXPECTED_TOKENS = [ ExpectedToken((VALUE, CHECK), 1), ExpectedToken((THEN, ), 2), ExpectedToken((CLAUSE, ), 3), ExpectedToken((ELSE, ), 0, optional=True), ] def _run(self, interpreter: Interpreter): if_clause = interpreter.stack_pop() condition_value = interpreter.stack_pop() else_clause = interpreter.stack_pop( ) if self.has_all_optionals else None if condition_value.get_value() == 1: if_clause.get_value()(interpreter) elif else_clause is not None: else_clause.get_value()(interpreter)
class EXCLUDE(Token): EXPECTED_TOKENS = [ ExpectedToken((VARNAME, ), 0), ExpectedToken((CONDITION, ), 1), ExpectedToken((FROM, ), 2), ExpectedToken((VALUE, ), 3), ] def run(self, interpreter: Interpreter): try: it = interpreter.get_variable("it") except exceptions.UndefinedVariableException: it = None for token in self.tokens[2:]: token.run(interpreter) collection = interpreter.stack_pop() collection_list = collection.get_value() self.tokens[0].run(interpreter) variable = interpreter.stack_pop() try: collection_value = list(collection.get_value()) except TypeError: raise exceptions.TypeException( f"Value of type {collection.get_value().__class__.__name__} is not iterable!" ) from None indices = [] for i, value in enumerate(collection_value): interpreter.stack_append( self.TOKEN_FACTORY.create_any_value(value)) interpreter.run(self.tokens[1]) # type: ignore condition_value = interpreter.stack_pop().get_value() if condition_value: indices.append(i) values = [] for i, index in enumerate(indices): values.append(collection_list.pop(index - i)) variable.value = values interpreter.set_variable(variable.name, variable) if it is not None: interpreter.set_variable("it", it)
class EACH(Token): must_be_subtoken = True # run order is ignored by EACH.run method EXPECTED_TOKENS = [ ExpectedToken((VARNAME, ), 1), ExpectedToken((IN, ), 2), ExpectedToken((VALUE, ), 0), ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._index = 0 self.collection = None def run(self, interpreter: Interpreter): if self.collection is None: interpreter.run(self.tokens[-1]) self.collection = interpreter.stack_pop().get_value() try: collection_value = self.collection[self._index] except IndexError: self.reset() raise exceptions.BreakIterationException(self) from None except TypeError: raise exceptions.TypeException( f"Cannot iterate through value of type {self.collection.__class__.__name__}!", token=self, ) from None value = self.TOKEN_FACTORY.create_any_value(value=collection_value) interpreter.stack_append(value) self._index += 1 # ignore collection (last token), as it was previously run for token in self.tokens[:-1]: interpreter.run(token) # append it again, this value can be consumed by optional for-each # condition, or needs to be thrown away by for-each loop if no condition interpreter.stack_append(value) def reset(self): self._index = 0 self.collection = None
class CONTENT(VALUE): EXPECTED_TOKENS = [ExpectedToken((OF, ), 0), ExpectedToken((VALUE, ), 1)] def _run(self, interpreter: Interpreter): value = interpreter.stack_pop().get_value() if not isinstance(value, str): raise exceptions.TypeException( f"Value of type {value.__class__.__name__} is not a valid file identifier!" ) try: with open(value, "r", encoding="utf-8") as file: content = file.read() except: raise exceptions.FileNotFoundException( f"File {value} cannot be read!") from None interpreter.stack_append(self.TOKEN_FACTORY.create_value(content))
class APPEND(Token): EXPECTED_TOKENS = [ ExpectedToken((VALUE, ), 0), ExpectedToken((TO, ), 1), ExpectedToken((VARNAME), 2), ] def _run(self, interpreter: Interpreter): collection_variable = interpreter.stack_pop() collection: List[Any] = collection_variable.get_value() value = interpreter.stack_pop().get_value() try: collection.append(value) except AttributeError: raise exceptions.TypeException( f"Cannot append value to type {collection.__class__.__name__}!", token=self, ) from None
class ROUND(VALUE): EXPECTED_TOKENS = [ExpectedToken((VALUE, ))] def _run(self, interpreter: Interpreter): value = interpreter.stack_pop() try: value.value = round(value.value) except TypeError: raise exceptions.TypeException( f"Cannot round value of type {value.value.__class__.__name__}!" ) from None
class REVERSE(Token): EXPECTED_TOKENS = [ExpectedToken((VALUE, ))] def _run(self, interpreter: Interpreter): collection: List[Any] = interpreter.stack_pop().get_value() try: collection.reverse() except AttributeError: raise exceptions.TypeException( f"Cannot reverse value of type {collection.__class__.__name__}!" ) from None
class WHILE(Token): EXPECTED_TOKENS = [ ExpectedToken((VALUE, ), 0), ExpectedToken((CLAUSE, ), 1), ] def run(self, interpreter: Interpreter): interpreter.run(self.tokens[-1]) clause_function = interpreter.stack_pop().get_value() condition = self.tokens[0] while True: condition.run(interpreter) if not interpreter.stack_pop().get_value(): break try: clause_function(interpreter) except exceptions.BreakIterationException: break
class UPDATE(Token): EXPECTED_TOKENS = [ ExpectedToken((VARNAME, ), 2), ExpectedToken((AT, ), 3), ExpectedToken((TO, ), 1), ExpectedToken((VALUE, ), 0), ] def _run(self, interpreter: Interpreter): index = interpreter.stack_pop().get_value() parent_value = interpreter.stack_pop().get_value() value = interpreter.stack_pop() try: parent_value[index] = value.get_value() except TypeError: raise exceptions.TypeException( f"Value of type {parent_value.__class__.__name__} cannot be indexed!" ) from None except IndexError: raise exceptions.ValueException("Index out of range!") from None
class SORT(Token): EXPECTED_TOKENS = [ExpectedToken((VALUE, ), 0)] def _run(self, interpreter: Interpreter): value: List[Any] = interpreter.stack_pop().get_value() try: value.sort() except AttributeError: raise exceptions.TypeException( f"Cannot sort value of type {value.__class__.__name__}" ) from None
class SLICE(VALUE): EXPECTED_TOKENS = [ ExpectedToken((OF, ), 0), ExpectedToken((VALUE, ), 4), ExpectedToken((FROM, ), 1), ExpectedToken((VALUE, ), 2), ExpectedToken((TO, ), 3), ExpectedToken((VALUE, ), 5), ] def _run(self, interpreter: Interpreter): end_index = interpreter.stack_pop().get_value() collection = interpreter.stack_pop().get_value() start_index = interpreter.stack_pop().get_value() if not isinstance(start_index, int): raise exceptions.ValueException( f"Wrong index of type {start_index.__class__.__name__}!" ) from None try: subcollection = collection[start_index:end_index] except TypeError: raise exceptions.TypeException( f"Value of type {collection.__class__.__name__} cannot be indexed!" ) from None except IndexError: raise exceptions.ValueException("Index out of range!") from None interpreter.stack_append( self.TOKEN_FACTORY.create_iterable_value(subcollection))