Parser: 91.7% of the corpus, operator symbols and #code statements

operatorSymbol now tries multi-token forms first, so 'operator *[]' is no longer
cut short by the bare '*'. '#code'/'#insert' take a whole statement, and a
statement that already consumed its ';' satisfies the enclosing declaration.

Ratchet 650/714.
This commit is contained in:
hgranthorner
2026-08-04 12:40:20 -04:00
parent dc53033898
commit 47a2c5805e
7 changed files with 143 additions and 85 deletions

View File

@@ -15,24 +15,24 @@ import java.io.File
class DebugParseTest : BasePlatformTestCase() {
private val snippets =
listOf(
"f :: () -> a: int = 1;\n",
"f :: () -> a: int = 1 { }\n",
"f :: () -> a: int = xx { }\n",
"f :: () -> a: int = 1 #foreign lib;\n",
"g :: () { x := 1; }\n",
"T :: struct {\n p := .06;\n b: BG;\n b.shape.kind = .ABS;\n b.color = V4.{.00, .10, 1};\n}\n",
"T :: struct {\n orientation: enum u8 {\n H :: 0;\n V :: 1;\n }\n\n d: BT;\n}\n",
"T :: struct {\n using,except .[\"x\"] orientation: Quaternion;\n}\n",
"operator *[] :: (b: *Bucket, index: int) -> *int { return null; }\n",
"code :: #code a := Vector3.{1, 1, 1};\n",
)
/** Corpus files to dump the first error of. */
private val corpusFiles =
listOf(
"modules/Basic/Array.jai",
"modules/Debug/windows.jai",
"modules/Simp/backend/gl.jai",
"modules/GetRect/system/occlusion.jai",
"modules/POSIX/compare_bindings.jai",
"modules/Android/Toolchain/apk.jai",
"modules/Curl/examples/ftp.jai",
"modules/Objective_C/LightweightRenderingView/module.jai",
"modules/GetRect/widgets/color_picker.jai",
"modules/GetRect/widgets/slidable_region.jai",
"how_to/094_array_operators.jai",
"how_to/044_using_advanced/main.jai",
"how_to/630_compiler_get_nodes.jai",
"modules/Bucket_Array.jai",
"modules/Android/Toolchain/adb.jai",
"modules/Hash_Table.jai",
)
fun testCorpusFiles() {
@@ -71,14 +71,25 @@ class DebugParseTest : BasePlatformTestCase() {
private fun dumpFile(file: File) {
val text = file.readText()
val psi = PsiFileFactory.getInstance(project).createFileFromText(file.name, JaiLanguage, text)
val error = firstError(psi)
if (error == null) {
val errors = mutableListOf<PsiErrorElement>()
psi.accept(
object : PsiRecursiveElementWalkingVisitor() {
override fun visitErrorElement(element: PsiErrorElement) {
errors.add(element)
super.visitErrorElement(element)
}
},
)
if (errors.isEmpty()) {
println("${file.name}: clean")
return
}
val line = text.substring(0, error.textOffset).count { it == '\n' } + 1
println("${file.name}:$line: ${error.errorDescription}")
println(" at '${text.substring(error.textOffset).take(80).replace("\n", "\\n")}'")
println("${file.name}: ${errors.size} error(s)")
for (error in errors.take(6)) {
val line = text.substring(0, error.textOffset).count { it == '\n' } + 1
println(" :$line ${error.errorDescription}")
println(" at '${text.substring(error.textOffset).take(70).replace("\n", "\\n")}'")
}
}
private fun firstError(file: PsiFile): PsiErrorElement? {

View File

@@ -106,7 +106,7 @@ class JaiCorpusParserTest : BasePlatformTestCase() {
private companion object {
/** Ratchet. Raise it as the grammar improves; never lower it. */
const val MIN_CLEAN_FILES = 645
const val MIN_CLEAN_FILES = 650
const val REPORTED_ERRORS = 25
const val REPORTED_KINDS = 20
const val GOT_WIDTH = 14