def find_character(self, tokens: t.Sequence[str], receiver: t.Optional[Obj] = None, options: FindOptions = FindOptions() ) -> t.Iterator[t.Tuple['Obj', t.Any]]: if id(self.link) in options.visited_envs: return iter(()) return self.link.find_character( tokens, self.link, options._replace(visited_envs=frozenset((id(self.link), )) | options.visited_envs))
def _dereference(self) -> t.Tuple[Obj, t.Optional[FindMetadata]]: if self._is_expression: assert self._do_not_collapse ret: t.Tuple[Obj, t.Optional[FindMetadata]] = (self._value.value, None) elif self._is_actual: ret = (self._value, self._receiver) else: if self._scope is None: ret = (None, None) else: value, metadata = next( self._scope.parse_full_match( self._value, None, FindOptions(search_environment=True)), (None, None)) # first only assert value is not None, "lookup error" ret = value, metadata # Dereference recursively. Hopefully don't get stuck. while isinstance(ret[0], Reference): ret = ret[0]._dereference() if self._cast is not None and ret[0] is not None: if issubclass(self._cast, Reference): ret = self._cast(ret[0]), ret[1] else: ret = self._cast(ret[0].value), ret[1] # Cache the reference parse (this saves a ton of time) if not self._do_not_collapse and not self._is_collapsed: self._is_actual = True self._is_collapsed = True self._old_value = self._value self._value = ret[0] self._receiver = ret[1] return ret
def parse(self, tokens: t.Sequence[str], receiver: t.Optional[Obj] = None, options: FindOptions = FindOptions() ) -> t.Iterator[t.Tuple['Obj', t.Any, t.Sequence[str]]]: if options.search_variables: return super().parse(tokens, receiver, options) return ()
def find_character(self, tokens: t.Sequence[lark.Token], receiver: t.Optional[Obj] = None, options: FindOptions = FindOptions() ) -> t.Iterator[t.Tuple['Obj', t.Any]]: if receiver is None: receiver = self return self._find(tuple(tokens), tuple(self.characters), 'find_character', receiver, options)
def parse(self, tokens: t.Sequence[lark.Token], receiver: t.Optional[Obj] = None, options: FindOptions = FindOptions() ) -> t.Iterator[t.Tuple[Obj, t.Any, t.Sequence[lark.Token]]]: if receiver is None: receiver = self.value stop = len(tokens) for i, token in enumerate(tokens): if token.type == "SCOPE_OPERATOR": stop = i break else: return self.find_character(tokens, receiver, options) # For matches after a SCOPE_OPERATOR, search only inheritances and not # in the environment options = FindOptions(search_environment=False) for character, meta in self.find_character(tokens[:stop], receiver, options): for ret in character.parse(tokens[stop:], meta.receiver, options): yield ret
def find_character(self, name: t.Sequence[str], receiver: t.Optional['Obj'], options: FindOptions = FindOptions() ) -> t.Iterator[t.Tuple['Obj', t.Any]]: """Search the `Obj`'s character list for any sub-`Obj`s with the given `name`. :param name: The name to search for. :returns: An `Obj` with the requested name, and associated match information. """ raise NotImplementedError()
def parse(self, tokens: t.Sequence[str], receiver: t.Optional['Obj'] = None, options: FindOptions = FindOptions() ) -> t.Iterator[t.Tuple['Obj', FindMetadata, t.Sequence[str]]]: """Given tokens, find the longest prefix match for this object, and return the found object, any associated data for the match, as well as the unused tokens. s :param tokens: Unprocessed tokens. :returns: Found object, associated match data, and remaining tokens. """ pass
def _collect_modifiers( self, rest: t.Sequence[str], verb: 'thapl.context.Obj', obj: 'thapl.context.Obj' ) -> t.Iterator[t.Tuple['thapl.context.Obj', t. Dict[t.Sequence[str], 'thapl.context.Atomic']]]: orig = rest while len(rest) != 0: modifier, metadata, rest = min(verb.parse( rest, options=FindOptions(search_variables=False)), key=lambda k: len(k[2])) assert modifier is not None, f"Bad modifier error ({orig})" yield (modifier, { name: parser.parse_literal(value, obj) for name, value in metadata.patterns.items() })
def find_actor(self, tokens: t.Sequence[str], receiver: t.Optional[Obj] = None, options: FindOptions = FindOptions() ) -> t.Iterator[t.Tuple[Obj, FindMetadata]]: unparsed, match, patterns = self._pattern.match(tokens) if receiver is None: receiver = self.value if not self.value.is_atomic(): receiver = self.value if match and len(unparsed) == 0: yield self.value, FindMetadata(patterns=patterns, receiver=receiver, named=self) return None
def parse_full_match(self, tokens: t.Sequence[str], receiver: t.Optional['Obj'] = None, options: FindOptions = FindOptions() ) -> t.Iterator[t.Tuple['Obj', FindMetadata]]: if receiver is None: receiver = self found = False for obj, metadata, remaining in self.parse(tokens, receiver, options): if len(remaining) == 0: found = True yield obj, metadata if not found: raise LookupException("Can't find [{0!r}], ({1:d}:{2:d})".format( tokens, t.cast(lark.Token, tokens[0]).line, t.cast(lark.Token, tokens[0]).column))
def _find(self, tokens: t.Tuple[lark.Token, ...], entries: t.Tuple[Obj, ...], method: str, receiver: Obj, options: FindOptions = FindOptions() ) -> t.Iterator[t.Tuple[Obj, FindMetadata]]: for entry in entries: found = False if (not options.search_environment and isinstance(entry, EnvironmentLink)): continue for ret, metadata in getattr(entry, method)(tokens, receiver, options): found = True yield ret, metadata if found: return
def parse(self, tokens: t.Sequence[lark.Token], receiver: t.Optional[Obj] = None, options: FindOptions = FindOptions() ) -> t.Iterator[t.Tuple['Obj', t.Any, t.Sequence[str]]]: if receiver is None: receiver = self for i in range(0, len(tokens)): found = False for actor, metadata in self.find_actor(tokens[:i + 1], receiver, options): found = True if (i + 1 < len(tokens) and tokens[i + 1].type == "SCOPE_OPERATOR"): found2 = False subtokens = tokens[i + 2:] if subtokens: for subresult in actor.parse(subtokens, metadata.receiver, options): found2 = True yield subresult if not found2: found = False else: assert isinstance(actor, Reference) yield actor.value, metadata, () # assert False, "not found?!" # ?? # TODO: Throw exception if nothing found? else: yield actor, metadata, tokens[i + 1:] if found: pass # break # TODO: Throw exception? return
def parse(self, tokens: t.Sequence[str], receiver: t.Optional[Obj] = None, options: FindOptions = FindOptions() ) -> t.Iterator[t.Tuple['Obj', FindMetadata, t.Sequence[str]]]: return self.link.parse(tokens, receiver, options)
def parse(self, tokens: t.Sequence[str], receiver: t.Optional[Obj] = None, options: FindOptions = FindOptions() ) -> t.Iterator[t.Tuple[Obj, t.Any, t.Sequence[str]]]: raise NotImplementedError()
def parse(self, tokens: t.Sequence[str], receiver: t.Optional[Obj] = None, options: FindOptions = FindOptions() ) -> t.Iterator[t.Tuple[Obj, t.Any, t.Sequence[str]]]: return self.value.parse(tokens, receiver, options)
def find_character(self, tokens: t.Sequence[str], receiver: t.Optional[Obj] = None, options: FindOptions = FindOptions() ) -> t.Iterator[t.Tuple[Obj, FindMetadata]]: return self.find_actor(tokens, receiver)
def find_character(self, tokens: t.Sequence[str], receiver: t.Optional[Obj] = None, options: FindOptions = FindOptions() ) -> t.Iterator[t.Tuple['Obj', t.Any]]: return self.link.find_character(tokens, receiver, options)