Parser: corpus parse rate 81% -> 90%

A bare procedure *type* parameter such as 'proc: (info: *Info, data: T)' has no
arrow, directive or body after the parentheses, so isProcHeaderAhead now accepts
any parenthesised group that contains a ':' or '$' at depth 1.

Also: compound-assignment operator overloads, 'for <=REVERSE *=BY_POINTER',
backticked loop variables and returns, 'cast(T, value)', postfix 'x.(T)' casts,
'{}' as the zero value, '#asm AVX, AVX2 { … }', 'push_context,defer_pop', and
'#string,\%' here-strings (used in how_to/018_print_functions.jai, which the
shipped Jai_Lexer module itself rejects).

A directive prefixing a declaration no longer takes a bare operand: '#add_context
deep_copy_depth: int;' had the directive eating the declared name.

Ratchet raised to 640/714.
This commit is contained in:
hgranthorner
2026-08-04 12:24:02 -04:00
parent 086ae993c5
commit b8e55fcd50
19 changed files with 550 additions and 78 deletions

View File

@@ -579,11 +579,16 @@ open class JaiLexer : LexerBase() {
private fun scanHereString(from: Int): Int {
var p = scanWhile(from) { isSpace(it) }
// Optional `,cr` modifier.
// Optional modifier: `#string,cr ID` in the compiler's lexer
// (module.jai:487), and `#string,\% ID` in how_to/018_print_functions.jai,
// which the shipped Jai_Lexer module does not accept. Any non-space run is
// taken as the modifier; a here-string still has to produce a terminator
// identifier and a newline after it, so this cannot misfire.
if (ch(p) == ','.code) {
p = scanWhile(p + 1) { isSpace(it) }
if (!startsIdentifier(ch(p))) return -1
p = scanIdentifier(p)
val modifierStart = p
p = scanWhile(p) { !isSpace(it) && it != -1 }
if (p == modifierStart) return -1
p = scanWhile(p) { isSpace(it) }
}

View File

@@ -282,11 +282,15 @@ object JaiParserUtil : GeneratedParserUtilBase() {
T.RPAREN -> {
depth--
if (depth == 0) {
// A `name:` or `$T` inside the parentheses can only be a
// parameter list, so the header stands on its own: a bare
// proc *type* like `proc: (info: *Info, data: T)` has no
// arrow, directive or body after it.
if (sawParamMarker) return true
val next = b.lookAhead(i + 1)
return when {
next === T.RIGHT_ARROW -> true
next === T.DIRECTIVE -> true
next === T.LBRACE -> empty || sawParamMarker
return when (next) {
T.RIGHT_ARROW, T.DIRECTIVE -> true
T.LBRACE -> empty
else -> false
}
}
@@ -459,6 +463,7 @@ object JaiParserUtil : GeneratedParserUtilBase() {
): Boolean {
var i = 0
while (true) {
if (b.lookAhead(i) === T.BACKTICK) i++
if (b.lookAhead(i) !== T.IDENT) return false
i++
when (b.lookAhead(i)) {