WIPPU
diff --git a/compiler/psi/src/org/jetbrains/kotlin/KtFileWithExpressions.kt b/compiler/psi/src/org/jetbrains/kotlin/KtFileWithExpressions.kt
new file mode 100644
index 0000000..549a8e2
--- /dev/null
+++ b/compiler/psi/src/org/jetbrains/kotlin/KtFileWithExpressions.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin
+
+import com.intellij.lang.ASTNode
+import com.intellij.psi.FileViewProvider
+import org.jetbrains.kotlin.psi.KtBlockExpression
+import org.jetbrains.kotlin.psi.KtDeclarationImpl
+import org.jetbrains.kotlin.psi.KtExpression
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.psi.KtVisitor
+
+class KtFileWithExpressions(
+    viewProvider: FileViewProvider,
+) : KtFile(viewProvider, isCompiled = false) {
+    init {
+        contentElementType = KtNodeTypes.FILE_WITH_EXPRESSIONS
+    }
+
+    val expressionHolders: List<KtFileExpressionHolder>
+        get() = findChildrenByClass(KtFileExpressionHolder::class.java).toList()
+}
+
+class KtFileExpressionHolder(node: ASTNode) : KtDeclarationImpl(node) {
+    val block: KtBlockExpression?
+        get() = findChildByClass(KtBlockExpression::class.java)
+
+    val expressions: List<KtExpression>
+        get() = block?.statements.orEmpty()
+
+    override fun <R, D> accept(visitor: KtVisitor<R, D>, data: D): R? = visitor.visitKtFileExpressionHolder(this, data)
+}
\ No newline at end of file
diff --git a/compiler/psi/src/org/jetbrains/kotlin/KtNodeTypes.java b/compiler/psi/src/org/jetbrains/kotlin/KtNodeTypes.java
index 56ec02b..bb03c88 100644
--- a/compiler/psi/src/org/jetbrains/kotlin/KtNodeTypes.java
+++ b/compiler/psi/src/org/jetbrains/kotlin/KtNodeTypes.java
@@ -28,6 +28,8 @@
     IElementType CLASS     = KtStubElementTypes.CLASS;
     IElementType FUN       = KtStubElementTypes.FUNCTION;
     IElementType PROPERTY  = KtStubElementTypes.PROPERTY;
+    IElementType FILE_EXPRESSION_HOLDER = new KtNodeType("FILE_EXPRESSION_HOLDER", KtFileExpressionHolder.class);
+
     IElementType DESTRUCTURING_DECLARATION = new KtNodeType("DESTRUCTURING_DECLARATION", KtDestructuringDeclaration.class);
     IElementType DESTRUCTURING_DECLARATION_ENTRY = new KtNodeType("DESTRUCTURING_DECLARATION_ENTRY", KtDestructuringDeclarationEntry.class);
 
@@ -168,4 +170,6 @@
     IFileElementType TYPE_CODE_FRAGMENT = KtStubElementTypes.TYPE_CODE_FRAGMENT;
     IFileElementType EXPRESSION_CODE_FRAGMENT = KtStubElementTypes.EXPRESSION_CODE_FRAGMENT;
     IFileElementType BLOCK_CODE_FRAGMENT = KtStubElementTypes.BLOCK_CODE_FRAGMENT;
+
+    IFileElementType FILE_WITH_EXPRESSIONS = KtStubElementTypes.FILE_WITH_EXPRESSIONS;
 }
diff --git a/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParser.java b/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParser.java
index 9651885..f67b059 100644
--- a/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParser.java
+++ b/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParser.java
@@ -81,6 +81,13 @@
     }
 
     @NotNull
+    public static ASTNode parseFileWithExpressions(PsiBuilder psiBuilder) {
+        KotlinParsing ktParsing = KotlinParsing.createForTopLevel(new SemanticWhitespaceAwarePsiBuilderImpl(psiBuilder));
+        ktParsing.parseFileWithExpressions();
+        return psiBuilder.getTreeBuilt();
+    }
+
+    @NotNull
     public static ASTNode parseLambdaExpression(PsiBuilder psiBuilder) {
         KotlinParsing ktParsing = KotlinParsing.createForTopLevel(new SemanticWhitespaceAwarePsiBuilderImpl(psiBuilder));
         ktParsing.parseLambdaExpression();
diff --git a/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParsing.java b/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParsing.java
index 6d23221..9a77ba5 100644
--- a/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParsing.java
+++ b/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParsing.java
@@ -29,6 +29,7 @@
 
 import static org.jetbrains.kotlin.KtNodeTypes.*;
 import static org.jetbrains.kotlin.lexer.KtTokens.*;
+import static org.jetbrains.kotlin.parsing.KotlinExpressionParsing.EXPRESSION_FIRST;
 import static org.jetbrains.kotlin.parsing.KotlinParsing.AnnotationParsingMode.*;
 import static org.jetbrains.kotlin.parsing.KotlinWhitespaceAndCommentsBindersKt.PRECEDING_ALL_BINDER;
 import static org.jetbrains.kotlin.parsing.KotlinWhitespaceAndCommentsBindersKt.TRAILING_ALL_BINDER;
@@ -184,6 +185,19 @@
         fileMarker.done(KT_FILE);
     }
 
+    void parseFileWithExpressions() {
+        PsiBuilder.Marker fileMarker = mark();
+
+        parsePreamble();
+
+        while (!eof()) {
+            parseTopLevelDeclaration();
+        }
+
+        checkUnclosedBlockComment();
+        fileMarker.done(FILE_WITH_EXPRESSIONS);
+    }
+
     private void checkUnclosedBlockComment() {
         if (BLOCK_DOC_COMMENT_SET.contains(myBuilder.rawLookup(-1))) {
             int startOffset = myBuilder.rawTokenTypeStart(-1);
@@ -485,7 +499,7 @@
      *   : object
      *   ;
      */
-    private void parseTopLevelDeclaration() {
+    private void parseTopLevelDeclaration(boolean allowExpressions) {
         if (at(SEMICOLON)) {
             advance(); // SEMICOLON
             return;
@@ -501,24 +515,36 @@
 
         IElementType declType = parseCommonDeclaration(detector, NameParsingMode.REQUIRED, DeclarationParsingMode.MEMBER_OR_TOPLEVEL);
 
-        if (declType == null && at(LBRACE)) {
-            error("Expecting a top level declaration");
-            parseBlock();
-            declType = FUN;
-        }
+        if (declType == null && allowExpressions && atSet(EXPRESSION_FIRST)) {
+            parseExpressionHolder();
+        } else {
+            if (declType == null && at(LBRACE)) {
+                error("Expecting a top level declaration");
+                parseBlock();
+                declType = FUN;
+            }
 
-        if (declType == null && at(IMPORT_KEYWORD)) {
-            error("imports are only allowed in the beginning of file");
-            parseImportDirectives();
-            decl.drop();
+            if (declType == null && at(IMPORT_KEYWORD)) {
+                error("imports are only allowed in the beginning of file");
+                parseImportDirectives();
+                decl.drop();
+            }
+            else if (declType == null) {
+                errorAndAdvance("Expecting a top level declaration");
+                decl.drop();
+            }
+            else {
+                closeDeclarationWithCommentBinders(decl, declType, true);
+            }
         }
-        else if (declType == null) {
-            errorAndAdvance("Expecting a top level declaration");
-            decl.drop();
-        }
-        else {
-            closeDeclarationWithCommentBinders(decl, declType, true);
-        }
+    }
+
+    private void parseExpressionHolder() {
+        PsiBuilder.Marker holder = mark();
+        PsiBuilder.Marker block = mark();
+        myExpressionParsing.parseExpression();
+        block.done(BLOCK);
+        holder.done(FILE_EXPRESSION_HOLDER);
     }
 
     public IElementType parseCommonDeclaration(
@@ -2347,7 +2373,7 @@
             recoverOnParenthesizedWordForPlatformTypes(0, "Mutable", true);
 
             if (expect(IDENTIFIER, "Expecting type name",
-                       TokenSet.orSet(KotlinExpressionParsing.EXPRESSION_FIRST, KotlinExpressionParsing.EXPRESSION_FOLLOW, DECLARATION_FIRST))) {
+                       TokenSet.orSet(EXPRESSION_FIRST, KotlinExpressionParsing.EXPRESSION_FOLLOW, DECLARATION_FIRST))) {
                 reference.done(REFERENCE_EXPRESSION);
             }
             else {
diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtFileWithExpressionsType.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/KtFileWithExpressionsType.kt
new file mode 100644
index 0000000..a6dec68
--- /dev/null
+++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtFileWithExpressionsType.kt
@@ -0,0 +1,22 @@
+package org.jetbrains.kotlin.psi
+
+import com.intellij.lang.ASTNode
+import com.intellij.lang.PsiBuilderFactory
+import com.intellij.psi.PsiElement
+import com.intellij.psi.tree.IFileElementType
+import org.jetbrains.kotlin.idea.KotlinLanguage
+import org.jetbrains.kotlin.parsing.KotlinParser
+
+class KtFileWithExpressionsType : IFileElementType(NAME, KotlinLanguage.INSTANCE) {
+    override fun doParseContents(chameleon: ASTNode, psi: PsiElement): ASTNode? {
+        val project = psi.project
+        val languageForParser = getLanguageForParser(psi)
+        val builder = PsiBuilderFactory.getInstance().createBuilder(project, chameleon, null, languageForParser, chameleon.chars)
+        return KotlinParser.parseFileWithExpressions(builder).firstChildNode
+    }
+
+    companion object {
+        private const val NAME = "kotlin.FILE_WITH_EXPRESSIONS"
+    }
+}
+
diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt
index 5d33cf7..b663c27 100644
--- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt
+++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt
@@ -11,9 +11,13 @@
 import com.intellij.psi.PsiElement
 import com.intellij.psi.PsiFile
 import com.intellij.psi.PsiFileFactory
+import com.intellij.psi.PsiManager
+import com.intellij.psi.impl.PsiManagerEx
 import com.intellij.psi.util.PsiTreeUtil
+import com.intellij.testFramework.LightVirtualFile
 import com.intellij.util.LocalTimeCounter
 import org.jetbrains.annotations.NonNls
+import org.jetbrains.kotlin.KtFileWithExpressions
 import org.jetbrains.kotlin.idea.KotlinFileType
 import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
 import org.jetbrains.kotlin.lexer.KtTokens
@@ -607,6 +611,16 @@
         return KtBlockCodeFragment(project, "fragment.kt", text, null, context)
     }
 
+    fun createFileWithExpressions(fileName: String, @NonNls text: String): KtFileWithExpressions {
+        val psiManager = PsiManager.getInstance(project) as PsiManagerEx
+        val viewProvider = psiManager.fileManager.createFileViewProvider(
+            LightVirtualFile(fileName, KotlinFileType.INSTANCE, text),
+            /* eventSystemEnabled = */true
+        )
+        return KtFileWithExpressions(viewProvider)
+    }
+
+
     fun createIf(condition: KtExpression, thenExpr: KtExpression, elseExpr: KtExpression? = null): KtIfExpression {
         return (if (elseExpr != null)
             createExpressionByPattern("if ($0) $1 else $2", condition, thenExpr, elseExpr) as KtIfExpression
diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtVisitor.java b/compiler/psi/src/org/jetbrains/kotlin/psi/KtVisitor.java
index 0894e0b..0e7505e 100644
--- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtVisitor.java
+++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtVisitor.java
@@ -18,6 +18,7 @@
 
 import com.intellij.psi.PsiElementVisitor;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.kotlin.KtFileExpressionHolder;
 
 public class KtVisitor<R, D> extends PsiElementVisitor {
     public R visitKtElement(@NotNull KtElement element, D data) {
@@ -364,6 +365,10 @@
         return visitAnonymousInitializer(initializer, data);
     }
 
+    public R visitKtFileExpressionHolder(@NotNull KtFileExpressionHolder holder, D data) {
+        return visitDeclaration(holder, data);
+    }
+
     public R visitClassInitializer(@NotNull KtClassInitializer initializer, D data) {
         return visitAnonymousInitializer(initializer, data);
     }
diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java
index 8a80754..04cf406 100644
--- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java
+++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java
@@ -17,6 +17,7 @@
 package org.jetbrains.kotlin.psi.stubs.elements;
 
 import com.intellij.psi.tree.TokenSet;
+import org.jetbrains.kotlin.KtFileExpressionHolder;
 import org.jetbrains.kotlin.psi.*;
 
 public interface KtStubElementTypes {
@@ -93,6 +94,7 @@
     KtTypeCodeFragmentType TYPE_CODE_FRAGMENT = new KtTypeCodeFragmentType();
     KtExpressionCodeFragmentType EXPRESSION_CODE_FRAGMENT = new KtExpressionCodeFragmentType();
     KtBlockCodeFragmentType BLOCK_CODE_FRAGMENT = new KtBlockCodeFragmentType();
+    KtFileWithExpressionsType FILE_WITH_EXPRESSIONS = new KtFileWithExpressionsType();
 
     KtTypeProjectionElementType TYPE_PROJECTION = new KtTypeProjectionElementType("TYPE_PROJECTION");
 
diff --git a/compiler/testData/parseFileWithExpressions/topLevelExpression.kt b/compiler/testData/parseFileWithExpressions/topLevelExpression.kt
new file mode 100644
index 0000000..c294f55
--- /dev/null
+++ b/compiler/testData/parseFileWithExpressions/topLevelExpression.kt
@@ -0,0 +1,15 @@
+package a.b.c
+
+class A
+val x = 10
+
+1 + 2
+
+run {
+
+}
+
+println(42)
+
+val y
+    get() = 1
\ No newline at end of file
diff --git a/compiler/tests-for-compiler-generator/tests/org/jetbrains/kotlin/test/generators/GenerateJUnit3CompilerTests.kt b/compiler/tests-for-compiler-generator/tests/org/jetbrains/kotlin/test/generators/GenerateJUnit3CompilerTests.kt
index cde1258..c94c58f 100644
--- a/compiler/tests-for-compiler-generator/tests/org/jetbrains/kotlin/test/generators/GenerateJUnit3CompilerTests.kt
+++ b/compiler/tests-for-compiler-generator/tests/org/jetbrains/kotlin/test/generators/GenerateJUnit3CompilerTests.kt
@@ -93,6 +93,7 @@
                 model("psi", testMethod = "doParsingTest", pattern = "^(.*)\\.kts?$")
                 model("parseCodeFragment/expression", testMethod = "doExpressionCodeFragmentParsingTest", extension = "kt")
                 model("parseCodeFragment/block", testMethod = "doBlockCodeFragmentParsingTest", extension = "kt")
+                model("parseFileWithExpressions", testMethod = "doFileWithExpressionsTest", extension = "kt")
             }
 
             testClass<AbstractLightAnalysisModeTest> {
diff --git a/compiler/tests/org/jetbrains/kotlin/parsing/AbstractParsingTest.java b/compiler/tests/org/jetbrains/kotlin/parsing/AbstractParsingTest.java
index cdcf231..31f3546 100644
--- a/compiler/tests/org/jetbrains/kotlin/parsing/AbstractParsingTest.java
+++ b/compiler/tests/org/jetbrains/kotlin/parsing/AbstractParsingTest.java
@@ -91,6 +91,10 @@
         doBaseTest(filePath, KtNodeTypes.EXPRESSION_CODE_FRAGMENT, null);
     }
 
+    protected void doFileWithExpressionsTest(@NotNull String filePath) {
+        doBaseTest(filePath, KtNodeTypes.FILE_WITH_EXPRESSIONS, null);
+    }
+
     protected void doBlockCodeFragmentParsingTest(@NotNull String filePath) {
         doBaseTest(filePath, KtNodeTypes.BLOCK_CODE_FRAGMENT, null);
     }
@@ -137,6 +141,8 @@
         }
         else if (fileType == KtNodeTypes.BLOCK_CODE_FRAGMENT) {
             return psiFactory.createBlockCodeFragment(fileContent, null);
+        }  else if (fileType == KtNodeTypes.FILE_WITH_EXPRESSIONS) {
+            return psiFactory.createFileWithExpressions(FileUtil.getNameWithoutExtension(PathUtil.getFileName(filePath)), fileContent);
         }
         else {
             return createPsiFile(FileUtil.getNameWithoutExtension(PathUtil.getFileName(filePath)), fileContent);