public function parseSourceFile(string $fileContents, string $uri = null) : SourceFileNode {
        $this->lexer = TokenStreamProviderFactory::GetTokenStreamProvider($fileContents);

        $this->reset();

        $sourceFile = new SourceFileNode();
        $this->sourceFile = $sourceFile;
        $sourceFile->fileContents = $fileContents;
        $sourceFile->uri = $uri;
        $sourceFile->statementList = array();
        if ($this->getCurrentToken()->kind !== TokenKind::EndOfFileToken) {
            $inlineHTML = $this->parseInlineHtml($sourceFile);
            $sourceFile->statementList[] = $inlineHTML;
            if ($inlineHTML->echoStatement) {
                $sourceFile->statementList[] = $inlineHTML->echoStatement;
                $inlineHTML->echoStatement->parent = $sourceFile;
                $inlineHTML->echoStatement = null;
            }
        }
        $sourceFile->statementList =
            \array_merge($sourceFile->statementList, $this->parseList($sourceFile, ParseContext::SourceElements));

        $this->sourceFile->endOfFileToken = $this->eat1(TokenKind::EndOfFileToken);
        $this->advanceToken();

        $sourceFile->parent = null;

        return $sourceFile;
    }