def scan(self, restrict):
        while True:
            best_pat = None
            best_pat_len = 0
            for p, regexp in self.patterns:
                if restrict and p not in restrict and p not in self.ignore:
                    continue
                m = regexp.match(self.input, self.pos)
                if m:
                    best_pat = p
                    best_pat_len = len(m.group(0))
                    break
            if best_pat is None:
                msg = "Bad Token"
                if restrict:
                    msg = "Trying to find one of " + ", ".join(restrict)
                raise SyntaxError(self.pos, msg)
            if best_pat in self.ignore:
                self.pos += best_pat_len
            else:
                end_pos = self.pos + best_pat_len
                token = (
                    self.pos,
                    end_pos,
                    best_pat,
                    self.input[self.pos:end_pos]
                )
                self.pos = end_pos
                if not self.tokens or token != self.tokens[-1]:
                    self.tokens.append(token)
                    self.restrictions.append(restrict)
                    return 1
                break
        return 0