Parser: cover full Jai corpus

This commit is contained in:
hgranthorner
2026-08-04 13:44:59 -04:00
parent 8265389f64
commit bb54639ce5
21 changed files with 649 additions and 113 deletions

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 = 650
const val MIN_CLEAN_FILES = 714
const val REPORTED_ERRORS = 25
const val REPORTED_KINDS = 20
const val GOT_WIDTH = 14

View File

@@ -0,0 +1,68 @@
package dev.hgh.jai.parser
import com.intellij.psi.PsiErrorElement
import com.intellij.psi.PsiFileFactory
import com.intellij.psi.PsiRecursiveElementWalkingVisitor
import com.intellij.testFramework.fixtures.BasePlatformTestCase
import dev.hgh.jai.JaiLanguage
/**
* Focused regressions for syntax recovered while closing the corpus gate.
*
* [JaiCorpusParserTest] proves acceptance across the full local distribution;
* these small examples make the individual grammar contracts easy to exercise
* while iterating on generated PSI.
*/
class JaiParserLongTailTest : BasePlatformTestCase() {
fun testLongTailConstructsParseWithoutErrors() {
val snippets =
listOf(
"result=, output, error := call();",
"""
Thing :: struct {
using,except SKIP_THESE field: Field;
}
proc :: (using,except(x,y,z) value: Value) {}
""".trimIndent(),
"""
factory :: () {
callback = p => { release(p); };
result := { callback, p };
}
""".trimIndent(),
"""
while `loop := ready { break loop; }
if #compile_time { report(); } else { fallback(); }
if (release) #if ENABLE_STATISTICS report();
""".trimIndent(),
"""
operator ! :: inline (value: Flag) -> bool { return value; }
push_context,defer_pop ctx;
return first, second,;
""".trimIndent(),
)
val factory = PsiFileFactory.getInstance(project)
for ((index, text) in snippets.withIndex()) {
val file = factory.createFileFromText("long-tail-$index.jai", JaiLanguage, text)
val errors = errorsIn(file)
assertTrue(
"Long-tail snippet $index produced parser errors: ${errors.joinToString { it.errorDescription }}\n$text",
errors.isEmpty(),
)
}
}
private fun errorsIn(file: com.intellij.psi.PsiFile): List<PsiErrorElement> {
val errors = mutableListOf<PsiErrorElement>()
file.accept(
object : PsiRecursiveElementWalkingVisitor() {
override fun visitErrorElement(element: PsiErrorElement) {
errors.add(element)
super.visitErrorElement(element)
}
},
)
return errors
}
}