예제 #1
0
 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))
예제 #2
0
 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
예제 #3
0
 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 ()
예제 #4
0
 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)
예제 #5
0
    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
예제 #6
0
    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()
예제 #7
0
    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
예제 #8
0
 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()
         })
예제 #9
0
 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
예제 #10
0
 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))
예제 #11
0
 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
예제 #12
0
 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
예제 #13
0
 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)
예제 #14
0
 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()
예제 #15
0
 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)
예제 #16
0
 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)
예제 #17
0
 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)