def start(self) -> None: """ todo: add support for in-place value mutations """ def to_dict(_ast): return _ast if _ast.name == 'running_name' else { 'op': _ast.op, 'left': to_dict(_ast.left), 'right': to_dict(_ast.right) } _path = [self.start_token] _identifier, path = next(self.header, None), None if _identifier.name not in { 'colon', 'dot', 'lparent', 'assign', 'increment', 'decrement', 'inplace' }: raise lang_exceptions.InvalidSyntax( f"In '{self.file}', line {self.line_counter.line_number}:\nInvalid Syntax: invalid syntax with name '{_identifier.value}'" ) _path.extend(list(self.attr_lookup(_identifier))) _identifier = next(self.header, None) if _identifier.name in {'assign', 'inplace'}: _full_ast, *_ = ast_creator.AST.create_ast( self.reverse_op, lang_utility_objs.ast_delimeters()) return lang_utility_objs.NameAction(_path, None, _identifier, _full_ast) if _identifier.name == 'colon': _type_ast, _, _last = ast_creator.AST.create_ast( self.reverse_op, lang_utility_objs.ast_delimeters("assign")) self.header = iter([_last, *self.header]) _check_next = next(self.header, None) if _check_next is None: raise lang_exceptions.InvalidTypeDeclaration( f"In '{self.file}', line {self.line_counter.line_number}:\nInvalid Type Declaration: expecting assignment expression" ) if _check_next.name != 'assign': lang_exceptions.InvalidSyntax( f"In '{self.file}', line {self.line_counter.line_number}:\nInvalid Assignment Expression: expecting value assignment" ) _assignment_ast, *_ = ast_creator.AST.create_ast( self.reverse_op, lang_utility_objs.ast_delimeters()) return lang_utility_objs.NameAction(_path, _type_ast, _check_next, _assignment_ast) if _identifier.name in {'increment', 'decrement'}: _check_next = next(self.header, None) if _check_next is not None: raise lang_exceptions.InvalidInplaceExpression( f"In '{self.file}', line {self.line_counter.line_number}:\nInvalid Inplace Expression: invalid {_identifier.name} expression" ) return lang_utility_objs.InPlaceAction(_path, _identifier) raise lang_exceptions.InvalidSyntax( f"In '{self.file}', line {self.line_counter.line_number}:\nInvalid Syntax: invalid syntax with name '{_identifier.value}'" )
def attr_lookup(self, _c): while _c.name == 'dot': _attr = next(self.header, None) if _attr is None: raise lang_exceptions.InvalidSyntax( f"In '{self.file}', line {self.line_counter.line_number}:\nInvalid Syntax: unexpected termination of expression" ) if _attr.name != 'variable': raise lang_exceptions.InvalidSyntax( f"In '{self.file}', line {self.line_counter.line_number}:\nInvalid Syntax: '{attr.value}'" ) yield _attr _c = next(self.header, None) if _c is not None: self.header = iter([_c, *self.header])
def start(self) -> None: _start, _queue = next(self.header, None), [] while _start is not None and _start.name not in self.delimeter: if _start.token_type in {'name', 'boolean', 'value', 'lang_type'}: _queue.append( NameLookup( [_start, *self.attr_lookup(next(self.header, None))])) elif _start.token_type in {'operator'}: _queue.append(OperatorObj(_start)) elif _start.name == 'lparen': _signature = [] while True: _param, end, _ending_token = self.__class__.create_ast( self.from_source, lang_utility_objs.ast_delimeters('comma', 'rparen')) if _param: _signature.append(_param) if _ending_token is None or _ending_token.name == 'rparen': break _queue.append(Signature(_signature)) elif _start.name == 'dot': _lookup = list(self.attr_lookup(_start)) if not _lookup: raise lang_exceptions.InvalidSyntax( f"In '{self.file}', line {self.line_counter.line_number}:\nInvalid Syntax: '{_start.value}'" ) _queue.append(TrailingNameLookup(_lookup)) _start = next(self.header, None) return _queue, self.delimeter, _start
def push(self, _name_action) -> None: if _name_action.ast_type == 'trailing_name_lookup' and ( not self.names or (self.names and self.names[-1].ast_type != 'signature')): raise lang_exceptions.InvalidSyntax( f"In '{self.file}', line {self.line_counter.line_number}:\nInvalid Syntax: '.'" ) self.names.append(_name_action)
def get_obj_ast(cls, _, _parser_obj, _header: typing.Iterator, _lines: typing.Iterator, _line_counter: LineCount, _file: str, _current_level: int, scope: Scope) -> typing.Any: _identifier = next(_header, None) if _identifier is None: raise lang_exceptions.InvalidSyntax( f"In '{_file}', line {_line_counter.line_number}:\nInvalid Syntax Error: expected identifier name" ) if _identifier.value not in cls.idenifiers: raise lang_exceptions.InvalidIdentifier( f"In '{_file}', line {_line_counter.line_number}:\nInvalid Indentifier: '{_identifier.value}'" ) _ = cls.idenifiers[_identifier.value].init_identifier( _parser_obj, _header, _lines, _line_counter, _file, _current_level + 4, scope)
def start(self) -> None: _start = next(self, None) while _start is not None: _t, *_trailing = _start if self.level and not _t.is_space or _t.is_space and self.level != len( _t): raise lang_exceptions.IndentationError( f"In '{self.file}', line {self.line_count.line_number}:\nIndentationError: expected {self.level}, got {len(_t)}" ) _trailing = iter(_trailing) if _t.is_space: _t, *_trailing = _trailing _trailing = iter(_trailing) if _t.token_type not in self.token_matcher: raise lang_exceptions.InvalidSyntax( f"In '{self.file}', line {self.line_count.line_number}:\nInvalid Syntax: invalid identifier '{_t.value}'" ) executable_ast = self.token_matcher[_t.token_type].get_obj_ast( _t, self.__class__, _trailing, self.stream, self.line_count, self.file, self.level, self.scope) print('got executable ast: ', executable_ast) print('-' * 20) _start = next(self, None) next(self.line_count)