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:
12
jaitest
12
jaitest
@@ -9,14 +9,24 @@
|
||||
# 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.
|
||||
#
|
||||
# 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*'
|
||||
set -uo pipefail
|
||||
|
||||
cd "$(dirname "$0")" || exit 1
|
||||
|
||||
extra=()
|
||||
if [[ " $* " != *" --tests "* ]]; then
|
||||
extra+=(--no-configuration-cache)
|
||||
fi
|
||||
|
||||
run_gradle() {
|
||||
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]}"
|
||||
}
|
||||
|
||||
|
||||
@@ -101,12 +101,13 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// '---' | expr
|
||||
// '---' | namedArgument | expr
|
||||
public static boolean argument(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "argument")) return false;
|
||||
boolean result_;
|
||||
Marker marker_ = enter_section_(builder_, level_, _NONE_, ARGUMENT, "<argument>");
|
||||
result_ = consumeToken(builder_, TRIPLE_MINUS);
|
||||
if (!result_) result_ = namedArgument(builder_, level_ + 1);
|
||||
if (!result_) result_ = expr(builder_, level_ + 1, -1);
|
||||
exit_section_(builder_, level_, marker_, result_, false, null);
|
||||
return result_;
|
||||
@@ -157,6 +158,40 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
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')
|
||||
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_) {
|
||||
if (!recursion_guard_(builder_, level_, "declModifier_")) return false;
|
||||
boolean result_;
|
||||
result_ = procModifier(builder_, level_ + 1);
|
||||
if (!result_) result_ = consumeToken(builder_, KW_USING);
|
||||
if (!result_) result_ = usingModifier_(builder_, level_ + 1);
|
||||
return result_;
|
||||
}
|
||||
|
||||
@@ -391,9 +426,9 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// ':' [<<exprNoAssign>>] procModifier* [('=' | ':') initializer]
|
||||
// | ':=' initializer
|
||||
// | '::' initializer
|
||||
// ':' [<<exprNoAssign>>] procModifier* [',' assignTargets_] [('=' | ':') initializerList_]
|
||||
// | ':=' initializerList_
|
||||
// | '::' initializerList_
|
||||
static boolean declTail_(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "declTail_")) return false;
|
||||
boolean result_;
|
||||
@@ -405,7 +440,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
return result_;
|
||||
}
|
||||
|
||||
// ':' [<<exprNoAssign>>] procModifier* [('=' | ':') initializer]
|
||||
// ':' [<<exprNoAssign>>] procModifier* [',' assignTargets_] [('=' | ':') initializerList_]
|
||||
private static boolean declTail__0(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "declTail__0")) return false;
|
||||
boolean result_;
|
||||
@@ -414,6 +449,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
result_ = result_ && declTail__0_1(builder_, level_ + 1);
|
||||
result_ = result_ && declTail__0_2(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_);
|
||||
return result_;
|
||||
}
|
||||
@@ -436,51 +472,69 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
// [('=' | ':') initializer]
|
||||
// [',' assignTargets_]
|
||||
private static boolean declTail__0_3(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "declTail__0_3")) return false;
|
||||
declTail__0_3_0(builder_, level_ + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ('=' | ':') initializer
|
||||
// ',' assignTargets_
|
||||
private static boolean declTail__0_3_0(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "declTail__0_3_0")) return false;
|
||||
boolean result_;
|
||||
Marker marker_ = enter_section_(builder_);
|
||||
result_ = declTail__0_3_0_0(builder_, level_ + 1);
|
||||
result_ = result_ && initializer(builder_, level_ + 1);
|
||||
result_ = consumeToken(builder_, COMMA);
|
||||
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_);
|
||||
return result_;
|
||||
}
|
||||
|
||||
// '=' | ':'
|
||||
private static boolean declTail__0_3_0_0(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "declTail__0_3_0_0")) return false;
|
||||
private static boolean declTail__0_4_0_0(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "declTail__0_4_0_0")) return false;
|
||||
boolean result_;
|
||||
result_ = consumeToken(builder_, EQ);
|
||||
if (!result_) result_ = consumeToken(builder_, COLON);
|
||||
return result_;
|
||||
}
|
||||
|
||||
// ':=' initializer
|
||||
// ':=' initializerList_
|
||||
private static boolean declTail__1(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "declTail__1")) return false;
|
||||
boolean result_;
|
||||
Marker marker_ = enter_section_(builder_);
|
||||
result_ = consumeToken(builder_, COLON_EQ);
|
||||
result_ = result_ && initializer(builder_, level_ + 1);
|
||||
result_ = result_ && initializerList_(builder_, level_ + 1);
|
||||
exit_section_(builder_, marker_, null, result_);
|
||||
return result_;
|
||||
}
|
||||
|
||||
// '::' initializer
|
||||
// '::' initializerList_
|
||||
private static boolean declTail__2(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "declTail__2")) return false;
|
||||
boolean result_;
|
||||
Marker marker_ = enter_section_(builder_);
|
||||
result_ = consumeToken(builder_, COLON_COLON);
|
||||
result_ = result_ && initializer(builder_, level_ + 1);
|
||||
result_ = result_ && initializerList_(builder_, level_ + 1);
|
||||
exit_section_(builder_, marker_, null, result_);
|
||||
return result_;
|
||||
}
|
||||
@@ -534,6 +588,9 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
|
||||
/* ********************************************************** */
|
||||
// <<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 "#module_parameters">> '(' [paramList] ')' ['(' [paramList] ')'] [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_4(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);
|
||||
return result_;
|
||||
}
|
||||
@@ -576,88 +636,91 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
// <<dir "#assert">> expr [expr]
|
||||
// <<dir "#foreign">> directiveFlag_* [<<exprNoAssign>>] [STRING]
|
||||
private static boolean directiveExpr_1(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveExpr_1")) return false;
|
||||
boolean result_;
|
||||
Marker marker_ = enter_section_(builder_);
|
||||
result_ = dir(builder_, level_ + 1, "#assert");
|
||||
result_ = result_ && expr(builder_, level_ + 1, -1);
|
||||
result_ = dir(builder_, level_ + 1, "#foreign");
|
||||
result_ = result_ && directiveExpr_1_1(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_);
|
||||
return result_;
|
||||
}
|
||||
|
||||
// [expr]
|
||||
private static boolean directiveExpr_1_2(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveExpr_1_2")) return false;
|
||||
expr(builder_, level_ + 1, -1);
|
||||
// directiveFlag_*
|
||||
private static boolean directiveExpr_1_1(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveExpr_1_1")) return false;
|
||||
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;
|
||||
}
|
||||
|
||||
// <<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_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveExpr_2")) return false;
|
||||
boolean result_;
|
||||
Marker marker_ = enter_section_(builder_);
|
||||
result_ = dir(builder_, level_ + 1, "#module_parameters");
|
||||
result_ = result_ && consumeToken(builder_, LPAREN);
|
||||
result_ = dir(builder_, level_ + 1, "#elsewhere");
|
||||
result_ = result_ && directiveExpr_2_1(builder_, level_ + 1);
|
||||
result_ = result_ && directiveExpr_2_2(builder_, level_ + 1);
|
||||
result_ = result_ && consumeToken(builder_, RPAREN);
|
||||
result_ = result_ && directiveExpr_2_4(builder_, level_ + 1);
|
||||
result_ = result_ && directiveExpr_2_5(builder_, level_ + 1);
|
||||
result_ = result_ && directiveExpr_2_3(builder_, level_ + 1);
|
||||
exit_section_(builder_, marker_, null, 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_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveExpr_2_2")) return false;
|
||||
paramList(builder_, level_ + 1);
|
||||
exprNoAssign(builder_, level_ + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ['(' [paramList] ')']
|
||||
private static boolean directiveExpr_2_4(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveExpr_2_4")) return false;
|
||||
directiveExpr_2_4_0(builder_, level_ + 1);
|
||||
// [STRING]
|
||||
private static boolean directiveExpr_2_3(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveExpr_2_3")) return false;
|
||||
consumeToken(builder_, STRING);
|
||||
return true;
|
||||
}
|
||||
|
||||
// '(' [paramList] ')'
|
||||
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
|
||||
// <<dir "#insert">> directiveFlag_* ['(' [argList] ')'] [block | expr]
|
||||
private static boolean directiveExpr_3(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveExpr_3")) return false;
|
||||
boolean result_;
|
||||
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_ && 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_);
|
||||
return result_;
|
||||
}
|
||||
@@ -673,29 +736,60 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
// <<dirWithOperand>> directiveFlag_* [expr]
|
||||
private static boolean directiveExpr_4(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveExpr_4")) return false;
|
||||
// ['(' [argList] ')']
|
||||
private static boolean directiveExpr_3_2(PsiBuilder builder_, int level_) {
|
||||
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_;
|
||||
Marker marker_ = enter_section_(builder_);
|
||||
result_ = dirWithOperand(builder_, level_ + 1);
|
||||
result_ = result_ && directiveExpr_4_1(builder_, level_ + 1);
|
||||
result_ = result_ && directiveExpr_4_2(builder_, level_ + 1);
|
||||
result_ = consumeToken(builder_, LPAREN);
|
||||
result_ = result_ && directiveExpr_3_2_0_1(builder_, level_ + 1);
|
||||
result_ = result_ && consumeToken(builder_, RPAREN);
|
||||
exit_section_(builder_, marker_, null, result_);
|
||||
return result_;
|
||||
}
|
||||
|
||||
// directiveFlag_*
|
||||
private static boolean directiveExpr_4_1(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveExpr_4_1")) return false;
|
||||
while (true) {
|
||||
int pos_ = current_position_(builder_);
|
||||
if (!directiveFlag_(builder_, level_ + 1)) break;
|
||||
if (!empty_element_parsed_guard_(builder_, "directiveExpr_4_1", pos_)) break;
|
||||
}
|
||||
// [argList]
|
||||
private static boolean directiveExpr_3_2_0_1(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveExpr_3_2_0_1")) return false;
|
||||
argList(builder_, level_ + 1);
|
||||
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]
|
||||
private static boolean directiveExpr_4_2(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveExpr_4_2")) return false;
|
||||
@@ -703,38 +797,140 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
// <<dirPlain>> directiveFlag_*
|
||||
// <<dir "#module_parameters">> '(' [paramList] ')' ['(' [paramList] ')'] [block]
|
||||
private static boolean directiveExpr_5(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveExpr_5")) return false;
|
||||
boolean result_;
|
||||
Marker marker_ = enter_section_(builder_);
|
||||
result_ = dirPlain(builder_, level_ + 1);
|
||||
result_ = result_ && directiveExpr_5_1(builder_, level_ + 1);
|
||||
result_ = dir(builder_, level_ + 1, "#module_parameters");
|
||||
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_);
|
||||
return result_;
|
||||
}
|
||||
|
||||
// directiveFlag_*
|
||||
private static boolean directiveExpr_5_1(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveExpr_5_1")) return false;
|
||||
private static boolean directiveExpr_6_1(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveExpr_6_1")) return false;
|
||||
while (true) {
|
||||
int pos_ = current_position_(builder_);
|
||||
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;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// ',' IDENT
|
||||
// <<directiveFlag>>
|
||||
static boolean directiveFlag_(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "directiveFlag_")) return false;
|
||||
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_;
|
||||
return directiveFlag(builder_, level_ + 1);
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
@@ -1059,6 +1255,28 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
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
|
||||
public static boolean initializer(PsiBuilder builder_, int level_) {
|
||||
@@ -1071,6 +1289,40 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
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]
|
||||
public static boolean interfaceExpr(PsiBuilder builder_, int level_) {
|
||||
@@ -1168,6 +1420,29 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
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+
|
||||
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_) {
|
||||
if (!recursion_guard_(builder_, level_, "operatorSymbol")) return false;
|
||||
boolean result_;
|
||||
@@ -1228,8 +1503,8 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
if (!result_) result_ = consumeToken(builder_, SHR);
|
||||
if (!result_) result_ = consumeToken(builder_, ROL);
|
||||
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);
|
||||
exit_section_(builder_, level_, marker_, result_, false, null);
|
||||
return result_;
|
||||
}
|
||||
@@ -1648,97 +1923,18 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// <<dirWithBlock>> directiveFlag_* block
|
||||
// | <<dirWithOperand>> directiveFlag_* [expr]
|
||||
// | <<dirPlain>> directiveFlag_*
|
||||
// directiveExpr
|
||||
public static boolean procModifier(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "procModifier")) return false;
|
||||
boolean result_;
|
||||
Marker marker_ = enter_section_(builder_, level_, _NONE_, PROC_MODIFIER, "<proc modifier>");
|
||||
result_ = procModifier_0(builder_, level_ + 1);
|
||||
if (!result_) result_ = procModifier_1(builder_, level_ + 1);
|
||||
if (!result_) result_ = procModifier_2(builder_, level_ + 1);
|
||||
result_ = directiveExpr(builder_, level_ + 1);
|
||||
exit_section_(builder_, level_, marker_, result_, false, null);
|
||||
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_) {
|
||||
if (!recursion_guard_(builder_, level_, "pushContextStatement")) 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>");
|
||||
result_ = pushContextStatement_0(builder_, level_ + 1);
|
||||
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);
|
||||
exit_section_(builder_, level_, marker_, result_, false, null);
|
||||
return result_;
|
||||
@@ -1759,6 +1955,13 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
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
|
||||
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_) {
|
||||
if (!recursion_guard_(builder_, level_, "unionExpr")) return false;
|
||||
if (!nextTokenIs(builder_, KW_UNION)) return false;
|
||||
@@ -2236,22 +2439,106 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
Marker marker_ = enter_section_(builder_);
|
||||
result_ = consumeToken(builder_, KW_UNION);
|
||||
result_ = result_ && unionExpr_1(builder_, level_ + 1);
|
||||
result_ = result_ && unionExpr_2(builder_, level_ + 1);
|
||||
result_ = result_ && block(builder_, level_ + 1);
|
||||
exit_section_(builder_, marker_, UNION_EXPR, result_);
|
||||
return result_;
|
||||
}
|
||||
|
||||
// structModifier_*
|
||||
// ['(' [paramList] ')']
|
||||
private static boolean unionExpr_1(PsiBuilder builder_, int level_) {
|
||||
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) {
|
||||
int pos_ = current_position_(builder_);
|
||||
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;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// '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
|
||||
public static boolean usingStatement(PsiBuilder builder_, int level_) {
|
||||
@@ -2643,18 +2930,17 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
return result_;
|
||||
}
|
||||
|
||||
// 'ifx' expr ['then'] [expr] ['else' expr]
|
||||
// ifxKeyword_ expr ['then'] [ifxBranch_] ['else' ifxBranch_]
|
||||
public static boolean ifxExpr(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "ifxExpr")) return false;
|
||||
if (!nextTokenIsSmart(builder_, KW_IFX)) return false;
|
||||
boolean result_;
|
||||
Marker marker_ = enter_section_(builder_);
|
||||
result_ = consumeTokenSmart(builder_, KW_IFX);
|
||||
Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, IFX_EXPR, "<ifx expr>");
|
||||
result_ = ifxKeyword_(builder_, level_ + 1);
|
||||
result_ = result_ && expr(builder_, level_ + 1, -1);
|
||||
result_ = result_ && ifxExpr_2(builder_, level_ + 1);
|
||||
result_ = result_ && ifxExpr_3(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_;
|
||||
}
|
||||
|
||||
@@ -2665,27 +2951,27 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
// [expr]
|
||||
// [ifxBranch_]
|
||||
private static boolean ifxExpr_3(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "ifxExpr_3")) return false;
|
||||
expr(builder_, level_ + 1, -1);
|
||||
ifxBranch_(builder_, level_ + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ['else' expr]
|
||||
// ['else' ifxBranch_]
|
||||
private static boolean ifxExpr_4(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "ifxExpr_4")) return false;
|
||||
ifxExpr_4_0(builder_, level_ + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 'else' expr
|
||||
// 'else' ifxBranch_
|
||||
private static boolean ifxExpr_4_0(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "ifxExpr_4_0")) return false;
|
||||
boolean result_;
|
||||
Marker marker_ = enter_section_(builder_);
|
||||
result_ = consumeTokenSmart(builder_, KW_ELSE);
|
||||
result_ = result_ && expr(builder_, level_ + 1, -1);
|
||||
result_ = result_ && ifxBranch_(builder_, level_ + 1);
|
||||
exit_section_(builder_, marker_, null, result_);
|
||||
return result_;
|
||||
}
|
||||
|
||||
@@ -10,4 +10,7 @@ public interface JaiArgument extends PsiElement {
|
||||
@Nullable
|
||||
JaiExpr getExpr();
|
||||
|
||||
@Nullable
|
||||
JaiNamedArgument getNamedArgument();
|
||||
|
||||
}
|
||||
|
||||
@@ -7,11 +7,14 @@ import com.intellij.psi.PsiElement;
|
||||
|
||||
public interface JaiDeclaration extends PsiElement {
|
||||
|
||||
@NotNull
|
||||
List<JaiArgument> getArgumentList();
|
||||
|
||||
@NotNull
|
||||
JaiDeclNames getDeclNames();
|
||||
|
||||
@Nullable
|
||||
JaiInitializer getInitializer();
|
||||
@NotNull
|
||||
List<JaiInitializer> getInitializerList();
|
||||
|
||||
@NotNull
|
||||
List<JaiProcModifier> getProcModifierList();
|
||||
|
||||
@@ -7,11 +7,14 @@ import com.intellij.psi.PsiElement;
|
||||
|
||||
public interface JaiDirectiveExpr extends JaiExpr {
|
||||
|
||||
@NotNull
|
||||
List<JaiArgument> getArgumentList();
|
||||
|
||||
@Nullable
|
||||
JaiBlock getBlock();
|
||||
|
||||
@NotNull
|
||||
List<JaiExpr> getExprList();
|
||||
@Nullable
|
||||
JaiExpr getExpr();
|
||||
|
||||
@NotNull
|
||||
List<JaiParameter> getParameterList();
|
||||
|
||||
@@ -7,6 +7,9 @@ import com.intellij.psi.PsiElement;
|
||||
|
||||
public interface JaiIfxExpr extends JaiExpr {
|
||||
|
||||
@NotNull
|
||||
List<JaiBlock> getBlockList();
|
||||
|
||||
@NotNull
|
||||
List<JaiExpr> getExprList();
|
||||
|
||||
|
||||
19
src/main/gen/dev/hgh/jai/psi/JaiNamedArgument.java
Normal file
19
src/main/gen/dev/hgh/jai/psi/JaiNamedArgument.java
Normal 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();
|
||||
|
||||
}
|
||||
@@ -7,10 +7,7 @@ import com.intellij.psi.PsiElement;
|
||||
|
||||
public interface JaiProcModifier extends PsiElement {
|
||||
|
||||
@Nullable
|
||||
JaiBlock getBlock();
|
||||
|
||||
@Nullable
|
||||
JaiExpr getExpr();
|
||||
@NotNull
|
||||
JaiDirectiveExpr getDirectiveExpr();
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ public interface JaiPushContextStatement extends PsiElement {
|
||||
@NotNull
|
||||
JaiBlock getBlock();
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
JaiExpr getExpr();
|
||||
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ public interface JaiTypes {
|
||||
IElementType MEMBER_EXPR = new JaiElementType("MEMBER_EXPR");
|
||||
IElementType MEMBER_NAME = new JaiElementType("MEMBER_NAME");
|
||||
IElementType MUL_EXPR = new JaiElementType("MUL_EXPR");
|
||||
IElementType NAMED_ARGUMENT = new JaiElementType("NAMED_ARGUMENT");
|
||||
IElementType NOTE_STATEMENT = new JaiElementType("NOTE_STATEMENT");
|
||||
IElementType OPERATOR_DECLARATION = new JaiElementType("OPERATOR_DECLARATION");
|
||||
IElementType OPERATOR_SYMBOL = new JaiElementType("OPERATOR_SYMBOL");
|
||||
@@ -327,6 +328,9 @@ public interface JaiTypes {
|
||||
else if (type == MUL_EXPR) {
|
||||
return new JaiMulExprImpl(node);
|
||||
}
|
||||
else if (type == NAMED_ARGUMENT) {
|
||||
return new JaiNamedArgumentImpl(node);
|
||||
}
|
||||
else if (type == NOTE_STATEMENT) {
|
||||
return new JaiNoteStatementImpl(node);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@ public interface JaiUnionExpr extends JaiExpr {
|
||||
@NotNull
|
||||
JaiBlock getBlock();
|
||||
|
||||
@NotNull
|
||||
List<JaiParameter> getParameterList();
|
||||
|
||||
@NotNull
|
||||
List<JaiProcModifier> getProcModifierList();
|
||||
|
||||
|
||||
@@ -183,6 +183,10 @@ public class JaiVisitor extends PsiElementVisitor {
|
||||
visitExpr(o);
|
||||
}
|
||||
|
||||
public void visitNamedArgument(@NotNull JaiNamedArgument o) {
|
||||
visitPsiElement(o);
|
||||
}
|
||||
|
||||
public void visitNoteStatement(@NotNull JaiNoteStatement o) {
|
||||
visitPsiElement(o);
|
||||
}
|
||||
|
||||
@@ -33,4 +33,10 @@ public class JaiArgumentImpl extends ASTWrapperPsiElement implements JaiArgument
|
||||
return findChildByClass(JaiExpr.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public JaiNamedArgument getNamedArgument() {
|
||||
return findChildByClass(JaiNamedArgument.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,12 @@ public class JaiDeclarationImpl extends ASTWrapperPsiElement implements JaiDecla
|
||||
else super.accept(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JaiArgument> getArgumentList() {
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiArgument.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public JaiDeclNames getDeclNames() {
|
||||
@@ -34,9 +40,9 @@ public class JaiDeclarationImpl extends ASTWrapperPsiElement implements JaiDecla
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public JaiInitializer getInitializer() {
|
||||
return findChildByClass(JaiInitializer.class);
|
||||
@NotNull
|
||||
public List<JaiInitializer> getInitializerList() {
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiInitializer.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,6 +27,12 @@ public class JaiDirectiveExprImpl extends JaiExprImpl implements JaiDirectiveExp
|
||||
else super.accept(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JaiArgument> getArgumentList() {
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiArgument.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public JaiBlock getBlock() {
|
||||
@@ -34,9 +40,9 @@ public class JaiDirectiveExprImpl extends JaiExprImpl implements JaiDirectiveExp
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JaiExpr> getExprList() {
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiExpr.class);
|
||||
@Nullable
|
||||
public JaiExpr getExpr() {
|
||||
return findChildByClass(JaiExpr.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,6 +27,12 @@ public class JaiIfxExprImpl extends JaiExprImpl implements JaiIfxExpr {
|
||||
else super.accept(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JaiBlock> getBlockList() {
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiBlock.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JaiExpr> getExprList() {
|
||||
|
||||
48
src/main/gen/dev/hgh/jai/psi/impl/JaiNamedArgumentImpl.java
Normal file
48
src/main/gen/dev/hgh/jai/psi/impl/JaiNamedArgumentImpl.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,15 +28,9 @@ public class JaiProcModifierImpl extends ASTWrapperPsiElement implements JaiProc
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public JaiBlock getBlock() {
|
||||
return findChildByClass(JaiBlock.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public JaiExpr getExpr() {
|
||||
return findChildByClass(JaiExpr.class);
|
||||
@NotNull
|
||||
public JaiDirectiveExpr getDirectiveExpr() {
|
||||
return findNotNullChildByClass(JaiDirectiveExpr.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,9 +34,9 @@ public class JaiPushContextStatementImpl extends ASTWrapperPsiElement implements
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@Nullable
|
||||
public JaiExpr getExpr() {
|
||||
return findNotNullChildByClass(JaiExpr.class);
|
||||
return findChildByClass(JaiExpr.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,6 +33,12 @@ public class JaiUnionExprImpl extends JaiExprImpl implements JaiUnionExpr {
|
||||
return findNotNullChildByClass(JaiBlock.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JaiParameter> getParameterList() {
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiParameter.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JaiProcModifier> getProcModifierList() {
|
||||
|
||||
@@ -203,7 +203,7 @@ breakStatement ::= 'break' [IDENT] semi
|
||||
continueStatement ::= 'continue' [IDENT] semi
|
||||
removeStatement ::= 'remove' [expr] semi
|
||||
deferStatement ::= ['`'] 'defer' statement
|
||||
pushContextStatement ::= ['`'] 'push_context' expr block
|
||||
pushContextStatement ::= ['`'] 'push_context' [expr] block
|
||||
usingStatement ::= 'using' [',' expr] expr semi
|
||||
|
||||
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
|
||||
// an expression statement such as `foo();`.
|
||||
declaration ::= <<isDeclarationAhead>> declModifier_* declNames declTail_ semiWithNotes_
|
||||
// `#as using base: Document;`, `#overlay (unknown.vtable) using vtable: *Vtable;`
|
||||
private declModifier_ ::= procModifier | 'using'
|
||||
// `#as using base: Document;`, `#overlay (unknown.vtable) using vtable: *Vtable;`,
|
||||
// `#as using,except(vtable) iunknown: IUnknown;`
|
||||
private declModifier_ ::= procModifier | usingModifier_
|
||||
private usingModifier_ ::= 'using' [directiveFlag_ ['(' [argList] ')']]
|
||||
declNames ::= declName (',' declName)*
|
||||
declName ::= ['`'] IDENT
|
||||
private declTail_ ::= ':' [<<exprNoAssign>>] procModifier* [('=' | ':') initializer]
|
||||
| ':=' initializer
|
||||
| '::' initializer
|
||||
private declTail_ ::= ':' [<<exprNoAssign>>] procModifier* [',' assignTargets_] [('=' | ':') initializerList_]
|
||||
| ':=' initializerList_
|
||||
| '::' 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
|
||||
|
||||
// `operator + :: (a: T, b: T) -> T { }`
|
||||
operatorDeclaration ::= 'operator' operatorSymbol '::' expr semiWithNotes_
|
||||
operatorSymbol ::= '+' | '-' | '*' | '/' | '%' | '==' | '!=' | '<' | '>' | '<=' | '>='
|
||||
| '&' | '|' | '^' | '~' | '<<' | '>>' | '<<<' | '>>>'
|
||||
| '[' ']' | '[' ']' '='
|
||||
| '[' ']' '=' | '[' ']'
|
||||
|
||||
// -------------------------------------------------------------------- expressions
|
||||
|
||||
@@ -293,7 +300,9 @@ derefCastExpr ::= '(' '.*' ')' expr
|
||||
castExpr ::= 'cast' [',' IDENT] '(' [expr] ')' expr
|
||||
autoCastExpr ::= 'xx' [',' IDENT] 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] ')'
|
||||
indexExpr ::= expr '[' [expr] ']'
|
||||
@@ -312,7 +321,8 @@ private keywordAsName_ ::= 'if' | 'for' | 'case' | 'enum' | 'cast' | 'union' | '
|
||||
|
||||
// `,,` introduces an inline context change: `join(parts,, allocator = temp)`.
|
||||
private argList ::= argument ((',' | ',,') argument)* [',']
|
||||
argument ::= '---' | expr
|
||||
argument ::= '---' | namedArgument | expr
|
||||
namedArgument ::= <<isNamedArgumentAhead>> memberName '=' (block | expr)
|
||||
|
||||
primaryExpr ::= procLiteralExpr
|
||||
| structExpr
|
||||
@@ -364,20 +374,24 @@ returnGroup ::= '(' [returnItem (',' returnItem)*] ')'
|
||||
returnItem ::= [<<isParamNameAhead>> IDENT ':'] <<exprNoAssign>>
|
||||
|
||||
// `#foreign lib`, `#modify { ... }`, `#c_call`, `#expand`, …
|
||||
procModifier ::= <<dirWithBlock>> directiveFlag_* block
|
||||
| <<dirWithOperand>> directiveFlag_* [expr]
|
||||
| <<dirPlain>> directiveFlag_*
|
||||
// `#foreign lib "symbol"`, `#modify { ... }`, `#c_call`, `#expand`, `#align 8` — the
|
||||
// same shape as any other directive, so there is one rule for both positions.
|
||||
procModifier ::= directiveExpr
|
||||
|
||||
structExpr ::= 'struct' ['(' [paramList] ')'] structModifier_* block
|
||||
enumExpr ::= ('enum' | 'enum_flags') [!'{' expr] structModifier_* block
|
||||
unionExpr ::= 'union' structModifier_* block
|
||||
unionExpr ::= 'union' ['(' [paramList] ')'] structModifier_* block
|
||||
private structModifier_ ::= procModifier
|
||||
|
||||
// -------------------------------------------------------------------- directives
|
||||
|
||||
// `#ident` is one token, so which directives take operands is decided in
|
||||
// JaiParserUtil rather than here.
|
||||
// `#foreign libc "inotify_init1"` names the library and then the C symbol.
|
||||
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 "#module_parameters">> '(' [paramList] ')' ['(' [paramList] ')'] [block]
|
||||
| <<dirWithBlock>> directiveFlag_* block
|
||||
@@ -385,5 +399,6 @@ directiveExpr ::= <<dir "#asm">> directiveFlag_* <<opaqueBlock>>
|
||||
| <<dirPlain>> directiveFlag_*
|
||||
|
||||
// `#import,file`, `#library,system,link_always`, `#run,stallable` — a directive can
|
||||
// carry any number of comma-separated flags.
|
||||
private directiveFlag_ ::= ',' IDENT
|
||||
// carry any number of comma-separated flags. Adjacency is enforced in the util; see
|
||||
// JaiParserUtil.directiveFlag.
|
||||
private directiveFlag_ ::= <<directiveFlag>>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.hgh.jai.parser
|
||||
|
||||
import com.intellij.psi.PsiErrorElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiFileFactory
|
||||
import com.intellij.psi.PsiRecursiveElementWalkingVisitor
|
||||
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].
|
||||
*
|
||||
* Set `-Djai.debug.file=<path>` to dump every error in one corpus file instead.
|
||||
* Edit [snippets] and [corpusFiles] freely while iterating on `Jai.bnf`.
|
||||
*/
|
||||
class DebugParseTest : BasePlatformTestCase() {
|
||||
private val snippets =
|
||||
listOf(
|
||||
"tzname: **u8 #elsewhere libc;\n",
|
||||
"S :: struct {\n #as unknown: IUnknown;\n}\n",
|
||||
"x.magic = (.*) cast(*u32) DATA.data;\n",
|
||||
"M :: #library,system,link_always \"Metal\";\n",
|
||||
"f :: (s: *u8, \$strict := false) -> u32 { return 1; }\n",
|
||||
"#module_parameters (MAX := 4, VERBOSE := false);\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",
|
||||
"#scope_file\n\n\nbig_endian :: () -> bool {\n return true;\n}\n",
|
||||
"S :: struct {\n #as using,except(vtable) iunknown: IUnknown;\n}\n",
|
||||
"using,except(FT_Init) new_module :: #import \"freetype\";\n",
|
||||
"operator []= :: inline (a: *B, i: int, v: bool) { }\n",
|
||||
"inotify_init :: (flags: s32 = 0) -> s32 #foreign libc \"inotify_init1\";\n",
|
||||
"F :: (a: *L) -> E #foreign ft #deprecated \"msg\";\n",
|
||||
)
|
||||
|
||||
/** Corpus files to dump the first error of; edit freely while working. */
|
||||
/** Corpus files to dump the first error of. */
|
||||
private val corpusFiles =
|
||||
listOf(
|
||||
"modules/Sound_Player/os/win32.jai",
|
||||
"examples/module_info.jai",
|
||||
"how_to/800_allocators.jai",
|
||||
"modules/POSIX/module.jai",
|
||||
"modules/Basic/module.jai",
|
||||
"modules/Compiler/module.jai",
|
||||
"modules/Window_Creation/module.jai",
|
||||
"modules/String/module.jai",
|
||||
"modules/Hash_Table.jai",
|
||||
"modules/Math/module.jai",
|
||||
"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",
|
||||
)
|
||||
|
||||
fun testCorpusFiles() {
|
||||
@@ -54,11 +46,6 @@ class DebugParseTest : BasePlatformTestCase() {
|
||||
}
|
||||
|
||||
fun testSnippets() {
|
||||
val debugFile = System.getProperty("jai.debug.file")
|
||||
if (debugFile != null) {
|
||||
dumpFile(File(debugFile))
|
||||
return
|
||||
}
|
||||
val factory = PsiFileFactory.getInstance(project)
|
||||
var failures = 0
|
||||
for (text in snippets) {
|
||||
@@ -89,7 +76,7 @@ class DebugParseTest : BasePlatformTestCase() {
|
||||
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
|
||||
file.accept(
|
||||
object : PsiRecursiveElementWalkingVisitor() {
|
||||
|
||||
@@ -36,6 +36,7 @@ class JaiCorpusParserTest : BasePlatformTestCase() {
|
||||
var totalErrors = 0
|
||||
val filesWithErrors = mutableListOf<String>()
|
||||
val firstErrors = mutableListOf<String>()
|
||||
val allErrors = mutableListOf<String>()
|
||||
val histogram = mutableMapOf<String, Int>()
|
||||
|
||||
for (file in jaiFiles) {
|
||||
@@ -62,10 +63,8 @@ class JaiCorpusParserTest : BasePlatformTestCase() {
|
||||
val offset = error.textOffset
|
||||
val got = snippet(text, offset).take(GOT_WIDTH)
|
||||
histogram.merge(got, 1, Int::plus)
|
||||
if (firstErrors.size < REPORTED_ERRORS) {
|
||||
val line = text.substring(0, offset).count { it == '\n' } + 1
|
||||
firstErrors.add("$relative:$line: ${error.errorDescription} [at '$got']")
|
||||
}
|
||||
val line = text.substring(0, offset).count { it == '\n' } + 1
|
||||
allErrors.add("$relative:$line: ${error.errorDescription} [at '$got']")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +81,10 @@ class JaiCorpusParserTest : BasePlatformTestCase() {
|
||||
.take(REPORTED_KINDS)
|
||||
.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") }
|
||||
|
||||
assertTrue(
|
||||
@@ -103,7 +106,7 @@ class JaiCorpusParserTest : BasePlatformTestCase() {
|
||||
|
||||
private companion object {
|
||||
/** 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_KINDS = 20
|
||||
const val GOT_WIDTH = 14
|
||||
|
||||
Reference in New Issue
Block a user