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:
hgranthorner
2026-08-04 12:20:36 -04:00
parent 840a503e40
commit 086ae993c5
24 changed files with 728 additions and 271 deletions

12
jaitest
View File

@@ -9,14 +9,24 @@
# with `java.io.EOFException` or a missing in-progress-results bin. That is an # with `java.io.EOFException` or a missing in-progress-results bin. That is an
# infrastructure failure, not a test failure, so it is retried once. # infrastructure failure, not a test failure, so it is retried once.
# #
# A `--tests` filter STICKS: Gradle reuses the configuration cache entry from the
# previous run, so a later unfiltered `./jaitest` silently re-runs just that one
# class and reports OK. Unfiltered runs therefore disable the configuration cache,
# which is the only reliable way to get the whole suite back.
#
# Usage: ./jaitest [gradle args...] e.g. ./jaitest --tests '*Lexer*' # Usage: ./jaitest [gradle args...] e.g. ./jaitest --tests '*Lexer*'
set -uo pipefail set -uo pipefail
cd "$(dirname "$0")" || exit 1 cd "$(dirname "$0")" || exit 1
extra=()
if [[ " $* " != *" --tests "* ]]; then
extra+=(--no-configuration-cache)
fi
run_gradle() { run_gradle() {
rm -rf build/reports/tests/test rm -rf build/reports/tests/test
./jaigradle cleanTest test "$@" 2>&1 | grep -vE '^\[[0-9.]+s\]\[warning\]\[cds\]' ./jaigradle cleanTest test "${extra[@]}" "$@" 2>&1 | grep -vE '^\[[0-9.]+s\]\[warning\]\[cds\]'
return "${PIPESTATUS[0]}" return "${PIPESTATUS[0]}"
} }

View File

@@ -101,12 +101,13 @@ public class JaiParser implements PsiParser, LightPsiParser {
} }
/* ********************************************************** */ /* ********************************************************** */
// '---' | expr // '---' | namedArgument | expr
public static boolean argument(PsiBuilder builder_, int level_) { public static boolean argument(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "argument")) return false; if (!recursion_guard_(builder_, level_, "argument")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_, level_, _NONE_, ARGUMENT, "<argument>"); Marker marker_ = enter_section_(builder_, level_, _NONE_, ARGUMENT, "<argument>");
result_ = consumeToken(builder_, TRIPLE_MINUS); result_ = consumeToken(builder_, TRIPLE_MINUS);
if (!result_) result_ = namedArgument(builder_, level_ + 1);
if (!result_) result_ = expr(builder_, level_ + 1, -1); if (!result_) result_ = expr(builder_, level_ + 1, -1);
exit_section_(builder_, level_, marker_, result_, false, null); exit_section_(builder_, level_, marker_, result_, false, null);
return result_; return result_;
@@ -157,6 +158,40 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
/* ********************************************************** */
// <<exprNoAssign>> (',' <<exprNoAssign>>)*
static boolean assignTargets_(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "assignTargets_")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = exprNoAssign(builder_, level_ + 1);
result_ = result_ && assignTargets__1(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// (',' <<exprNoAssign>>)*
private static boolean assignTargets__1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "assignTargets__1")) return false;
while (true) {
int pos_ = current_position_(builder_);
if (!assignTargets__1_0(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "assignTargets__1", pos_)) break;
}
return true;
}
// ',' <<exprNoAssign>>
private static boolean assignTargets__1_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "assignTargets__1_0")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = consumeToken(builder_, COMMA);
result_ = result_ && exprNoAssign(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
/* ********************************************************** */ /* ********************************************************** */
// '`' (IDENT | 'defer' | 'return' | 'push_context' | 'operator') // '`' (IDENT | 'defer' | 'return' | 'push_context' | 'operator')
public static boolean backtickExpr(PsiBuilder builder_, int level_) { public static boolean backtickExpr(PsiBuilder builder_, int level_) {
@@ -326,12 +361,12 @@ public class JaiParser implements PsiParser, LightPsiParser {
} }
/* ********************************************************** */ /* ********************************************************** */
// procModifier | 'using' // procModifier | usingModifier_
static boolean declModifier_(PsiBuilder builder_, int level_) { static boolean declModifier_(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declModifier_")) return false; if (!recursion_guard_(builder_, level_, "declModifier_")) return false;
boolean result_; boolean result_;
result_ = procModifier(builder_, level_ + 1); result_ = procModifier(builder_, level_ + 1);
if (!result_) result_ = consumeToken(builder_, KW_USING); if (!result_) result_ = usingModifier_(builder_, level_ + 1);
return result_; return result_;
} }
@@ -391,9 +426,9 @@ public class JaiParser implements PsiParser, LightPsiParser {
} }
/* ********************************************************** */ /* ********************************************************** */
// ':' [<<exprNoAssign>>] procModifier* [('=' | ':') initializer] // ':' [<<exprNoAssign>>] procModifier* [',' assignTargets_] [('=' | ':') initializerList_]
// | ':=' initializer // | ':=' initializerList_
// | '::' initializer // | '::' initializerList_
static boolean declTail_(PsiBuilder builder_, int level_) { static boolean declTail_(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declTail_")) return false; if (!recursion_guard_(builder_, level_, "declTail_")) return false;
boolean result_; boolean result_;
@@ -405,7 +440,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
// ':' [<<exprNoAssign>>] procModifier* [('=' | ':') initializer] // ':' [<<exprNoAssign>>] procModifier* [',' assignTargets_] [('=' | ':') initializerList_]
private static boolean declTail__0(PsiBuilder builder_, int level_) { private static boolean declTail__0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declTail__0")) return false; if (!recursion_guard_(builder_, level_, "declTail__0")) return false;
boolean result_; boolean result_;
@@ -414,6 +449,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
result_ = result_ && declTail__0_1(builder_, level_ + 1); result_ = result_ && declTail__0_1(builder_, level_ + 1);
result_ = result_ && declTail__0_2(builder_, level_ + 1); result_ = result_ && declTail__0_2(builder_, level_ + 1);
result_ = result_ && declTail__0_3(builder_, level_ + 1); result_ = result_ && declTail__0_3(builder_, level_ + 1);
result_ = result_ && declTail__0_4(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
@@ -436,51 +472,69 @@ public class JaiParser implements PsiParser, LightPsiParser {
return true; return true;
} }
// [('=' | ':') initializer] // [',' assignTargets_]
private static boolean declTail__0_3(PsiBuilder builder_, int level_) { private static boolean declTail__0_3(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declTail__0_3")) return false; if (!recursion_guard_(builder_, level_, "declTail__0_3")) return false;
declTail__0_3_0(builder_, level_ + 1); declTail__0_3_0(builder_, level_ + 1);
return true; return true;
} }
// ('=' | ':') initializer // ',' assignTargets_
private static boolean declTail__0_3_0(PsiBuilder builder_, int level_) { private static boolean declTail__0_3_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declTail__0_3_0")) return false; if (!recursion_guard_(builder_, level_, "declTail__0_3_0")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_);
result_ = declTail__0_3_0_0(builder_, level_ + 1); result_ = consumeToken(builder_, COMMA);
result_ = result_ && initializer(builder_, level_ + 1); result_ = result_ && assignTargets_(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// [('=' | ':') initializerList_]
private static boolean declTail__0_4(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declTail__0_4")) return false;
declTail__0_4_0(builder_, level_ + 1);
return true;
}
// ('=' | ':') initializerList_
private static boolean declTail__0_4_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declTail__0_4_0")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = declTail__0_4_0_0(builder_, level_ + 1);
result_ = result_ && initializerList_(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
// '=' | ':' // '=' | ':'
private static boolean declTail__0_3_0_0(PsiBuilder builder_, int level_) { private static boolean declTail__0_4_0_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declTail__0_3_0_0")) return false; if (!recursion_guard_(builder_, level_, "declTail__0_4_0_0")) return false;
boolean result_; boolean result_;
result_ = consumeToken(builder_, EQ); result_ = consumeToken(builder_, EQ);
if (!result_) result_ = consumeToken(builder_, COLON); if (!result_) result_ = consumeToken(builder_, COLON);
return result_; return result_;
} }
// ':=' initializer // ':=' initializerList_
private static boolean declTail__1(PsiBuilder builder_, int level_) { private static boolean declTail__1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declTail__1")) return false; if (!recursion_guard_(builder_, level_, "declTail__1")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_);
result_ = consumeToken(builder_, COLON_EQ); result_ = consumeToken(builder_, COLON_EQ);
result_ = result_ && initializer(builder_, level_ + 1); result_ = result_ && initializerList_(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
// '::' initializer // '::' initializerList_
private static boolean declTail__2(PsiBuilder builder_, int level_) { private static boolean declTail__2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declTail__2")) return false; if (!recursion_guard_(builder_, level_, "declTail__2")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_);
result_ = consumeToken(builder_, COLON_COLON); result_ = consumeToken(builder_, COLON_COLON);
result_ = result_ && initializer(builder_, level_ + 1); result_ = result_ && initializerList_(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
@@ -534,6 +588,9 @@ public class JaiParser implements PsiParser, LightPsiParser {
/* ********************************************************** */ /* ********************************************************** */
// <<dir "#asm">> directiveFlag_* <<opaqueBlock>> // <<dir "#asm">> directiveFlag_* <<opaqueBlock>>
// | <<dir "#foreign">> directiveFlag_* [<<exprNoAssign>>] [STRING]
// | <<dir "#elsewhere">> directiveFlag_* [<<exprNoAssign>>] [STRING]
// | <<dir "#insert">> directiveFlag_* ['(' [argList] ')'] [block | expr]
// | <<dir "#assert">> expr [expr] // | <<dir "#assert">> expr [expr]
// | <<dir "#module_parameters">> '(' [paramList] ')' ['(' [paramList] ')'] [block] // | <<dir "#module_parameters">> '(' [paramList] ')' ['(' [paramList] ')'] [block]
// | <<dirWithBlock>> directiveFlag_* block // | <<dirWithBlock>> directiveFlag_* block
@@ -549,6 +606,9 @@ public class JaiParser implements PsiParser, LightPsiParser {
if (!result_) result_ = directiveExpr_3(builder_, level_ + 1); if (!result_) result_ = directiveExpr_3(builder_, level_ + 1);
if (!result_) result_ = directiveExpr_4(builder_, level_ + 1); if (!result_) result_ = directiveExpr_4(builder_, level_ + 1);
if (!result_) result_ = directiveExpr_5(builder_, level_ + 1); if (!result_) result_ = directiveExpr_5(builder_, level_ + 1);
if (!result_) result_ = directiveExpr_6(builder_, level_ + 1);
if (!result_) result_ = directiveExpr_7(builder_, level_ + 1);
if (!result_) result_ = directiveExpr_8(builder_, level_ + 1);
exit_section_(builder_, level_, marker_, result_, false, null); exit_section_(builder_, level_, marker_, result_, false, null);
return result_; return result_;
} }
@@ -576,88 +636,91 @@ public class JaiParser implements PsiParser, LightPsiParser {
return true; return true;
} }
// <<dir "#assert">> expr [expr] // <<dir "#foreign">> directiveFlag_* [<<exprNoAssign>>] [STRING]
private static boolean directiveExpr_1(PsiBuilder builder_, int level_) { private static boolean directiveExpr_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_1")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_1")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_);
result_ = dir(builder_, level_ + 1, "#assert"); result_ = dir(builder_, level_ + 1, "#foreign");
result_ = result_ && expr(builder_, level_ + 1, -1); result_ = result_ && directiveExpr_1_1(builder_, level_ + 1);
result_ = result_ && directiveExpr_1_2(builder_, level_ + 1); result_ = result_ && directiveExpr_1_2(builder_, level_ + 1);
result_ = result_ && directiveExpr_1_3(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
// [expr] // directiveFlag_*
private static boolean directiveExpr_1_2(PsiBuilder builder_, int level_) { private static boolean directiveExpr_1_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_1_2")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_1_1")) return false;
expr(builder_, level_ + 1, -1); while (true) {
int pos_ = current_position_(builder_);
if (!directiveFlag_(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "directiveExpr_1_1", pos_)) break;
}
return true; return true;
} }
// <<dir "#module_parameters">> '(' [paramList] ')' ['(' [paramList] ')'] [block] // [<<exprNoAssign>>]
private static boolean directiveExpr_1_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_1_2")) return false;
exprNoAssign(builder_, level_ + 1);
return true;
}
// [STRING]
private static boolean directiveExpr_1_3(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_1_3")) return false;
consumeToken(builder_, STRING);
return true;
}
// <<dir "#elsewhere">> directiveFlag_* [<<exprNoAssign>>] [STRING]
private static boolean directiveExpr_2(PsiBuilder builder_, int level_) { private static boolean directiveExpr_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_2")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_2")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_);
result_ = dir(builder_, level_ + 1, "#module_parameters"); result_ = dir(builder_, level_ + 1, "#elsewhere");
result_ = result_ && consumeToken(builder_, LPAREN); result_ = result_ && directiveExpr_2_1(builder_, level_ + 1);
result_ = result_ && directiveExpr_2_2(builder_, level_ + 1); result_ = result_ && directiveExpr_2_2(builder_, level_ + 1);
result_ = result_ && consumeToken(builder_, RPAREN); result_ = result_ && directiveExpr_2_3(builder_, level_ + 1);
result_ = result_ && directiveExpr_2_4(builder_, level_ + 1);
result_ = result_ && directiveExpr_2_5(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
// [paramList] // directiveFlag_*
private static boolean directiveExpr_2_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_2_1")) return false;
while (true) {
int pos_ = current_position_(builder_);
if (!directiveFlag_(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "directiveExpr_2_1", pos_)) break;
}
return true;
}
// [<<exprNoAssign>>]
private static boolean directiveExpr_2_2(PsiBuilder builder_, int level_) { private static boolean directiveExpr_2_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_2_2")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_2_2")) return false;
paramList(builder_, level_ + 1); exprNoAssign(builder_, level_ + 1);
return true; return true;
} }
// ['(' [paramList] ')'] // [STRING]
private static boolean directiveExpr_2_4(PsiBuilder builder_, int level_) { private static boolean directiveExpr_2_3(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_2_4")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_2_3")) return false;
directiveExpr_2_4_0(builder_, level_ + 1); consumeToken(builder_, STRING);
return true; return true;
} }
// '(' [paramList] ')' // <<dir "#insert">> directiveFlag_* ['(' [argList] ')'] [block | expr]
private static boolean directiveExpr_2_4_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_2_4_0")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = consumeToken(builder_, LPAREN);
result_ = result_ && directiveExpr_2_4_0_1(builder_, level_ + 1);
result_ = result_ && consumeToken(builder_, RPAREN);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// [paramList]
private static boolean directiveExpr_2_4_0_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_2_4_0_1")) return false;
paramList(builder_, level_ + 1);
return true;
}
// [block]
private static boolean directiveExpr_2_5(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_2_5")) return false;
block(builder_, level_ + 1);
return true;
}
// <<dirWithBlock>> directiveFlag_* block
private static boolean directiveExpr_3(PsiBuilder builder_, int level_) { private static boolean directiveExpr_3(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_3")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_3")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_);
result_ = dirWithBlock(builder_, level_ + 1); result_ = dir(builder_, level_ + 1, "#insert");
result_ = result_ && directiveExpr_3_1(builder_, level_ + 1); result_ = result_ && directiveExpr_3_1(builder_, level_ + 1);
result_ = result_ && block(builder_, level_ + 1); result_ = result_ && directiveExpr_3_2(builder_, level_ + 1);
result_ = result_ && directiveExpr_3_3(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
@@ -673,29 +736,60 @@ public class JaiParser implements PsiParser, LightPsiParser {
return true; return true;
} }
// <<dirWithOperand>> directiveFlag_* [expr] // ['(' [argList] ')']
private static boolean directiveExpr_4(PsiBuilder builder_, int level_) { private static boolean directiveExpr_3_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_4")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_3_2")) return false;
directiveExpr_3_2_0(builder_, level_ + 1);
return true;
}
// '(' [argList] ')'
private static boolean directiveExpr_3_2_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_3_2_0")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_);
result_ = dirWithOperand(builder_, level_ + 1); result_ = consumeToken(builder_, LPAREN);
result_ = result_ && directiveExpr_4_1(builder_, level_ + 1); result_ = result_ && directiveExpr_3_2_0_1(builder_, level_ + 1);
result_ = result_ && directiveExpr_4_2(builder_, level_ + 1); result_ = result_ && consumeToken(builder_, RPAREN);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
// directiveFlag_* // [argList]
private static boolean directiveExpr_4_1(PsiBuilder builder_, int level_) { private static boolean directiveExpr_3_2_0_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_4_1")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_3_2_0_1")) return false;
while (true) { argList(builder_, level_ + 1);
int pos_ = current_position_(builder_);
if (!directiveFlag_(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "directiveExpr_4_1", pos_)) break;
}
return true; return true;
} }
// [block | expr]
private static boolean directiveExpr_3_3(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_3_3")) return false;
directiveExpr_3_3_0(builder_, level_ + 1);
return true;
}
// block | expr
private static boolean directiveExpr_3_3_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_3_3_0")) return false;
boolean result_;
result_ = block(builder_, level_ + 1);
if (!result_) result_ = expr(builder_, level_ + 1, -1);
return result_;
}
// <<dir "#assert">> expr [expr]
private static boolean directiveExpr_4(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_4")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = dir(builder_, level_ + 1, "#assert");
result_ = result_ && expr(builder_, level_ + 1, -1);
result_ = result_ && directiveExpr_4_2(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// [expr] // [expr]
private static boolean directiveExpr_4_2(PsiBuilder builder_, int level_) { private static boolean directiveExpr_4_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_4_2")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_4_2")) return false;
@@ -703,38 +797,140 @@ public class JaiParser implements PsiParser, LightPsiParser {
return true; return true;
} }
// <<dirPlain>> directiveFlag_* // <<dir "#module_parameters">> '(' [paramList] ')' ['(' [paramList] ')'] [block]
private static boolean directiveExpr_5(PsiBuilder builder_, int level_) { private static boolean directiveExpr_5(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_5")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_5")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_);
result_ = dirPlain(builder_, level_ + 1); result_ = dir(builder_, level_ + 1, "#module_parameters");
result_ = result_ && directiveExpr_5_1(builder_, level_ + 1); result_ = result_ && consumeToken(builder_, LPAREN);
result_ = result_ && directiveExpr_5_2(builder_, level_ + 1);
result_ = result_ && consumeToken(builder_, RPAREN);
result_ = result_ && directiveExpr_5_4(builder_, level_ + 1);
result_ = result_ && directiveExpr_5_5(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// [paramList]
private static boolean directiveExpr_5_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_5_2")) return false;
paramList(builder_, level_ + 1);
return true;
}
// ['(' [paramList] ')']
private static boolean directiveExpr_5_4(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_5_4")) return false;
directiveExpr_5_4_0(builder_, level_ + 1);
return true;
}
// '(' [paramList] ')'
private static boolean directiveExpr_5_4_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_5_4_0")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = consumeToken(builder_, LPAREN);
result_ = result_ && directiveExpr_5_4_0_1(builder_, level_ + 1);
result_ = result_ && consumeToken(builder_, RPAREN);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// [paramList]
private static boolean directiveExpr_5_4_0_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_5_4_0_1")) return false;
paramList(builder_, level_ + 1);
return true;
}
// [block]
private static boolean directiveExpr_5_5(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_5_5")) return false;
block(builder_, level_ + 1);
return true;
}
// <<dirWithBlock>> directiveFlag_* block
private static boolean directiveExpr_6(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_6")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = dirWithBlock(builder_, level_ + 1);
result_ = result_ && directiveExpr_6_1(builder_, level_ + 1);
result_ = result_ && block(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
// directiveFlag_* // directiveFlag_*
private static boolean directiveExpr_5_1(PsiBuilder builder_, int level_) { private static boolean directiveExpr_6_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_5_1")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_6_1")) return false;
while (true) { while (true) {
int pos_ = current_position_(builder_); int pos_ = current_position_(builder_);
if (!directiveFlag_(builder_, level_ + 1)) break; if (!directiveFlag_(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "directiveExpr_5_1", pos_)) break; if (!empty_element_parsed_guard_(builder_, "directiveExpr_6_1", pos_)) break;
}
return true;
}
// <<dirWithOperand>> directiveFlag_* [expr]
private static boolean directiveExpr_7(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_7")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = dirWithOperand(builder_, level_ + 1);
result_ = result_ && directiveExpr_7_1(builder_, level_ + 1);
result_ = result_ && directiveExpr_7_2(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// directiveFlag_*
private static boolean directiveExpr_7_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_7_1")) return false;
while (true) {
int pos_ = current_position_(builder_);
if (!directiveFlag_(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "directiveExpr_7_1", pos_)) break;
}
return true;
}
// [expr]
private static boolean directiveExpr_7_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_7_2")) return false;
expr(builder_, level_ + 1, -1);
return true;
}
// <<dirPlain>> directiveFlag_*
private static boolean directiveExpr_8(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_8")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = dirPlain(builder_, level_ + 1);
result_ = result_ && directiveExpr_8_1(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// directiveFlag_*
private static boolean directiveExpr_8_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_8_1")) return false;
while (true) {
int pos_ = current_position_(builder_);
if (!directiveFlag_(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "directiveExpr_8_1", pos_)) break;
} }
return true; return true;
} }
/* ********************************************************** */ /* ********************************************************** */
// ',' IDENT // <<directiveFlag>>
static boolean directiveFlag_(PsiBuilder builder_, int level_) { static boolean directiveFlag_(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveFlag_")) return false; return directiveFlag(builder_, level_ + 1);
if (!nextTokenIs(builder_, COMMA)) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = consumeTokens(builder_, 0, COMMA, IDENT);
exit_section_(builder_, marker_, null, result_);
return result_;
} }
/* ********************************************************** */ /* ********************************************************** */
@@ -1059,6 +1255,28 @@ public class JaiParser implements PsiParser, LightPsiParser {
return true; return true;
} }
/* ********************************************************** */
// block | expr
static boolean ifxBranch_(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "ifxBranch_")) return false;
boolean result_;
result_ = block(builder_, level_ + 1);
if (!result_) result_ = expr(builder_, level_ + 1, -1);
return result_;
}
/* ********************************************************** */
// 'ifx' | <<dir "#ifx">>
static boolean ifxKeyword_(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "ifxKeyword_")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = consumeToken(builder_, KW_IFX);
if (!result_) result_ = dir(builder_, level_ + 1, "#ifx");
exit_section_(builder_, marker_, null, result_);
return result_;
}
/* ********************************************************** */ /* ********************************************************** */
// '---' | expr // '---' | expr
public static boolean initializer(PsiBuilder builder_, int level_) { public static boolean initializer(PsiBuilder builder_, int level_) {
@@ -1071,6 +1289,40 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
/* ********************************************************** */
// initializer (',' initializer)*
static boolean initializerList_(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "initializerList_")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = initializer(builder_, level_ + 1);
result_ = result_ && initializerList__1(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// (',' initializer)*
private static boolean initializerList__1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "initializerList__1")) return false;
while (true) {
int pos_ = current_position_(builder_);
if (!initializerList__1_0(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "initializerList__1", pos_)) break;
}
return true;
}
// ',' initializer
private static boolean initializerList__1_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "initializerList__1_0")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = consumeToken(builder_, COMMA);
result_ = result_ && initializer(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
/* ********************************************************** */ /* ********************************************************** */
// 'interface' [expr] // 'interface' [expr]
public static boolean interfaceExpr(PsiBuilder builder_, int level_) { public static boolean interfaceExpr(PsiBuilder builder_, int level_) {
@@ -1168,6 +1420,29 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
/* ********************************************************** */
// <<isNamedArgumentAhead>> memberName '=' (block | expr)
public static boolean namedArgument(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "namedArgument")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_, level_, _NONE_, NAMED_ARGUMENT, "<named argument>");
result_ = isNamedArgumentAhead(builder_, level_ + 1);
result_ = result_ && memberName(builder_, level_ + 1);
result_ = result_ && consumeToken(builder_, EQ);
result_ = result_ && namedArgument_3(builder_, level_ + 1);
exit_section_(builder_, level_, marker_, result_, false, null);
return result_;
}
// block | expr
private static boolean namedArgument_3(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "namedArgument_3")) return false;
boolean result_;
result_ = block(builder_, level_ + 1);
if (!result_) result_ = expr(builder_, level_ + 1, -1);
return result_;
}
/* ********************************************************** */ /* ********************************************************** */
// NOTE+ // NOTE+
public static boolean noteStatement(PsiBuilder builder_, int level_) { public static boolean noteStatement(PsiBuilder builder_, int level_) {
@@ -1204,7 +1479,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
/* ********************************************************** */ /* ********************************************************** */
// '+' | '-' | '*' | '/' | '%' | '==' | '!=' | '<' | '>' | '<=' | '>=' // '+' | '-' | '*' | '/' | '%' | '==' | '!=' | '<' | '>' | '<=' | '>='
// | '&' | '|' | '^' | '~' | '<<' | '>>' | '<<<' | '>>>' // | '&' | '|' | '^' | '~' | '<<' | '>>' | '<<<' | '>>>'
// | '[' ']' | '[' ']' '=' // | '[' ']' '=' | '[' ']'
public static boolean operatorSymbol(PsiBuilder builder_, int level_) { public static boolean operatorSymbol(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "operatorSymbol")) return false; if (!recursion_guard_(builder_, level_, "operatorSymbol")) return false;
boolean result_; boolean result_;
@@ -1228,8 +1503,8 @@ public class JaiParser implements PsiParser, LightPsiParser {
if (!result_) result_ = consumeToken(builder_, SHR); if (!result_) result_ = consumeToken(builder_, SHR);
if (!result_) result_ = consumeToken(builder_, ROL); if (!result_) result_ = consumeToken(builder_, ROL);
if (!result_) result_ = consumeToken(builder_, ROR); if (!result_) result_ = consumeToken(builder_, ROR);
if (!result_) result_ = parseTokens(builder_, 0, LBRACKET, RBRACKET);
if (!result_) result_ = parseTokens(builder_, 0, LBRACKET, RBRACKET, EQ); if (!result_) result_ = parseTokens(builder_, 0, LBRACKET, RBRACKET, EQ);
if (!result_) result_ = parseTokens(builder_, 0, LBRACKET, RBRACKET);
exit_section_(builder_, level_, marker_, result_, false, null); exit_section_(builder_, level_, marker_, result_, false, null);
return result_; return result_;
} }
@@ -1648,97 +1923,18 @@ public class JaiParser implements PsiParser, LightPsiParser {
} }
/* ********************************************************** */ /* ********************************************************** */
// <<dirWithBlock>> directiveFlag_* block // directiveExpr
// | <<dirWithOperand>> directiveFlag_* [expr]
// | <<dirPlain>> directiveFlag_*
public static boolean procModifier(PsiBuilder builder_, int level_) { public static boolean procModifier(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "procModifier")) return false; if (!recursion_guard_(builder_, level_, "procModifier")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_, level_, _NONE_, PROC_MODIFIER, "<proc modifier>"); Marker marker_ = enter_section_(builder_, level_, _NONE_, PROC_MODIFIER, "<proc modifier>");
result_ = procModifier_0(builder_, level_ + 1); result_ = directiveExpr(builder_, level_ + 1);
if (!result_) result_ = procModifier_1(builder_, level_ + 1);
if (!result_) result_ = procModifier_2(builder_, level_ + 1);
exit_section_(builder_, level_, marker_, result_, false, null); exit_section_(builder_, level_, marker_, result_, false, null);
return result_; return result_;
} }
// <<dirWithBlock>> directiveFlag_* block
private static boolean procModifier_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "procModifier_0")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = dirWithBlock(builder_, level_ + 1);
result_ = result_ && procModifier_0_1(builder_, level_ + 1);
result_ = result_ && block(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// directiveFlag_*
private static boolean procModifier_0_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "procModifier_0_1")) return false;
while (true) {
int pos_ = current_position_(builder_);
if (!directiveFlag_(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "procModifier_0_1", pos_)) break;
}
return true;
}
// <<dirWithOperand>> directiveFlag_* [expr]
private static boolean procModifier_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "procModifier_1")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = dirWithOperand(builder_, level_ + 1);
result_ = result_ && procModifier_1_1(builder_, level_ + 1);
result_ = result_ && procModifier_1_2(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// directiveFlag_*
private static boolean procModifier_1_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "procModifier_1_1")) return false;
while (true) {
int pos_ = current_position_(builder_);
if (!directiveFlag_(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "procModifier_1_1", pos_)) break;
}
return true;
}
// [expr]
private static boolean procModifier_1_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "procModifier_1_2")) return false;
expr(builder_, level_ + 1, -1);
return true;
}
// <<dirPlain>> directiveFlag_*
private static boolean procModifier_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "procModifier_2")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = dirPlain(builder_, level_ + 1);
result_ = result_ && procModifier_2_1(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// directiveFlag_*
private static boolean procModifier_2_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "procModifier_2_1")) return false;
while (true) {
int pos_ = current_position_(builder_);
if (!directiveFlag_(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "procModifier_2_1", pos_)) break;
}
return true;
}
/* ********************************************************** */ /* ********************************************************** */
// ['`'] 'push_context' expr block // ['`'] 'push_context' [expr] block
public static boolean pushContextStatement(PsiBuilder builder_, int level_) { public static boolean pushContextStatement(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "pushContextStatement")) return false; if (!recursion_guard_(builder_, level_, "pushContextStatement")) return false;
if (!nextTokenIs(builder_, "<push context statement>", BACKTICK, KW_PUSH_CONTEXT)) return false; if (!nextTokenIs(builder_, "<push context statement>", BACKTICK, KW_PUSH_CONTEXT)) return false;
@@ -1746,7 +1942,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
Marker marker_ = enter_section_(builder_, level_, _NONE_, PUSH_CONTEXT_STATEMENT, "<push context statement>"); Marker marker_ = enter_section_(builder_, level_, _NONE_, PUSH_CONTEXT_STATEMENT, "<push context statement>");
result_ = pushContextStatement_0(builder_, level_ + 1); result_ = pushContextStatement_0(builder_, level_ + 1);
result_ = result_ && consumeToken(builder_, KW_PUSH_CONTEXT); result_ = result_ && consumeToken(builder_, KW_PUSH_CONTEXT);
result_ = result_ && expr(builder_, level_ + 1, -1); result_ = result_ && pushContextStatement_2(builder_, level_ + 1);
result_ = result_ && block(builder_, level_ + 1); result_ = result_ && block(builder_, level_ + 1);
exit_section_(builder_, level_, marker_, result_, false, null); exit_section_(builder_, level_, marker_, result_, false, null);
return result_; return result_;
@@ -1759,6 +1955,13 @@ public class JaiParser implements PsiParser, LightPsiParser {
return true; return true;
} }
// [expr]
private static boolean pushContextStatement_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "pushContextStatement_2")) return false;
expr(builder_, level_ + 1, -1);
return true;
}
/* ********************************************************** */ /* ********************************************************** */
// IDENT // IDENT
public static boolean refExpr(PsiBuilder builder_, int level_) { public static boolean refExpr(PsiBuilder builder_, int level_) {
@@ -2228,7 +2431,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
} }
/* ********************************************************** */ /* ********************************************************** */
// 'union' structModifier_* block // 'union' ['(' [paramList] ')'] structModifier_* block
public static boolean unionExpr(PsiBuilder builder_, int level_) { public static boolean unionExpr(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "unionExpr")) return false; if (!recursion_guard_(builder_, level_, "unionExpr")) return false;
if (!nextTokenIs(builder_, KW_UNION)) return false; if (!nextTokenIs(builder_, KW_UNION)) return false;
@@ -2236,22 +2439,106 @@ public class JaiParser implements PsiParser, LightPsiParser {
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_);
result_ = consumeToken(builder_, KW_UNION); result_ = consumeToken(builder_, KW_UNION);
result_ = result_ && unionExpr_1(builder_, level_ + 1); result_ = result_ && unionExpr_1(builder_, level_ + 1);
result_ = result_ && unionExpr_2(builder_, level_ + 1);
result_ = result_ && block(builder_, level_ + 1); result_ = result_ && block(builder_, level_ + 1);
exit_section_(builder_, marker_, UNION_EXPR, result_); exit_section_(builder_, marker_, UNION_EXPR, result_);
return result_; return result_;
} }
// structModifier_* // ['(' [paramList] ')']
private static boolean unionExpr_1(PsiBuilder builder_, int level_) { private static boolean unionExpr_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "unionExpr_1")) return false; if (!recursion_guard_(builder_, level_, "unionExpr_1")) return false;
unionExpr_1_0(builder_, level_ + 1);
return true;
}
// '(' [paramList] ')'
private static boolean unionExpr_1_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "unionExpr_1_0")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = consumeToken(builder_, LPAREN);
result_ = result_ && unionExpr_1_0_1(builder_, level_ + 1);
result_ = result_ && consumeToken(builder_, RPAREN);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// [paramList]
private static boolean unionExpr_1_0_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "unionExpr_1_0_1")) return false;
paramList(builder_, level_ + 1);
return true;
}
// structModifier_*
private static boolean unionExpr_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "unionExpr_2")) return false;
while (true) { while (true) {
int pos_ = current_position_(builder_); int pos_ = current_position_(builder_);
if (!structModifier_(builder_, level_ + 1)) break; if (!structModifier_(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "unionExpr_1", pos_)) break; if (!empty_element_parsed_guard_(builder_, "unionExpr_2", pos_)) break;
} }
return true; return true;
} }
/* ********************************************************** */
// 'using' [directiveFlag_ ['(' [argList] ')']]
static boolean usingModifier_(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "usingModifier_")) return false;
if (!nextTokenIs(builder_, KW_USING)) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = consumeToken(builder_, KW_USING);
result_ = result_ && usingModifier__1(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// [directiveFlag_ ['(' [argList] ')']]
private static boolean usingModifier__1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "usingModifier__1")) return false;
usingModifier__1_0(builder_, level_ + 1);
return true;
}
// directiveFlag_ ['(' [argList] ')']
private static boolean usingModifier__1_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "usingModifier__1_0")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = directiveFlag_(builder_, level_ + 1);
result_ = result_ && usingModifier__1_0_1(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// ['(' [argList] ')']
private static boolean usingModifier__1_0_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "usingModifier__1_0_1")) return false;
usingModifier__1_0_1_0(builder_, level_ + 1);
return true;
}
// '(' [argList] ')'
private static boolean usingModifier__1_0_1_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "usingModifier__1_0_1_0")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = consumeToken(builder_, LPAREN);
result_ = result_ && usingModifier__1_0_1_0_1(builder_, level_ + 1);
result_ = result_ && consumeToken(builder_, RPAREN);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// [argList]
private static boolean usingModifier__1_0_1_0_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "usingModifier__1_0_1_0_1")) return false;
argList(builder_, level_ + 1);
return true;
}
/* ********************************************************** */ /* ********************************************************** */
// 'using' [',' expr] expr semi // 'using' [',' expr] expr semi
public static boolean usingStatement(PsiBuilder builder_, int level_) { public static boolean usingStatement(PsiBuilder builder_, int level_) {
@@ -2643,18 +2930,17 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
// 'ifx' expr ['then'] [expr] ['else' expr] // ifxKeyword_ expr ['then'] [ifxBranch_] ['else' ifxBranch_]
public static boolean ifxExpr(PsiBuilder builder_, int level_) { public static boolean ifxExpr(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "ifxExpr")) return false; if (!recursion_guard_(builder_, level_, "ifxExpr")) return false;
if (!nextTokenIsSmart(builder_, KW_IFX)) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, IFX_EXPR, "<ifx expr>");
result_ = consumeTokenSmart(builder_, KW_IFX); result_ = ifxKeyword_(builder_, level_ + 1);
result_ = result_ && expr(builder_, level_ + 1, -1); result_ = result_ && expr(builder_, level_ + 1, -1);
result_ = result_ && ifxExpr_2(builder_, level_ + 1); result_ = result_ && ifxExpr_2(builder_, level_ + 1);
result_ = result_ && ifxExpr_3(builder_, level_ + 1); result_ = result_ && ifxExpr_3(builder_, level_ + 1);
result_ = result_ && ifxExpr_4(builder_, level_ + 1); result_ = result_ && ifxExpr_4(builder_, level_ + 1);
exit_section_(builder_, marker_, IFX_EXPR, result_); exit_section_(builder_, level_, marker_, result_, false, null);
return result_; return result_;
} }
@@ -2665,27 +2951,27 @@ public class JaiParser implements PsiParser, LightPsiParser {
return true; return true;
} }
// [expr] // [ifxBranch_]
private static boolean ifxExpr_3(PsiBuilder builder_, int level_) { private static boolean ifxExpr_3(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "ifxExpr_3")) return false; if (!recursion_guard_(builder_, level_, "ifxExpr_3")) return false;
expr(builder_, level_ + 1, -1); ifxBranch_(builder_, level_ + 1);
return true; return true;
} }
// ['else' expr] // ['else' ifxBranch_]
private static boolean ifxExpr_4(PsiBuilder builder_, int level_) { private static boolean ifxExpr_4(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "ifxExpr_4")) return false; if (!recursion_guard_(builder_, level_, "ifxExpr_4")) return false;
ifxExpr_4_0(builder_, level_ + 1); ifxExpr_4_0(builder_, level_ + 1);
return true; return true;
} }
// 'else' expr // 'else' ifxBranch_
private static boolean ifxExpr_4_0(PsiBuilder builder_, int level_) { private static boolean ifxExpr_4_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "ifxExpr_4_0")) return false; if (!recursion_guard_(builder_, level_, "ifxExpr_4_0")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_);
result_ = consumeTokenSmart(builder_, KW_ELSE); result_ = consumeTokenSmart(builder_, KW_ELSE);
result_ = result_ && expr(builder_, level_ + 1, -1); result_ = result_ && ifxBranch_(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }

View File

@@ -10,4 +10,7 @@ public interface JaiArgument extends PsiElement {
@Nullable @Nullable
JaiExpr getExpr(); JaiExpr getExpr();
@Nullable
JaiNamedArgument getNamedArgument();
} }

View File

@@ -7,11 +7,14 @@ import com.intellij.psi.PsiElement;
public interface JaiDeclaration extends PsiElement { public interface JaiDeclaration extends PsiElement {
@NotNull
List<JaiArgument> getArgumentList();
@NotNull @NotNull
JaiDeclNames getDeclNames(); JaiDeclNames getDeclNames();
@Nullable @NotNull
JaiInitializer getInitializer(); List<JaiInitializer> getInitializerList();
@NotNull @NotNull
List<JaiProcModifier> getProcModifierList(); List<JaiProcModifier> getProcModifierList();

View File

@@ -7,11 +7,14 @@ import com.intellij.psi.PsiElement;
public interface JaiDirectiveExpr extends JaiExpr { public interface JaiDirectiveExpr extends JaiExpr {
@NotNull
List<JaiArgument> getArgumentList();
@Nullable @Nullable
JaiBlock getBlock(); JaiBlock getBlock();
@NotNull @Nullable
List<JaiExpr> getExprList(); JaiExpr getExpr();
@NotNull @NotNull
List<JaiParameter> getParameterList(); List<JaiParameter> getParameterList();

View File

@@ -7,6 +7,9 @@ import com.intellij.psi.PsiElement;
public interface JaiIfxExpr extends JaiExpr { public interface JaiIfxExpr extends JaiExpr {
@NotNull
List<JaiBlock> getBlockList();
@NotNull @NotNull
List<JaiExpr> getExprList(); List<JaiExpr> getExprList();

View File

@@ -0,0 +1,19 @@
// This is a generated file. Not intended for manual editing.
package dev.hgh.jai.psi;
import java.util.List;
import org.jetbrains.annotations.*;
import com.intellij.psi.PsiElement;
public interface JaiNamedArgument extends PsiElement {
@Nullable
JaiBlock getBlock();
@Nullable
JaiExpr getExpr();
@NotNull
JaiMemberName getMemberName();
}

View File

@@ -7,10 +7,7 @@ import com.intellij.psi.PsiElement;
public interface JaiProcModifier extends PsiElement { public interface JaiProcModifier extends PsiElement {
@Nullable @NotNull
JaiBlock getBlock(); JaiDirectiveExpr getDirectiveExpr();
@Nullable
JaiExpr getExpr();
} }

View File

@@ -10,7 +10,7 @@ public interface JaiPushContextStatement extends PsiElement {
@NotNull @NotNull
JaiBlock getBlock(); JaiBlock getBlock();
@NotNull @Nullable
JaiExpr getExpr(); JaiExpr getExpr();
} }

View File

@@ -53,6 +53,7 @@ public interface JaiTypes {
IElementType MEMBER_EXPR = new JaiElementType("MEMBER_EXPR"); IElementType MEMBER_EXPR = new JaiElementType("MEMBER_EXPR");
IElementType MEMBER_NAME = new JaiElementType("MEMBER_NAME"); IElementType MEMBER_NAME = new JaiElementType("MEMBER_NAME");
IElementType MUL_EXPR = new JaiElementType("MUL_EXPR"); IElementType MUL_EXPR = new JaiElementType("MUL_EXPR");
IElementType NAMED_ARGUMENT = new JaiElementType("NAMED_ARGUMENT");
IElementType NOTE_STATEMENT = new JaiElementType("NOTE_STATEMENT"); IElementType NOTE_STATEMENT = new JaiElementType("NOTE_STATEMENT");
IElementType OPERATOR_DECLARATION = new JaiElementType("OPERATOR_DECLARATION"); IElementType OPERATOR_DECLARATION = new JaiElementType("OPERATOR_DECLARATION");
IElementType OPERATOR_SYMBOL = new JaiElementType("OPERATOR_SYMBOL"); IElementType OPERATOR_SYMBOL = new JaiElementType("OPERATOR_SYMBOL");
@@ -327,6 +328,9 @@ public interface JaiTypes {
else if (type == MUL_EXPR) { else if (type == MUL_EXPR) {
return new JaiMulExprImpl(node); return new JaiMulExprImpl(node);
} }
else if (type == NAMED_ARGUMENT) {
return new JaiNamedArgumentImpl(node);
}
else if (type == NOTE_STATEMENT) { else if (type == NOTE_STATEMENT) {
return new JaiNoteStatementImpl(node); return new JaiNoteStatementImpl(node);
} }

View File

@@ -10,6 +10,9 @@ public interface JaiUnionExpr extends JaiExpr {
@NotNull @NotNull
JaiBlock getBlock(); JaiBlock getBlock();
@NotNull
List<JaiParameter> getParameterList();
@NotNull @NotNull
List<JaiProcModifier> getProcModifierList(); List<JaiProcModifier> getProcModifierList();

View File

@@ -183,6 +183,10 @@ public class JaiVisitor extends PsiElementVisitor {
visitExpr(o); visitExpr(o);
} }
public void visitNamedArgument(@NotNull JaiNamedArgument o) {
visitPsiElement(o);
}
public void visitNoteStatement(@NotNull JaiNoteStatement o) { public void visitNoteStatement(@NotNull JaiNoteStatement o) {
visitPsiElement(o); visitPsiElement(o);
} }

View File

@@ -33,4 +33,10 @@ public class JaiArgumentImpl extends ASTWrapperPsiElement implements JaiArgument
return findChildByClass(JaiExpr.class); return findChildByClass(JaiExpr.class);
} }
@Override
@Nullable
public JaiNamedArgument getNamedArgument() {
return findChildByClass(JaiNamedArgument.class);
}
} }

View File

@@ -27,6 +27,12 @@ public class JaiDeclarationImpl extends ASTWrapperPsiElement implements JaiDecla
else super.accept(visitor); else super.accept(visitor);
} }
@Override
@NotNull
public List<JaiArgument> getArgumentList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiArgument.class);
}
@Override @Override
@NotNull @NotNull
public JaiDeclNames getDeclNames() { public JaiDeclNames getDeclNames() {
@@ -34,9 +40,9 @@ public class JaiDeclarationImpl extends ASTWrapperPsiElement implements JaiDecla
} }
@Override @Override
@Nullable @NotNull
public JaiInitializer getInitializer() { public List<JaiInitializer> getInitializerList() {
return findChildByClass(JaiInitializer.class); return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiInitializer.class);
} }
@Override @Override

View File

@@ -27,6 +27,12 @@ public class JaiDirectiveExprImpl extends JaiExprImpl implements JaiDirectiveExp
else super.accept(visitor); else super.accept(visitor);
} }
@Override
@NotNull
public List<JaiArgument> getArgumentList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiArgument.class);
}
@Override @Override
@Nullable @Nullable
public JaiBlock getBlock() { public JaiBlock getBlock() {
@@ -34,9 +40,9 @@ public class JaiDirectiveExprImpl extends JaiExprImpl implements JaiDirectiveExp
} }
@Override @Override
@NotNull @Nullable
public List<JaiExpr> getExprList() { public JaiExpr getExpr() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiExpr.class); return findChildByClass(JaiExpr.class);
} }
@Override @Override

View File

@@ -27,6 +27,12 @@ public class JaiIfxExprImpl extends JaiExprImpl implements JaiIfxExpr {
else super.accept(visitor); else super.accept(visitor);
} }
@Override
@NotNull
public List<JaiBlock> getBlockList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiBlock.class);
}
@Override @Override
@NotNull @NotNull
public List<JaiExpr> getExprList() { public List<JaiExpr> getExprList() {

View File

@@ -0,0 +1,48 @@
// This is a generated file. Not intended for manual editing.
package dev.hgh.jai.psi.impl;
import java.util.List;
import org.jetbrains.annotations.*;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import static dev.hgh.jai.psi.JaiTypes.*;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import dev.hgh.jai.psi.*;
public class JaiNamedArgumentImpl extends ASTWrapperPsiElement implements JaiNamedArgument {
public JaiNamedArgumentImpl(@NotNull ASTNode node) {
super(node);
}
public void accept(@NotNull JaiVisitor visitor) {
visitor.visitNamedArgument(this);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JaiVisitor) accept((JaiVisitor)visitor);
else super.accept(visitor);
}
@Override
@Nullable
public JaiBlock getBlock() {
return findChildByClass(JaiBlock.class);
}
@Override
@Nullable
public JaiExpr getExpr() {
return findChildByClass(JaiExpr.class);
}
@Override
@NotNull
public JaiMemberName getMemberName() {
return findNotNullChildByClass(JaiMemberName.class);
}
}

View File

@@ -28,15 +28,9 @@ public class JaiProcModifierImpl extends ASTWrapperPsiElement implements JaiProc
} }
@Override @Override
@Nullable @NotNull
public JaiBlock getBlock() { public JaiDirectiveExpr getDirectiveExpr() {
return findChildByClass(JaiBlock.class); return findNotNullChildByClass(JaiDirectiveExpr.class);
}
@Override
@Nullable
public JaiExpr getExpr() {
return findChildByClass(JaiExpr.class);
} }
} }

View File

@@ -34,9 +34,9 @@ public class JaiPushContextStatementImpl extends ASTWrapperPsiElement implements
} }
@Override @Override
@NotNull @Nullable
public JaiExpr getExpr() { public JaiExpr getExpr() {
return findNotNullChildByClass(JaiExpr.class); return findChildByClass(JaiExpr.class);
} }
} }

View File

@@ -33,6 +33,12 @@ public class JaiUnionExprImpl extends JaiExprImpl implements JaiUnionExpr {
return findNotNullChildByClass(JaiBlock.class); return findNotNullChildByClass(JaiBlock.class);
} }
@Override
@NotNull
public List<JaiParameter> getParameterList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiParameter.class);
}
@Override @Override
@NotNull @NotNull
public List<JaiProcModifier> getProcModifierList() { public List<JaiProcModifier> getProcModifierList() {

View File

@@ -203,7 +203,7 @@ breakStatement ::= 'break' [IDENT] semi
continueStatement ::= 'continue' [IDENT] semi continueStatement ::= 'continue' [IDENT] semi
removeStatement ::= 'remove' [expr] semi removeStatement ::= 'remove' [expr] semi
deferStatement ::= ['`'] 'defer' statement deferStatement ::= ['`'] 'defer' statement
pushContextStatement ::= ['`'] 'push_context' expr block pushContextStatement ::= ['`'] 'push_context' [expr] block
usingStatement ::= 'using' [',' expr] expr semi usingStatement ::= 'using' [',' expr] expr semi
expressionStatement ::= expr (',' expr)* semiWithNotes_ expressionStatement ::= expr (',' expr)* semiWithNotes_
@@ -214,20 +214,27 @@ expressionStatement ::= expr (',' expr)* semiWithNotes_
// and `main :: () {}` are all the same shape. The guard is what separates them from // and `main :: () {}` are all the same shape. The guard is what separates them from
// an expression statement such as `foo();`. // an expression statement such as `foo();`.
declaration ::= <<isDeclarationAhead>> declModifier_* declNames declTail_ semiWithNotes_ declaration ::= <<isDeclarationAhead>> declModifier_* declNames declTail_ semiWithNotes_
// `#as using base: Document;`, `#overlay (unknown.vtable) using vtable: *Vtable;` // `#as using base: Document;`, `#overlay (unknown.vtable) using vtable: *Vtable;`,
private declModifier_ ::= procModifier | 'using' // `#as using,except(vtable) iunknown: IUnknown;`
private declModifier_ ::= procModifier | usingModifier_
private usingModifier_ ::= 'using' [directiveFlag_ ['(' [argList] ')']]
declNames ::= declName (',' declName)* declNames ::= declName (',' declName)*
declName ::= ['`'] IDENT declName ::= ['`'] IDENT
private declTail_ ::= ':' [<<exprNoAssign>>] procModifier* [('=' | ':') initializer] private declTail_ ::= ':' [<<exprNoAssign>>] procModifier* [',' assignTargets_] [('=' | ':') initializerList_]
| ':=' initializer | ':=' initializerList_
| '::' initializer | '::' initializerList_
// `x, y := mouse_x, mouse_y;` — one initializer per name.
private initializerList_ ::= initializer (',' initializer)*
// `success:, apk.zip_dir = load_zip_directory(path);` declares the first name and
// assigns to the remaining lvalues.
private assignTargets_ ::= <<exprNoAssign>> (',' <<exprNoAssign>>)*
initializer ::= '---' | expr initializer ::= '---' | expr
// `operator + :: (a: T, b: T) -> T { }` // `operator + :: (a: T, b: T) -> T { }`
operatorDeclaration ::= 'operator' operatorSymbol '::' expr semiWithNotes_ operatorDeclaration ::= 'operator' operatorSymbol '::' expr semiWithNotes_
operatorSymbol ::= '+' | '-' | '*' | '/' | '%' | '==' | '!=' | '<' | '>' | '<=' | '>=' operatorSymbol ::= '+' | '-' | '*' | '/' | '%' | '==' | '!=' | '<' | '>' | '<=' | '>='
| '&' | '|' | '^' | '~' | '<<' | '>>' | '<<<' | '>>>' | '&' | '|' | '^' | '~' | '<<' | '>>' | '<<<' | '>>>'
| '[' ']' | '[' ']' '=' | '[' ']' '=' | '[' ']'
// -------------------------------------------------------------------- expressions // -------------------------------------------------------------------- expressions
@@ -293,7 +300,9 @@ derefCastExpr ::= '(' '.*' ')' expr
castExpr ::= 'cast' [',' IDENT] '(' [expr] ')' expr castExpr ::= 'cast' [',' IDENT] '(' [expr] ')' expr
autoCastExpr ::= 'xx' [',' IDENT] expr autoCastExpr ::= 'xx' [',' IDENT] expr
inlineExpr ::= ('inline' | 'no_inline') expr inlineExpr ::= ('inline' | 'no_inline') expr
ifxExpr ::= 'ifx' expr ['then'] [expr] ['else' expr] ifxExpr ::= ifxKeyword_ expr ['then'] [ifxBranch_] ['else' ifxBranch_]
private ifxKeyword_ ::= 'ifx' | <<dir "#ifx">>
private ifxBranch_ ::= block | expr
callExpr ::= expr '(' [argList] ')' callExpr ::= expr '(' [argList] ')'
indexExpr ::= expr '[' [expr] ']' indexExpr ::= expr '[' [expr] ']'
@@ -312,7 +321,8 @@ private keywordAsName_ ::= 'if' | 'for' | 'case' | 'enum' | 'cast' | 'union' | '
// `,,` introduces an inline context change: `join(parts,, allocator = temp)`. // `,,` introduces an inline context change: `join(parts,, allocator = temp)`.
private argList ::= argument ((',' | ',,') argument)* [','] private argList ::= argument ((',' | ',,') argument)* [',']
argument ::= '---' | expr argument ::= '---' | namedArgument | expr
namedArgument ::= <<isNamedArgumentAhead>> memberName '=' (block | expr)
primaryExpr ::= procLiteralExpr primaryExpr ::= procLiteralExpr
| structExpr | structExpr
@@ -364,20 +374,24 @@ returnGroup ::= '(' [returnItem (',' returnItem)*] ')'
returnItem ::= [<<isParamNameAhead>> IDENT ':'] <<exprNoAssign>> returnItem ::= [<<isParamNameAhead>> IDENT ':'] <<exprNoAssign>>
// `#foreign lib`, `#modify { ... }`, `#c_call`, `#expand`, … // `#foreign lib`, `#modify { ... }`, `#c_call`, `#expand`, …
procModifier ::= <<dirWithBlock>> directiveFlag_* block // `#foreign lib "symbol"`, `#modify { ... }`, `#c_call`, `#expand`, `#align 8` — the
| <<dirWithOperand>> directiveFlag_* [expr] // same shape as any other directive, so there is one rule for both positions.
| <<dirPlain>> directiveFlag_* procModifier ::= directiveExpr
structExpr ::= 'struct' ['(' [paramList] ')'] structModifier_* block structExpr ::= 'struct' ['(' [paramList] ')'] structModifier_* block
enumExpr ::= ('enum' | 'enum_flags') [!'{' expr] structModifier_* block enumExpr ::= ('enum' | 'enum_flags') [!'{' expr] structModifier_* block
unionExpr ::= 'union' structModifier_* block unionExpr ::= 'union' ['(' [paramList] ')'] structModifier_* block
private structModifier_ ::= procModifier private structModifier_ ::= procModifier
// -------------------------------------------------------------------- directives // -------------------------------------------------------------------- directives
// `#ident` is one token, so which directives take operands is decided in // `#ident` is one token, so which directives take operands is decided in
// JaiParserUtil rather than here. // JaiParserUtil rather than here.
// `#foreign libc "inotify_init1"` names the library and then the C symbol.
directiveExpr ::= <<dir "#asm">> directiveFlag_* <<opaqueBlock>> directiveExpr ::= <<dir "#asm">> directiveFlag_* <<opaqueBlock>>
| <<dir "#foreign">> directiveFlag_* [<<exprNoAssign>>] [STRING]
| <<dir "#elsewhere">> directiveFlag_* [<<exprNoAssign>>] [STRING]
| <<dir "#insert">> directiveFlag_* ['(' [argList] ')'] [block | expr]
| <<dir "#assert">> expr [expr] | <<dir "#assert">> expr [expr]
| <<dir "#module_parameters">> '(' [paramList] ')' ['(' [paramList] ')'] [block] | <<dir "#module_parameters">> '(' [paramList] ')' ['(' [paramList] ')'] [block]
| <<dirWithBlock>> directiveFlag_* block | <<dirWithBlock>> directiveFlag_* block
@@ -385,5 +399,6 @@ directiveExpr ::= <<dir "#asm">> directiveFlag_* <<opaqueBlock>>
| <<dirPlain>> directiveFlag_* | <<dirPlain>> directiveFlag_*
// `#import,file`, `#library,system,link_always`, `#run,stallable` — a directive can // `#import,file`, `#library,system,link_always`, `#run,stallable` — a directive can
// carry any number of comma-separated flags. // carry any number of comma-separated flags. Adjacency is enforced in the util; see
private directiveFlag_ ::= ',' IDENT // JaiParserUtil.directiveFlag.
private directiveFlag_ ::= <<directiveFlag>>

View File

@@ -4,6 +4,7 @@ import com.intellij.lang.PsiBuilder
import com.intellij.lang.parser.GeneratedParserUtilBase import com.intellij.lang.parser.GeneratedParserUtilBase
import com.intellij.psi.TokenType import com.intellij.psi.TokenType
import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.IElementType
import dev.hgh.jai.lexer.JaiTokenTypes
import dev.hgh.jai.lexer.JaiTokenTypes as T import dev.hgh.jai.lexer.JaiTokenTypes as T
/** /**
@@ -170,6 +171,39 @@ object JaiParserUtil : GeneratedParserUtilBase() {
return true 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 // ------------------------------------------------------------------ operators
/** /**
@@ -291,7 +325,8 @@ object JaiParserUtil : GeneratedParserUtilBase() {
* `foo :: () {}` apart from `foo();`. * `foo :: () {}` apart from `foo();`.
* *
* The prefix skip covers `#as using base: Document;`, * 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; ``. * `` `it := entry.value; ``.
*/ */
@JvmStatic @JvmStatic
@@ -300,10 +335,12 @@ object JaiParserUtil : GeneratedParserUtilBase() {
level: Int, level: Int,
): Boolean { ): Boolean {
var i = 0 var i = 0
var inPrefix = false
loop@ while (true) { loop@ while (true) {
when (b.lookAhead(i)) { when (b.lookAhead(i)) {
T.DIRECTIVE, T.KW_USING -> { T.DIRECTIVE, T.KW_USING -> {
i++ i++
inPrefix = true
} }
T.LPAREN -> { T.LPAREN -> {
@@ -311,6 +348,14 @@ object JaiParserUtil : GeneratedParserUtilBase() {
if (i < 0) return false 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 -> { else -> {
break@loop break@loop
} }

View File

@@ -1,6 +1,7 @@
package dev.hgh.jai.parser package dev.hgh.jai.parser
import com.intellij.psi.PsiErrorElement import com.intellij.psi.PsiErrorElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiFileFactory import com.intellij.psi.PsiFileFactory
import com.intellij.psi.PsiRecursiveElementWalkingVisitor import com.intellij.psi.PsiRecursiveElementWalkingVisitor
import com.intellij.testFramework.fixtures.BasePlatformTestCase import com.intellij.testFramework.fixtures.BasePlatformTestCase
@@ -9,39 +10,30 @@ import java.io.File
/** /**
* Scratch harness for grammar work. Not a gate — the gate is [JaiCorpusParserTest]. * Scratch harness for grammar work. Not a gate — the gate is [JaiCorpusParserTest].
* * Edit [snippets] and [corpusFiles] freely while iterating on `Jai.bnf`.
* Set `-Djai.debug.file=<path>` to dump every error in one corpus file instead.
*/ */
class DebugParseTest : BasePlatformTestCase() { class DebugParseTest : BasePlatformTestCase() {
private val snippets = private val snippets =
listOf( listOf(
"tzname: **u8 #elsewhere libc;\n", "#scope_file\n\n\nbig_endian :: () -> bool {\n return true;\n}\n",
"S :: struct {\n #as unknown: IUnknown;\n}\n", "S :: struct {\n #as using,except(vtable) iunknown: IUnknown;\n}\n",
"x.magic = (.*) cast(*u32) DATA.data;\n", "using,except(FT_Init) new_module :: #import \"freetype\";\n",
"M :: #library,system,link_always \"Metal\";\n", "operator []= :: inline (a: *B, i: int, v: bool) { }\n",
"f :: (s: *u8, \$strict := false) -> u32 { return 1; }\n", "inotify_init :: (flags: s32 = 0) -> s32 #foreign libc \"inotify_init1\";\n",
"#module_parameters (MAX := 4, VERBOSE := false);\n", "F :: (a: *L) -> E #foreign ft #deprecated \"msg\";\n",
"Allocator_Proc :: #type (mode: int, old: *void) -> *void;\n",
"SimpleProcedure :: #type () -> ();\n",
"n := tprint(\"%\", ifx options.output_path else \".\");\n",
"v :: (info: *File_Visit_Info, modules : *[..] string) { }\n",
"B :: struct (type: Type, by_pointer := false) { }\n",
"e := ifx a then b;\n",
) )
/** Corpus files to dump the first error of; edit freely while working. */ /** Corpus files to dump the first error of. */
private val corpusFiles = private val corpusFiles =
listOf( listOf(
"modules/Sound_Player/os/win32.jai", "modules/Basic/Array.jai",
"examples/module_info.jai", "modules/Debug/windows.jai",
"how_to/800_allocators.jai", "modules/Simp/backend/gl.jai",
"modules/POSIX/module.jai", "modules/GetRect/system/occlusion.jai",
"modules/Basic/module.jai", "modules/POSIX/compare_bindings.jai",
"modules/Compiler/module.jai", "modules/Android/Toolchain/apk.jai",
"modules/Window_Creation/module.jai", "modules/Curl/examples/ftp.jai",
"modules/String/module.jai", "modules/Objective_C/LightweightRenderingView/module.jai",
"modules/Hash_Table.jai",
"modules/Math/module.jai",
) )
fun testCorpusFiles() { fun testCorpusFiles() {
@@ -54,11 +46,6 @@ class DebugParseTest : BasePlatformTestCase() {
} }
fun testSnippets() { fun testSnippets() {
val debugFile = System.getProperty("jai.debug.file")
if (debugFile != null) {
dumpFile(File(debugFile))
return
}
val factory = PsiFileFactory.getInstance(project) val factory = PsiFileFactory.getInstance(project)
var failures = 0 var failures = 0
for (text in snippets) { for (text in snippets) {
@@ -89,7 +76,7 @@ class DebugParseTest : BasePlatformTestCase() {
println(" at '${text.substring(error.textOffset).take(80).replace("\n", "\\n")}'") println(" at '${text.substring(error.textOffset).take(80).replace("\n", "\\n")}'")
} }
private fun firstError(file: com.intellij.psi.PsiFile): PsiErrorElement? { private fun firstError(file: PsiFile): PsiErrorElement? {
var first: PsiErrorElement? = null var first: PsiErrorElement? = null
file.accept( file.accept(
object : PsiRecursiveElementWalkingVisitor() { object : PsiRecursiveElementWalkingVisitor() {

View File

@@ -36,6 +36,7 @@ class JaiCorpusParserTest : BasePlatformTestCase() {
var totalErrors = 0 var totalErrors = 0
val filesWithErrors = mutableListOf<String>() val filesWithErrors = mutableListOf<String>()
val firstErrors = mutableListOf<String>() val firstErrors = mutableListOf<String>()
val allErrors = mutableListOf<String>()
val histogram = mutableMapOf<String, Int>() val histogram = mutableMapOf<String, Int>()
for (file in jaiFiles) { for (file in jaiFiles) {
@@ -62,10 +63,8 @@ class JaiCorpusParserTest : BasePlatformTestCase() {
val offset = error.textOffset val offset = error.textOffset
val got = snippet(text, offset).take(GOT_WIDTH) val got = snippet(text, offset).take(GOT_WIDTH)
histogram.merge(got, 1, Int::plus) histogram.merge(got, 1, Int::plus)
if (firstErrors.size < REPORTED_ERRORS) { val line = text.substring(0, offset).count { it == '\n' } + 1
val line = text.substring(0, offset).count { it == '\n' } + 1 allErrors.add("$relative:$line: ${error.errorDescription} [at '$got']")
firstErrors.add("$relative:$line: ${error.errorDescription} [at '$got']")
}
} }
} }
@@ -82,6 +81,10 @@ class JaiCorpusParserTest : BasePlatformTestCase() {
.take(REPORTED_KINDS) .take(REPORTED_KINDS)
.forEach { (token, count) -> println(" %5d %s".format(count, token)) } .forEach { (token, count) -> println(" %5d %s".format(count, token)) }
} }
// A spread across the corpus, not the first N alphabetically: the failures
// cluster by directory, so an alphabetical head hides whole categories.
val stride = maxOf(1, allErrors.size / REPORTED_ERRORS)
allErrors.filterIndexed { index, _ -> index % stride == 0 }.take(REPORTED_ERRORS).forEach { println(" $it") }
firstErrors.forEach { println(" $it") } firstErrors.forEach { println(" $it") }
assertTrue( assertTrue(
@@ -103,7 +106,7 @@ class JaiCorpusParserTest : BasePlatformTestCase() {
private companion object { private companion object {
/** Ratchet. Raise it as the grammar improves; never lower it. */ /** Ratchet. Raise it as the grammar improves; never lower it. */
const val MIN_CLEAN_FILES = 4 const val MIN_CLEAN_FILES = 575
const val REPORTED_ERRORS = 25 const val REPORTED_ERRORS = 25
const val REPORTED_KINDS = 20 const val REPORTED_KINDS = 20
const val GOT_WIDTH = 14 const val GOT_WIDTH = 14