public function parse($text, TokenList $tokenList = null, $recursive = false) {
        if ($this->startRule === null) {
            throw new ParserException('Start rule not set');
        }

        if ($this->lexer === null) {
            throw new ParserException('Lexer not set');
        }

        uasort($this->rules, [$this, 'sortRulesByOrder']);

        $this->connectRulesToLexer();

        \Event::fire('vikon.parser.before.parse', [&$text]);

        $tokenList = $this->lexer->tokenize($text, $this->startRule->getName(), $tokenList);

        foreach ($this->rules as $rule) {
            $rule->finalize($tokenList, $recursive);
        }

        return $tokenList;
    }