public function parse($input, $file = null)
    {
        $this->languageSpecifierLine = null;
        $this->input = $input;
        $this->file = $file;
        $this->tags = array();

        try {
            $this->lexer->analyse($this->input, 'en');
        } catch (LexerException $e) {
            throw new ParserException(
                sprintf('Lexer exception "%s" thrown for file %s', $e->getMessage(), $file),
                0,
                $e
            );
        }

        $feature = null;
        while ('EOS' !== ($predicted = $this->predictTokenType())) {
            $node = $this->parseExpression();

            if (null === $node || "\n" === $node) {
                continue;
            }

            if (!$feature && $node instanceof FeatureNode) {
                $feature = $node;
                continue;
            }

            if ($feature && $node instanceof FeatureNode) {
                throw new ParserException(sprintf(
                    'Only one feature is allowed per feature file. But %s got multiple.',
                    $this->file
                ));
            }

            if (is_string($node)) {
                throw new ParserException(sprintf(
                    'Expected Feature, but got text: "%s"%s',
                    $node,
                    $this->file ? ' in file: ' . $this->file : ''
                ));
            }

            if (!$node instanceof FeatureNode) {
                throw new ParserException(sprintf(
                    'Expected Feature, but got %s on line: %d%s',
                    $node->getKeyword(),
                    $node->getLine(),
                    $this->file ? ' in file: ' . $this->file : ''
                ));
            }
        }

        return $feature;
    }