Parser: corpus parse rate 69% -> 81%, and stop --tests from sticking
Grammar: 'using,except(x)' modifiers, '#ifx' with block branches, unions with
parameters, multi-value initializers, mixed 'name:, lvalue = call()' targets,
'push_context' with no explicit context, 'operator []=', '#foreign lib "symbol"',
keyword-named arguments such as 'remove={...}', and '#insert (options) body'.
Directive flags now require adjacency: without it, in
'(callback: (*GUID) #c_call, lpContext: *void)' the flag swallowed ', lpContext'.
procModifier is now just directiveExpr — one rule for directives in both
positions, so fixes apply everywhere.
jaitest: a '--tests' filter persisted through Gradle's configuration cache, so a
later unfiltered ./jaitest silently re-ran only that class and printed OK.
Unfiltered runs now disable the configuration cache.
MIN_CLEAN_FILES ratchets the corpus gate at 575/714.
This commit is contained in:
@@ -4,6 +4,7 @@ import com.intellij.lang.PsiBuilder
|
||||
import com.intellij.lang.parser.GeneratedParserUtilBase
|
||||
import com.intellij.psi.TokenType
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import dev.hgh.jai.lexer.JaiTokenTypes
|
||||
import dev.hgh.jai.lexer.JaiTokenTypes as T
|
||||
|
||||
/**
|
||||
@@ -170,6 +171,39 @@ object JaiParserUtil : GeneratedParserUtilBase() {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* A `,flag` suffix on a directive: `#import,file`, `#library,system,link_always`,
|
||||
* `#run,stallable`.
|
||||
*
|
||||
* Adjacency is required. Without it, in
|
||||
* `(callback: (*GUID) #c_call, lpContext: *void)` the flag would swallow
|
||||
* `, lpContext` and the parameter list would fall apart. Every flag in the corpus
|
||||
* is written tight against the directive; a separator comma always has a space.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directiveFlag(
|
||||
b: PsiBuilder,
|
||||
level: Int,
|
||||
): Boolean {
|
||||
if (b.tokenType !== T.COMMA) return false
|
||||
if (b.rawLookup(-1) === TokenType.WHITE_SPACE) return false
|
||||
if (b.rawLookup(1) !== T.IDENT) return false
|
||||
b.advanceLexer()
|
||||
b.advanceLexer()
|
||||
return true
|
||||
}
|
||||
|
||||
/** `name =` inside an argument list, where `name` may be a keyword (`remove=`). */
|
||||
@JvmStatic
|
||||
fun isNamedArgumentAhead(
|
||||
b: PsiBuilder,
|
||||
level: Int,
|
||||
): Boolean {
|
||||
val t = b.tokenType ?: return false
|
||||
if (t !== T.IDENT && t !in JaiTokenTypes.KEYWORDS) return false
|
||||
return b.lookAhead(1) === T.EQ
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ operators
|
||||
|
||||
/**
|
||||
@@ -291,7 +325,8 @@ object JaiParserUtil : GeneratedParserUtilBase() {
|
||||
* `foo :: () {}` apart from `foo();`.
|
||||
*
|
||||
* The prefix skip covers `#as using base: Document;`,
|
||||
* `#overlay (unknown.vtable) using vtable: *Vtable;` and the macro-exported
|
||||
* `#overlay (unknown.vtable) using vtable: *Vtable;`,
|
||||
* `#as using,except(vtable) iunknown: IUnknown;` and the macro-exported
|
||||
* `` `it := entry.value; ``.
|
||||
*/
|
||||
@JvmStatic
|
||||
@@ -300,10 +335,12 @@ object JaiParserUtil : GeneratedParserUtilBase() {
|
||||
level: Int,
|
||||
): Boolean {
|
||||
var i = 0
|
||||
var inPrefix = false
|
||||
loop@ while (true) {
|
||||
when (b.lookAhead(i)) {
|
||||
T.DIRECTIVE, T.KW_USING -> {
|
||||
i++
|
||||
inPrefix = true
|
||||
}
|
||||
|
||||
T.LPAREN -> {
|
||||
@@ -311,6 +348,14 @@ object JaiParserUtil : GeneratedParserUtilBase() {
|
||||
if (i < 0) return false
|
||||
}
|
||||
|
||||
// Only a `,flag` belonging to the prefix, as in `using,except(x)`.
|
||||
// A comma between declared names is handled by the loop below.
|
||||
T.COMMA -> {
|
||||
if (!inPrefix || b.lookAhead(i + 1) !== T.IDENT) break@loop
|
||||
i += 2
|
||||
inPrefix = false
|
||||
}
|
||||
|
||||
else -> {
|
||||
break@loop
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user