public function match($regexp, &$matches = array(), $flags = 0)
    {
        // we do not like empty strings
        if (strlen($regexp) == 0) {
            return false;
        }

        $ret = false;
        $explicitRegexp = strlen($regexp) > 0 && $regexp[0] == "/";
        $substr = substr($this->string, $this->offset);

        if (!$explicitRegexp) {
            $caseSensitive  = TextTokenizer::CASE_SENSITIVE
                & ($this->_flags | $flags);
            $searchAnywhere = TextTokenizer::SEARCH_ANYWHERE
                & ($this->_flags | $flags);
            $modifiers = "us" . ($caseSensitive? "" : "i");
            $regexp = $searchAnywhere
                ? "/($regexp)/$modifiers"
                : "/^\s*($regexp)/$modifiers";
        }

        if (preg_match($regexp, $substr, $matches, PREG_OFFSET_CAPTURE)) {
            $offsetCapture = TextTokenizer::OFFSET_CAPTURE
                              & ($this->_flags | $flags);
            $str = $matches[0][0];
            $offset = $matches[0][1] + strlen($str);

            if ($offsetCapture) {
                // fixes offsets
                foreach ($matches as $i => $match) {
                    $matches[$i][1] += $this->offset;
                }
            } else {
                // ignores offsets
                foreach ($matches as $i => $match) {
                    $matches[$i] = $matches[$i][0];
                }
            }

            if (!ctype_alnum($substr[$offset - 1])
                || $offset == strlen($substr)
                || !ctype_alnum($substr[$offset])
            ) {
                $this->offset += $offset;
                $ret = array(ltrim($str));
            }
        }

        return $ret;
    }