Parser: raise corpus parse rate from 57% to 69%

Grammar gains: array types, directive flags, declaration-level directive
modifiers, parameter markers, backticked declaration names, notes after a
block-valued declaration, 'if cond then stmt', 'ifx c else v', '#module_parameters'
two-group form, '(.*)' prefix dereference, and '#asm' bodies consumed opaquely
(they are x86-64 assembly, not Jai).

Return items no longer take a default value: allowing one made
'f: (K) -> u32 = null' swallow the enclosing parameter's default and read the
rest of the parameter list as extra return values.
This commit is contained in:
hgranthorner
2026-08-04 12:13:26 -04:00
parent 37809b8aa7
commit 840a503e40
19 changed files with 727 additions and 220 deletions

View File

@@ -39,14 +39,14 @@ public class JaiParser implements PsiParser, LightPsiParser {
create_token_set_(ADD_EXPR, AND_EXPR, ARRAY_LITERAL_EXPR, ARRAY_TYPE_EXPR, create_token_set_(ADD_EXPR, AND_EXPR, ARRAY_LITERAL_EXPR, ARRAY_TYPE_EXPR,
ASSIGN_EXPR, AUTO_CAST_EXPR, BACKTICK_EXPR, BIT_AND_EXPR, ASSIGN_EXPR, AUTO_CAST_EXPR, BACKTICK_EXPR, BIT_AND_EXPR,
BIT_OR_EXPR, BIT_XOR_EXPR, BUILTIN_CALL_EXPR, CALL_EXPR, BIT_OR_EXPR, BIT_XOR_EXPR, BUILTIN_CALL_EXPR, CALL_EXPR,
CAST_EXPR, DEREF_EXPR, DIRECTIVE_EXPR, ENUM_EXPR, CAST_EXPR, DEREF_CAST_EXPR, DEREF_EXPR, DIRECTIVE_EXPR,
EQUALITY_EXPR, EXPR, IFX_EXPR, INDEX_EXPR, ENUM_EXPR, EQUALITY_EXPR, EXPR, IFX_EXPR,
INLINE_EXPR, INTERFACE_EXPR, LAMBDA_EXPR, LITERAL_EXPR, INDEX_EXPR, INLINE_EXPR, INTERFACE_EXPR, LAMBDA_EXPR,
MEMBER_EXPR, MUL_EXPR, OR_EXPR, PAREN_EXPR, LITERAL_EXPR, MEMBER_EXPR, MUL_EXPR, OR_EXPR,
PREFIX_EXPR, PRIMARY_EXPR, PROC_LITERAL_EXPR, RANGE_EXPR, PAREN_EXPR, PREFIX_EXPR, PRIMARY_EXPR, PROC_LITERAL_EXPR,
REF_EXPR, RELATIONAL_EXPR, SHIFT_EXPR, STRUCT_EXPR, RANGE_EXPR, REF_EXPR, RELATIONAL_EXPR, SHIFT_EXPR,
STRUCT_LITERAL_EXPR, TYPED_ARRAY_LITERAL_EXPR, TYPED_STRUCT_LITERAL_EXPR, UNARY_DOT_EXPR, STRUCT_EXPR, STRUCT_LITERAL_EXPR, TYPED_ARRAY_LITERAL_EXPR, TYPED_STRUCT_LITERAL_EXPR,
UNINITIALIZED_EXPR, UNION_EXPR), UNARY_DOT_EXPR, UNINITIALIZED_EXPR, UNION_EXPR),
}; };
/* ********************************************************** */ /* ********************************************************** */
@@ -326,31 +326,49 @@ public class JaiParser implements PsiParser, LightPsiParser {
} }
/* ********************************************************** */ /* ********************************************************** */
// <<dirPlain>> | 'using' // procModifier | 'using'
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_;
Marker marker_ = enter_section_(builder_); result_ = procModifier(builder_, level_ + 1);
result_ = dirPlain(builder_, level_ + 1);
if (!result_) result_ = consumeToken(builder_, KW_USING); if (!result_) result_ = consumeToken(builder_, KW_USING);
exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
/* ********************************************************** */ /* ********************************************************** */
// IDENT (',' IDENT)* // ['`'] IDENT
public static boolean declNames(PsiBuilder builder_, int level_) { public static boolean declName(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declNames")) return false; if (!recursion_guard_(builder_, level_, "declName")) return false;
if (!nextTokenIs(builder_, IDENT)) return false; if (!nextTokenIs(builder_, "<decl name>", BACKTICK, IDENT)) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_, level_, _NONE_, DECL_NAME, "<decl name>");
result_ = consumeToken(builder_, IDENT); result_ = declName_0(builder_, level_ + 1);
result_ = result_ && declNames_1(builder_, level_ + 1); result_ = result_ && consumeToken(builder_, IDENT);
exit_section_(builder_, marker_, DECL_NAMES, result_); exit_section_(builder_, level_, marker_, result_, false, null);
return result_; return result_;
} }
// (',' IDENT)* // ['`']
private static boolean declName_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declName_0")) return false;
consumeToken(builder_, BACKTICK);
return true;
}
/* ********************************************************** */
// declName (',' declName)*
public static boolean declNames(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declNames")) return false;
if (!nextTokenIs(builder_, "<decl names>", BACKTICK, IDENT)) return false;
boolean result_;
Marker marker_ = enter_section_(builder_, level_, _NONE_, DECL_NAMES, "<decl names>");
result_ = declName(builder_, level_ + 1);
result_ = result_ && declNames_1(builder_, level_ + 1);
exit_section_(builder_, level_, marker_, result_, false, null);
return result_;
}
// (',' declName)*
private static boolean declNames_1(PsiBuilder builder_, int level_) { private static boolean declNames_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declNames_1")) return false; if (!recursion_guard_(builder_, level_, "declNames_1")) return false;
while (true) { while (true) {
@@ -361,18 +379,19 @@ public class JaiParser implements PsiParser, LightPsiParser {
return true; return true;
} }
// ',' IDENT // ',' declName
private static boolean declNames_1_0(PsiBuilder builder_, int level_) { private static boolean declNames_1_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declNames_1_0")) return false; if (!recursion_guard_(builder_, level_, "declNames_1_0")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_);
result_ = consumeTokens(builder_, 0, COMMA, IDENT); result_ = consumeToken(builder_, COMMA);
result_ = result_ && declName(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
/* ********************************************************** */ /* ********************************************************** */
// ':' [<<exprNoAssign>>] [('=' | ':') initializer] // ':' [<<exprNoAssign>>] procModifier* [('=' | ':') initializer]
// | ':=' initializer // | ':=' initializer
// | '::' initializer // | '::' initializer
static boolean declTail_(PsiBuilder builder_, int level_) { static boolean declTail_(PsiBuilder builder_, int level_) {
@@ -386,7 +405,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
// ':' [<<exprNoAssign>>] [('=' | ':') initializer] // ':' [<<exprNoAssign>>] procModifier* [('=' | ':') initializer]
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_;
@@ -394,6 +413,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
result_ = consumeToken(builder_, COLON); result_ = consumeToken(builder_, COLON);
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);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
@@ -405,27 +425,38 @@ public class JaiParser implements PsiParser, LightPsiParser {
return true; return true;
} }
// [('=' | ':') initializer] // procModifier*
private static boolean declTail__0_2(PsiBuilder builder_, int level_) { private static boolean declTail__0_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declTail__0_2")) return false; if (!recursion_guard_(builder_, level_, "declTail__0_2")) return false;
declTail__0_2_0(builder_, level_ + 1); while (true) {
int pos_ = current_position_(builder_);
if (!procModifier(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "declTail__0_2", pos_)) break;
}
return true;
}
// [('=' | ':') initializer]
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; return true;
} }
// ('=' | ':') initializer // ('=' | ':') initializer
private static boolean declTail__0_2_0(PsiBuilder builder_, int level_) { private static boolean declTail__0_3_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declTail__0_2_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_2_0_0(builder_, level_ + 1); result_ = declTail__0_3_0_0(builder_, level_ + 1);
result_ = result_ && initializer(builder_, level_ + 1); result_ = result_ && initializer(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
// '=' | ':' // '=' | ':'
private static boolean declTail__0_2_0_0(PsiBuilder builder_, int level_) { private static boolean declTail__0_3_0_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declTail__0_2_0_0")) return false; if (!recursion_guard_(builder_, level_, "declTail__0_3_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);
@@ -455,7 +486,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
} }
/* ********************************************************** */ /* ********************************************************** */
// <<isDeclarationAhead>> declModifier_* declNames declTail_ NOTE* semi // <<isDeclarationAhead>> declModifier_* declNames declTail_ semiWithNotes_
public static boolean declaration(PsiBuilder builder_, int level_) { public static boolean declaration(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declaration")) return false; if (!recursion_guard_(builder_, level_, "declaration")) return false;
boolean result_; boolean result_;
@@ -464,8 +495,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
result_ = result_ && declaration_1(builder_, level_ + 1); result_ = result_ && declaration_1(builder_, level_ + 1);
result_ = result_ && declNames(builder_, level_ + 1); result_ = result_ && declNames(builder_, level_ + 1);
result_ = result_ && declTail_(builder_, level_ + 1); result_ = result_ && declTail_(builder_, level_ + 1);
result_ = result_ && declaration_4(builder_, level_ + 1); result_ = result_ && semiWithNotes_(builder_, level_ + 1);
result_ = result_ && semi(builder_, level_ + 1);
exit_section_(builder_, level_, marker_, result_, false, null); exit_section_(builder_, level_, marker_, result_, false, null);
return result_; return result_;
} }
@@ -481,17 +511,6 @@ public class JaiParser implements PsiParser, LightPsiParser {
return true; return true;
} }
// NOTE*
private static boolean declaration_4(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "declaration_4")) return false;
while (true) {
int pos_ = current_position_(builder_);
if (!consumeToken(builder_, NOTE)) break;
if (!empty_element_parsed_guard_(builder_, "declaration_4", pos_)) break;
}
return true;
}
/* ********************************************************** */ /* ********************************************************** */
// ['`'] 'defer' statement // ['`'] 'defer' statement
public static boolean deferStatement(PsiBuilder builder_, int level_) { public static boolean deferStatement(PsiBuilder builder_, int level_) {
@@ -514,10 +533,12 @@ public class JaiParser implements PsiParser, LightPsiParser {
} }
/* ********************************************************** */ /* ********************************************************** */
// <<dir "#assert">> expr [expr] // <<dir "#asm">> directiveFlag_* <<opaqueBlock>>
// | <<dirWithBlock>> [',' IDENT] block // | <<dir "#assert">> expr [expr]
// | <<dirWithOperand>> [',' IDENT] [expr] // | <<dir "#module_parameters">> '(' [paramList] ')' ['(' [paramList] ')'] [block]
// | <<dirPlain>> [',' IDENT] // | <<dirWithBlock>> directiveFlag_* block
// | <<dirWithOperand>> directiveFlag_* [expr]
// | <<dirPlain>> directiveFlag_*
public static boolean directiveExpr(PsiBuilder builder_, int level_) { public static boolean directiveExpr(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr")) return false;
boolean result_; boolean result_;
@@ -526,94 +547,198 @@ public class JaiParser implements PsiParser, LightPsiParser {
if (!result_) result_ = directiveExpr_1(builder_, level_ + 1); if (!result_) result_ = directiveExpr_1(builder_, level_ + 1);
if (!result_) result_ = directiveExpr_2(builder_, level_ + 1); if (!result_) result_ = directiveExpr_2(builder_, level_ + 1);
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_5(builder_, level_ + 1);
exit_section_(builder_, level_, marker_, result_, false, null); exit_section_(builder_, level_, marker_, result_, false, null);
return result_; return result_;
} }
// <<dir "#assert">> expr [expr] // <<dir "#asm">> directiveFlag_* <<opaqueBlock>>
private static boolean directiveExpr_0(PsiBuilder builder_, int level_) { private static boolean directiveExpr_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_0")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_0")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_);
result_ = dir(builder_, level_ + 1, "#asm");
result_ = result_ && directiveExpr_0_1(builder_, level_ + 1);
result_ = result_ && opaqueBlock(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// directiveFlag_*
private static boolean directiveExpr_0_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_0_1")) return false;
while (true) {
int pos_ = current_position_(builder_);
if (!directiveFlag_(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "directiveExpr_0_1", pos_)) break;
}
return true;
}
// <<dir "#assert">> expr [expr]
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_ = dir(builder_, level_ + 1, "#assert");
result_ = result_ && expr(builder_, level_ + 1, -1); result_ = result_ && expr(builder_, level_ + 1, -1);
result_ = result_ && directiveExpr_0_2(builder_, level_ + 1); result_ = result_ && directiveExpr_1_2(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
// [expr] // [expr]
private static boolean directiveExpr_0_2(PsiBuilder builder_, int level_) { private static boolean directiveExpr_1_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_0_2")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_1_2")) return false;
expr(builder_, level_ + 1, -1); expr(builder_, level_ + 1, -1);
return true; return true;
} }
// <<dirWithBlock>> [',' IDENT] block // <<dir "#module_parameters">> '(' [paramList] ')' ['(' [paramList] ')'] [block]
private static boolean directiveExpr_1(PsiBuilder builder_, int level_) { private static boolean directiveExpr_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_1")) return false; 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_ = 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);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// [paramList]
private static boolean directiveExpr_2_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_2_2")) return false;
paramList(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);
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
private static boolean directiveExpr_3(PsiBuilder builder_, int level_) {
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_ = dirWithBlock(builder_, level_ + 1);
result_ = result_ && directiveExpr_1_1(builder_, level_ + 1); result_ = result_ && directiveExpr_3_1(builder_, level_ + 1);
result_ = result_ && block(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_;
} }
// [',' IDENT] // directiveFlag_*
private static boolean directiveExpr_1_1(PsiBuilder builder_, int level_) { private static boolean directiveExpr_3_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_1_1")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_3_1")) return false;
parseTokens(builder_, 0, COMMA, IDENT); while (true) {
int pos_ = current_position_(builder_);
if (!directiveFlag_(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "directiveExpr_3_1", pos_)) break;
}
return true; return true;
} }
// <<dirWithOperand>> [',' IDENT] [expr] // <<dirWithOperand>> directiveFlag_* [expr]
private static boolean directiveExpr_2(PsiBuilder builder_, int level_) { private static boolean directiveExpr_4(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_2")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_4")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_);
result_ = dirWithOperand(builder_, level_ + 1); result_ = dirWithOperand(builder_, level_ + 1);
result_ = result_ && directiveExpr_2_1(builder_, level_ + 1); result_ = result_ && directiveExpr_4_1(builder_, level_ + 1);
result_ = result_ && directiveExpr_2_2(builder_, level_ + 1); result_ = result_ && directiveExpr_4_2(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
// [',' IDENT] // directiveFlag_*
private static boolean directiveExpr_2_1(PsiBuilder builder_, int level_) { private static boolean directiveExpr_4_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_2_1")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_4_1")) return false;
parseTokens(builder_, 0, COMMA, IDENT); while (true) {
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;
} }
// [expr] // [expr]
private static boolean directiveExpr_2_2(PsiBuilder builder_, int level_) { private static boolean directiveExpr_4_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_2_2")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_4_2")) return false;
expr(builder_, level_ + 1, -1); expr(builder_, level_ + 1, -1);
return true; return true;
} }
// <<dirPlain>> [',' IDENT] // <<dirPlain>> directiveFlag_*
private static boolean directiveExpr_3(PsiBuilder builder_, int level_) { private static boolean directiveExpr_5(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_3")) 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_ = dirPlain(builder_, level_ + 1);
result_ = result_ && directiveExpr_3_1(builder_, level_ + 1); result_ = result_ && directiveExpr_5_1(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_); exit_section_(builder_, marker_, null, result_);
return result_; return result_;
} }
// [',' IDENT] // directiveFlag_*
private static boolean directiveExpr_3_1(PsiBuilder builder_, int level_) { private static boolean directiveExpr_5_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveExpr_3_1")) return false; if (!recursion_guard_(builder_, level_, "directiveExpr_5_1")) return false;
parseTokens(builder_, 0, COMMA, IDENT); while (true) {
int pos_ = current_position_(builder_);
if (!directiveFlag_(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "directiveExpr_5_1", pos_)) break;
}
return true; return true;
} }
/* ********************************************************** */ /* ********************************************************** */
// <<dirBare>> [',' IDENT] [';'] // ',' IDENT
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_;
}
/* ********************************************************** */
// <<dirBare>> directiveFlag_* [';']
public static boolean directiveStatement(PsiBuilder builder_, int level_) { public static boolean directiveStatement(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveStatement")) return false; if (!recursion_guard_(builder_, level_, "directiveStatement")) return false;
boolean result_; boolean result_;
@@ -625,10 +750,14 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
// [',' IDENT] // directiveFlag_*
private static boolean directiveStatement_1(PsiBuilder builder_, int level_) { private static boolean directiveStatement_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "directiveStatement_1")) return false; if (!recursion_guard_(builder_, level_, "directiveStatement_1")) return false;
parseTokens(builder_, 0, COMMA, IDENT); while (true) {
int pos_ = current_position_(builder_);
if (!directiveFlag_(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "directiveStatement_1", pos_)) break;
}
return true; return true;
} }
@@ -716,15 +845,14 @@ public class JaiParser implements PsiParser, LightPsiParser {
} }
/* ********************************************************** */ /* ********************************************************** */
// expr (',' expr)* NOTE* semi // expr (',' expr)* semiWithNotes_
public static boolean expressionStatement(PsiBuilder builder_, int level_) { public static boolean expressionStatement(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "expressionStatement")) return false; if (!recursion_guard_(builder_, level_, "expressionStatement")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_, level_, _NONE_, EXPRESSION_STATEMENT, "<expression statement>"); Marker marker_ = enter_section_(builder_, level_, _NONE_, EXPRESSION_STATEMENT, "<expression statement>");
result_ = expr(builder_, level_ + 1, -1); result_ = expr(builder_, level_ + 1, -1);
result_ = result_ && expressionStatement_1(builder_, level_ + 1); result_ = result_ && expressionStatement_1(builder_, level_ + 1);
result_ = result_ && expressionStatement_2(builder_, level_ + 1); result_ = result_ && semiWithNotes_(builder_, level_ + 1);
result_ = result_ && semi(builder_, level_ + 1);
exit_section_(builder_, level_, marker_, result_, false, null); exit_section_(builder_, level_, marker_, result_, false, null);
return result_; return result_;
} }
@@ -751,17 +879,6 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
// NOTE*
private static boolean expressionStatement_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "expressionStatement_2")) return false;
while (true) {
int pos_ = current_position_(builder_);
if (!consumeToken(builder_, NOTE)) break;
if (!empty_element_parsed_guard_(builder_, "expressionStatement_2", pos_)) break;
}
return true;
}
/* ********************************************************** */ /* ********************************************************** */
// '<' | '*' // '<' | '*'
static boolean forModifier_(PsiBuilder builder_, int level_) { static boolean forModifier_(PsiBuilder builder_, int level_) {
@@ -1069,7 +1186,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
} }
/* ********************************************************** */ /* ********************************************************** */
// 'operator' operatorSymbol '::' expr NOTE* semi // 'operator' operatorSymbol '::' expr semiWithNotes_
public static boolean operatorDeclaration(PsiBuilder builder_, int level_) { public static boolean operatorDeclaration(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "operatorDeclaration")) return false; if (!recursion_guard_(builder_, level_, "operatorDeclaration")) return false;
if (!nextTokenIs(builder_, KW_OPERATOR)) return false; if (!nextTokenIs(builder_, KW_OPERATOR)) return false;
@@ -1079,23 +1196,11 @@ public class JaiParser implements PsiParser, LightPsiParser {
result_ = result_ && operatorSymbol(builder_, level_ + 1); result_ = result_ && operatorSymbol(builder_, level_ + 1);
result_ = result_ && consumeToken(builder_, COLON_COLON); result_ = result_ && consumeToken(builder_, COLON_COLON);
result_ = result_ && expr(builder_, level_ + 1, -1); result_ = result_ && expr(builder_, level_ + 1, -1);
result_ = result_ && operatorDeclaration_4(builder_, level_ + 1); result_ = result_ && semiWithNotes_(builder_, level_ + 1);
result_ = result_ && semi(builder_, level_ + 1);
exit_section_(builder_, marker_, OPERATOR_DECLARATION, result_); exit_section_(builder_, marker_, OPERATOR_DECLARATION, result_);
return result_; return result_;
} }
// NOTE*
private static boolean operatorDeclaration_4(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "operatorDeclaration_4")) return false;
while (true) {
int pos_ = current_position_(builder_);
if (!consumeToken(builder_, NOTE)) break;
if (!empty_element_parsed_guard_(builder_, "operatorDeclaration_4", pos_)) break;
}
return true;
}
/* ********************************************************** */ /* ********************************************************** */
// '+' | '-' | '*' | '/' | '%' | '==' | '!=' | '<' | '>' | '<=' | '>=' // '+' | '-' | '*' | '/' | '%' | '==' | '!=' | '<' | '>' | '<=' | '>='
// | '&' | '|' | '^' | '~' | '<<' | '>>' | '<<<' | '>>>' // | '&' | '|' | '^' | '~' | '<<' | '>>' | '<<<' | '>>>'
@@ -1171,6 +1276,18 @@ public class JaiParser implements PsiParser, LightPsiParser {
return true; return true;
} }
/* ********************************************************** */
// <<dirPlain>> | 'using'
static boolean paramModifier_(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "paramModifier_")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = dirPlain(builder_, level_ + 1);
if (!result_) result_ = consumeToken(builder_, KW_USING);
exit_section_(builder_, marker_, null, result_);
return result_;
}
/* ********************************************************** */ /* ********************************************************** */
// ['$' | '$$'] IDENT // ['$' | '$$'] IDENT
public static boolean paramName(PsiBuilder builder_, int level_) { public static boolean paramName(PsiBuilder builder_, int level_) {
@@ -1308,7 +1425,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
} }
/* ********************************************************** */ /* ********************************************************** */
// ['using'] parameterTail_ // paramModifier_* parameterTail_
public static boolean parameter(PsiBuilder builder_, int level_) { public static boolean parameter(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "parameter")) return false; if (!recursion_guard_(builder_, level_, "parameter")) return false;
boolean result_; boolean result_;
@@ -1319,10 +1436,14 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
// ['using'] // paramModifier_*
private static boolean parameter_0(PsiBuilder builder_, int level_) { private static boolean parameter_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "parameter_0")) return false; if (!recursion_guard_(builder_, level_, "parameter_0")) return false;
consumeToken(builder_, KW_USING); while (true) {
int pos_ = current_position_(builder_);
if (!paramModifier_(builder_, level_ + 1)) break;
if (!empty_element_parsed_guard_(builder_, "parameter_0", pos_)) break;
}
return true; return true;
} }
@@ -1527,9 +1648,9 @@ public class JaiParser implements PsiParser, LightPsiParser {
} }
/* ********************************************************** */ /* ********************************************************** */
// <<dirWithBlock>> block // <<dirWithBlock>> directiveFlag_* block
// | <<dirWithOperand>> [',' IDENT] [expr] // | <<dirWithOperand>> directiveFlag_* [expr]
// | <<dirPlain>> [',' IDENT] // | <<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_;
@@ -1541,18 +1662,30 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
// <<dirWithBlock>> block // <<dirWithBlock>> directiveFlag_* block
private static boolean procModifier_0(PsiBuilder builder_, int level_) { private static boolean procModifier_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "procModifier_0")) return false; if (!recursion_guard_(builder_, level_, "procModifier_0")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_);
result_ = dirWithBlock(builder_, level_ + 1); result_ = dirWithBlock(builder_, level_ + 1);
result_ = result_ && procModifier_0_1(builder_, level_ + 1);
result_ = result_ && block(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_;
} }
// <<dirWithOperand>> [',' IDENT] [expr] // 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_) { private static boolean procModifier_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "procModifier_1")) return false; if (!recursion_guard_(builder_, level_, "procModifier_1")) return false;
boolean result_; boolean result_;
@@ -1564,10 +1697,14 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
// [',' IDENT] // directiveFlag_*
private static boolean procModifier_1_1(PsiBuilder builder_, int level_) { private static boolean procModifier_1_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "procModifier_1_1")) return false; if (!recursion_guard_(builder_, level_, "procModifier_1_1")) return false;
parseTokens(builder_, 0, COMMA, IDENT); 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; return true;
} }
@@ -1578,7 +1715,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
return true; return true;
} }
// <<dirPlain>> [',' IDENT] // <<dirPlain>> directiveFlag_*
private static boolean procModifier_2(PsiBuilder builder_, int level_) { private static boolean procModifier_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "procModifier_2")) return false; if (!recursion_guard_(builder_, level_, "procModifier_2")) return false;
boolean result_; boolean result_;
@@ -1589,10 +1726,14 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
// [',' IDENT] // directiveFlag_*
private static boolean procModifier_2_1(PsiBuilder builder_, int level_) { private static boolean procModifier_2_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "procModifier_2_1")) return false; if (!recursion_guard_(builder_, level_, "procModifier_2_1")) return false;
parseTokens(builder_, 0, COMMA, IDENT); 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; return true;
} }
@@ -1706,14 +1847,13 @@ public class JaiParser implements PsiParser, LightPsiParser {
} }
/* ********************************************************** */ /* ********************************************************** */
// [<<isParamNameAhead>> IDENT ':'] <<exprNoAssign>> ['=' initializer] // [<<isParamNameAhead>> IDENT ':'] <<exprNoAssign>>
public static boolean returnItem(PsiBuilder builder_, int level_) { public static boolean returnItem(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "returnItem")) return false; if (!recursion_guard_(builder_, level_, "returnItem")) return false;
boolean result_; boolean result_;
Marker marker_ = enter_section_(builder_, level_, _NONE_, RETURN_ITEM, "<return item>"); Marker marker_ = enter_section_(builder_, level_, _NONE_, RETURN_ITEM, "<return item>");
result_ = returnItem_0(builder_, level_ + 1); result_ = returnItem_0(builder_, level_ + 1);
result_ = result_ && exprNoAssign(builder_, level_ + 1); result_ = result_ && exprNoAssign(builder_, level_ + 1);
result_ = result_ && returnItem_2(builder_, level_ + 1);
exit_section_(builder_, level_, marker_, result_, false, null); exit_section_(builder_, level_, marker_, result_, false, null);
return result_; return result_;
} }
@@ -1736,26 +1876,8 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
// ['=' initializer]
private static boolean returnItem_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "returnItem_2")) return false;
returnItem_2_0(builder_, level_ + 1);
return true;
}
// '=' initializer
private static boolean returnItem_2_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "returnItem_2_0")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = consumeToken(builder_, EQ);
result_ = result_ && initializer(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
/* ********************************************************** */ /* ********************************************************** */
// 'return' [expr (',' expr)*] NOTE* semi // 'return' [expr (',' expr)*] semiWithNotes_
public static boolean returnStatement(PsiBuilder builder_, int level_) { public static boolean returnStatement(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "returnStatement")) return false; if (!recursion_guard_(builder_, level_, "returnStatement")) return false;
if (!nextTokenIs(builder_, KW_RETURN)) return false; if (!nextTokenIs(builder_, KW_RETURN)) return false;
@@ -1763,8 +1885,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
Marker marker_ = enter_section_(builder_); Marker marker_ = enter_section_(builder_);
result_ = consumeToken(builder_, KW_RETURN); result_ = consumeToken(builder_, KW_RETURN);
result_ = result_ && returnStatement_1(builder_, level_ + 1); result_ = result_ && returnStatement_1(builder_, level_ + 1);
result_ = result_ && returnStatement_2(builder_, level_ + 1); result_ = result_ && semiWithNotes_(builder_, level_ + 1);
result_ = result_ && semi(builder_, level_ + 1);
exit_section_(builder_, marker_, RETURN_STATEMENT, result_); exit_section_(builder_, marker_, RETURN_STATEMENT, result_);
return result_; return result_;
} }
@@ -1809,17 +1930,6 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
// NOTE*
private static boolean returnStatement_2(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "returnStatement_2")) return false;
while (true) {
int pos_ = current_position_(builder_);
if (!consumeToken(builder_, NOTE)) break;
if (!empty_element_parsed_guard_(builder_, "returnStatement_2", pos_)) break;
}
return true;
}
/* ********************************************************** */ /* ********************************************************** */
// <<isReturnGroupAhead>> returnGroup | returnItem (',' returnItem)* // <<isReturnGroupAhead>> returnGroup | returnItem (',' returnItem)*
static boolean returnTypes_(PsiBuilder builder_, int level_) { static boolean returnTypes_(PsiBuilder builder_, int level_) {
@@ -1888,6 +1998,62 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
/* ********************************************************** */
// <<prevEndsConstruct>> NOTE* | NOTE* ';'
static boolean semiWithNotes_(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "semiWithNotes_")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = semiWithNotes__0(builder_, level_ + 1);
if (!result_) result_ = semiWithNotes__1(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// <<prevEndsConstruct>> NOTE*
private static boolean semiWithNotes__0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "semiWithNotes__0")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = prevEndsConstruct(builder_, level_ + 1);
result_ = result_ && semiWithNotes__0_1(builder_, level_ + 1);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// NOTE*
private static boolean semiWithNotes__0_1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "semiWithNotes__0_1")) return false;
while (true) {
int pos_ = current_position_(builder_);
if (!consumeToken(builder_, NOTE)) break;
if (!empty_element_parsed_guard_(builder_, "semiWithNotes__0_1", pos_)) break;
}
return true;
}
// NOTE* ';'
private static boolean semiWithNotes__1(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "semiWithNotes__1")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_);
result_ = semiWithNotes__1_0(builder_, level_ + 1);
result_ = result_ && consumeToken(builder_, SEMICOLON);
exit_section_(builder_, marker_, null, result_);
return result_;
}
// NOTE*
private static boolean semiWithNotes__1_0(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "semiWithNotes__1_0")) return false;
while (true) {
int pos_ = current_position_(builder_);
if (!consumeToken(builder_, NOTE)) break;
if (!empty_element_parsed_guard_(builder_, "semiWithNotes__1_0", pos_)) break;
}
return true;
}
/* ********************************************************** */ /* ********************************************************** */
// ';' // ';'
// | block // | block
@@ -1903,8 +2069,8 @@ public class JaiParser implements PsiParser, LightPsiParser {
// | operatorDeclaration // | operatorDeclaration
// | usingStatement // | usingStatement
// | noteStatement // | noteStatement
// | directiveStatement
// | declaration // | declaration
// | directiveStatement
// | expressionStatement // | expressionStatement
public static boolean statement(PsiBuilder builder_, int level_) { public static boolean statement(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "statement")) return false; if (!recursion_guard_(builder_, level_, "statement")) return false;
@@ -1924,8 +2090,8 @@ public class JaiParser implements PsiParser, LightPsiParser {
if (!result_) result_ = operatorDeclaration(builder_, level_ + 1); if (!result_) result_ = operatorDeclaration(builder_, level_ + 1);
if (!result_) result_ = usingStatement(builder_, level_ + 1); if (!result_) result_ = usingStatement(builder_, level_ + 1);
if (!result_) result_ = noteStatement(builder_, level_ + 1); if (!result_) result_ = noteStatement(builder_, level_ + 1);
if (!result_) result_ = directiveStatement(builder_, level_ + 1);
if (!result_) result_ = declaration(builder_, level_ + 1); if (!result_) result_ = declaration(builder_, level_ + 1);
if (!result_) result_ = directiveStatement(builder_, level_ + 1);
if (!result_) result_ = expressionStatement(builder_, level_ + 1); if (!result_) result_ = expressionStatement(builder_, level_ + 1);
exit_section_(builder_, level_, marker_, result_, false, null); exit_section_(builder_, level_, marker_, result_, false, null);
return result_; return result_;
@@ -2169,24 +2335,26 @@ public class JaiParser implements PsiParser, LightPsiParser {
// 11: BINARY(addExpr) // 11: BINARY(addExpr)
// 12: BINARY(mulExpr) // 12: BINARY(mulExpr)
// 13: PREFIX(prefixExpr) // 13: PREFIX(prefixExpr)
// 14: ATOM(arrayTypeExpr) // 14: PREFIX(derefCastExpr)
// 15: ATOM(castExpr) // 15: ATOM(arrayTypeExpr)
// 16: PREFIX(autoCastExpr) // 16: ATOM(castExpr)
// 17: PREFIX(inlineExpr) // 17: PREFIX(autoCastExpr)
// 18: ATOM(ifxExpr) // 18: PREFIX(inlineExpr)
// 19: POSTFIX(callExpr) // 19: ATOM(ifxExpr)
// 20: POSTFIX(indexExpr) // 20: POSTFIX(callExpr)
// 21: POSTFIX(memberExpr) // 21: POSTFIX(indexExpr)
// 22: POSTFIX(derefExpr) // 22: POSTFIX(memberExpr)
// 23: POSTFIX(typedStructLiteralExpr) // 23: POSTFIX(derefExpr)
// 24: POSTFIX(typedArrayLiteralExpr) // 24: POSTFIX(typedStructLiteralExpr)
// 25: ATOM(primaryExpr) // 25: POSTFIX(typedArrayLiteralExpr)
// 26: ATOM(primaryExpr)
public static boolean expr(PsiBuilder builder_, int level_, int priority_) { public static boolean expr(PsiBuilder builder_, int level_, int priority_) {
if (!recursion_guard_(builder_, level_, "expr")) return false; if (!recursion_guard_(builder_, level_, "expr")) return false;
addVariant(builder_, "<expr>"); addVariant(builder_, "<expr>");
boolean result_, pinned_; boolean result_, pinned_;
Marker marker_ = enter_section_(builder_, level_, _NONE_, "<expr>"); Marker marker_ = enter_section_(builder_, level_, _NONE_, "<expr>");
result_ = prefixExpr(builder_, level_ + 1); result_ = prefixExpr(builder_, level_ + 1);
if (!result_) result_ = derefCastExpr(builder_, level_ + 1);
if (!result_) result_ = arrayTypeExpr(builder_, level_ + 1); if (!result_) result_ = arrayTypeExpr(builder_, level_ + 1);
if (!result_) result_ = castExpr(builder_, level_ + 1); if (!result_) result_ = castExpr(builder_, level_ + 1);
if (!result_) result_ = autoCastExpr(builder_, level_ + 1); if (!result_) result_ = autoCastExpr(builder_, level_ + 1);
@@ -2256,27 +2424,27 @@ public class JaiParser implements PsiParser, LightPsiParser {
result_ = expr(builder_, level_, 12); result_ = expr(builder_, level_, 12);
exit_section_(builder_, level_, marker_, MUL_EXPR, result_, true, null); exit_section_(builder_, level_, marker_, MUL_EXPR, result_, true, null);
} }
else if (priority_ < 19 && callExpr_0(builder_, level_ + 1)) { else if (priority_ < 20 && callExpr_0(builder_, level_ + 1)) {
result_ = true; result_ = true;
exit_section_(builder_, level_, marker_, CALL_EXPR, result_, true, null); exit_section_(builder_, level_, marker_, CALL_EXPR, result_, true, null);
} }
else if (priority_ < 20 && indexExpr_0(builder_, level_ + 1)) { else if (priority_ < 21 && indexExpr_0(builder_, level_ + 1)) {
result_ = true; result_ = true;
exit_section_(builder_, level_, marker_, INDEX_EXPR, result_, true, null); exit_section_(builder_, level_, marker_, INDEX_EXPR, result_, true, null);
} }
else if (priority_ < 21 && memberExpr_0(builder_, level_ + 1)) { else if (priority_ < 22 && memberExpr_0(builder_, level_ + 1)) {
result_ = true; result_ = true;
exit_section_(builder_, level_, marker_, MEMBER_EXPR, result_, true, null); exit_section_(builder_, level_, marker_, MEMBER_EXPR, result_, true, null);
} }
else if (priority_ < 22 && consumeTokenSmart(builder_, POSTFIX_DEREFERENCE)) { else if (priority_ < 23 && consumeTokenSmart(builder_, POSTFIX_DEREFERENCE)) {
result_ = true; result_ = true;
exit_section_(builder_, level_, marker_, DEREF_EXPR, result_, true, null); exit_section_(builder_, level_, marker_, DEREF_EXPR, result_, true, null);
} }
else if (priority_ < 23 && typedStructLiteralExpr_0(builder_, level_ + 1)) { else if (priority_ < 24 && typedStructLiteralExpr_0(builder_, level_ + 1)) {
result_ = true; result_ = true;
exit_section_(builder_, level_, marker_, TYPED_STRUCT_LITERAL_EXPR, result_, true, null); exit_section_(builder_, level_, marker_, TYPED_STRUCT_LITERAL_EXPR, result_, true, null);
} }
else if (priority_ < 24 && typedArrayLiteralExpr_0(builder_, level_ + 1)) { else if (priority_ < 25 && typedArrayLiteralExpr_0(builder_, level_ + 1)) {
result_ = true; result_ = true;
exit_section_(builder_, level_, marker_, TYPED_ARRAY_LITERAL_EXPR, result_, true, null); exit_section_(builder_, level_, marker_, TYPED_ARRAY_LITERAL_EXPR, result_, true, null);
} }
@@ -2352,6 +2520,18 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_ || pinned_; return result_ || pinned_;
} }
public static boolean derefCastExpr(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "derefCastExpr")) return false;
if (!nextTokenIsSmart(builder_, LPAREN)) return false;
boolean result_, pinned_;
Marker marker_ = enter_section_(builder_, level_, _NONE_, null);
result_ = parseTokensSmart(builder_, 0, LPAREN, POSTFIX_DEREFERENCE, RPAREN);
pinned_ = result_;
result_ = pinned_ && expr(builder_, level_, 14);
exit_section_(builder_, level_, marker_, DEREF_CAST_EXPR, result_, pinned_, null);
return result_ || pinned_;
}
// '[' ['..' | expr] ']' expr // '[' ['..' | expr] ']' expr
public static boolean arrayTypeExpr(PsiBuilder builder_, int level_) { public static boolean arrayTypeExpr(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "arrayTypeExpr")) return false; if (!recursion_guard_(builder_, level_, "arrayTypeExpr")) return false;
@@ -2419,7 +2599,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
Marker marker_ = enter_section_(builder_, level_, _NONE_, null); Marker marker_ = enter_section_(builder_, level_, _NONE_, null);
result_ = autoCastExpr_0(builder_, level_ + 1); result_ = autoCastExpr_0(builder_, level_ + 1);
pinned_ = result_; pinned_ = result_;
result_ = pinned_ && expr(builder_, level_, 16); result_ = pinned_ && expr(builder_, level_, 17);
exit_section_(builder_, level_, marker_, AUTO_CAST_EXPR, result_, pinned_, null); exit_section_(builder_, level_, marker_, AUTO_CAST_EXPR, result_, pinned_, null);
return result_ || pinned_; return result_ || pinned_;
} }
@@ -2449,7 +2629,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
Marker marker_ = enter_section_(builder_, level_, _NONE_, null); Marker marker_ = enter_section_(builder_, level_, _NONE_, null);
result_ = inlineExpr_0(builder_, level_ + 1); result_ = inlineExpr_0(builder_, level_ + 1);
pinned_ = result_; pinned_ = result_;
result_ = pinned_ && expr(builder_, level_, 17); result_ = pinned_ && expr(builder_, level_, 18);
exit_section_(builder_, level_, marker_, INLINE_EXPR, result_, pinned_, null); exit_section_(builder_, level_, marker_, INLINE_EXPR, result_, pinned_, null);
return result_ || pinned_; return result_ || pinned_;
} }
@@ -2463,7 +2643,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
return result_; return result_;
} }
// 'ifx' expr ['then'] expr ['else' expr] // 'ifx' expr ['then'] [expr] ['else' expr]
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; if (!nextTokenIsSmart(builder_, KW_IFX)) return false;
@@ -2472,7 +2652,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
result_ = consumeTokenSmart(builder_, KW_IFX); result_ = consumeTokenSmart(builder_, KW_IFX);
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_ && expr(builder_, level_ + 1, -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_, marker_, IFX_EXPR, result_);
return result_; return result_;
@@ -2485,6 +2665,13 @@ public class JaiParser implements PsiParser, LightPsiParser {
return true; return true;
} }
// [expr]
private static boolean ifxExpr_3(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "ifxExpr_3")) return false;
expr(builder_, level_ + 1, -1);
return true;
}
// ['else' expr] // ['else' expr]
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;

View File

@@ -0,0 +1,10 @@
// 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 JaiDeclName extends PsiElement {
}

View File

@@ -7,4 +7,7 @@ import com.intellij.psi.PsiElement;
public interface JaiDeclNames extends PsiElement { public interface JaiDeclNames extends PsiElement {
@NotNull
List<JaiDeclName> getDeclNameList();
} }

View File

@@ -13,4 +13,7 @@ public interface JaiDeclaration extends PsiElement {
@Nullable @Nullable
JaiInitializer getInitializer(); JaiInitializer getInitializer();
@NotNull
List<JaiProcModifier> getProcModifierList();
} }

View File

@@ -0,0 +1,13 @@
// 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 JaiDerefCastExpr extends JaiExpr {
@Nullable
JaiExpr getExpr();
}

View File

@@ -13,4 +13,7 @@ public interface JaiDirectiveExpr extends JaiExpr {
@NotNull @NotNull
List<JaiExpr> getExprList(); List<JaiExpr> getExprList();
@NotNull
List<JaiParameter> getParameterList();
} }

View File

@@ -7,7 +7,4 @@ import com.intellij.psi.PsiElement;
public interface JaiReturnItem extends PsiElement { public interface JaiReturnItem extends PsiElement {
@Nullable
JaiInitializer getInitializer();
} }

View File

@@ -28,8 +28,10 @@ public interface JaiTypes {
IElementType CAST_EXPR = new JaiElementType("CAST_EXPR"); IElementType CAST_EXPR = new JaiElementType("CAST_EXPR");
IElementType CONTINUE_STATEMENT = new JaiElementType("CONTINUE_STATEMENT"); IElementType CONTINUE_STATEMENT = new JaiElementType("CONTINUE_STATEMENT");
IElementType DECLARATION = new JaiElementType("DECLARATION"); IElementType DECLARATION = new JaiElementType("DECLARATION");
IElementType DECL_NAME = new JaiElementType("DECL_NAME");
IElementType DECL_NAMES = new JaiElementType("DECL_NAMES"); IElementType DECL_NAMES = new JaiElementType("DECL_NAMES");
IElementType DEFER_STATEMENT = new JaiElementType("DEFER_STATEMENT"); IElementType DEFER_STATEMENT = new JaiElementType("DEFER_STATEMENT");
IElementType DEREF_CAST_EXPR = new JaiElementType("DEREF_CAST_EXPR");
IElementType DEREF_EXPR = new JaiElementType("DEREF_EXPR"); IElementType DEREF_EXPR = new JaiElementType("DEREF_EXPR");
IElementType DIRECTIVE_EXPR = new JaiElementType("DIRECTIVE_EXPR"); IElementType DIRECTIVE_EXPR = new JaiElementType("DIRECTIVE_EXPR");
IElementType DIRECTIVE_STATEMENT = new JaiElementType("DIRECTIVE_STATEMENT"); IElementType DIRECTIVE_STATEMENT = new JaiElementType("DIRECTIVE_STATEMENT");
@@ -253,12 +255,18 @@ public interface JaiTypes {
else if (type == DECLARATION) { else if (type == DECLARATION) {
return new JaiDeclarationImpl(node); return new JaiDeclarationImpl(node);
} }
else if (type == DECL_NAME) {
return new JaiDeclNameImpl(node);
}
else if (type == DECL_NAMES) { else if (type == DECL_NAMES) {
return new JaiDeclNamesImpl(node); return new JaiDeclNamesImpl(node);
} }
else if (type == DEFER_STATEMENT) { else if (type == DEFER_STATEMENT) {
return new JaiDeferStatementImpl(node); return new JaiDeferStatementImpl(node);
} }
else if (type == DEREF_CAST_EXPR) {
return new JaiDerefCastExprImpl(node);
}
else if (type == DEREF_EXPR) { else if (type == DEREF_EXPR) {
return new JaiDerefExprImpl(node); return new JaiDerefExprImpl(node);
} }

View File

@@ -79,6 +79,10 @@ public class JaiVisitor extends PsiElementVisitor {
visitPsiElement(o); visitPsiElement(o);
} }
public void visitDeclName(@NotNull JaiDeclName o) {
visitPsiElement(o);
}
public void visitDeclNames(@NotNull JaiDeclNames o) { public void visitDeclNames(@NotNull JaiDeclNames o) {
visitPsiElement(o); visitPsiElement(o);
} }
@@ -91,6 +95,10 @@ public class JaiVisitor extends PsiElementVisitor {
visitPsiElement(o); visitPsiElement(o);
} }
public void visitDerefCastExpr(@NotNull JaiDerefCastExpr o) {
visitExpr(o);
}
public void visitDerefExpr(@NotNull JaiDerefExpr o) { public void visitDerefExpr(@NotNull JaiDerefExpr o) {
visitExpr(o); visitExpr(o);
} }

View File

@@ -0,0 +1,30 @@
// 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 JaiDeclNameImpl extends ASTWrapperPsiElement implements JaiDeclName {
public JaiDeclNameImpl(@NotNull ASTNode node) {
super(node);
}
public void accept(@NotNull JaiVisitor visitor) {
visitor.visitDeclName(this);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JaiVisitor) accept((JaiVisitor)visitor);
else super.accept(visitor);
}
}

View File

@@ -27,4 +27,10 @@ public class JaiDeclNamesImpl extends ASTWrapperPsiElement implements JaiDeclNam
else super.accept(visitor); else super.accept(visitor);
} }
@Override
@NotNull
public List<JaiDeclName> getDeclNameList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiDeclName.class);
}
} }

View File

@@ -39,4 +39,10 @@ public class JaiDeclarationImpl extends ASTWrapperPsiElement implements JaiDecla
return findChildByClass(JaiInitializer.class); return findChildByClass(JaiInitializer.class);
} }
@Override
@NotNull
public List<JaiProcModifier> getProcModifierList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiProcModifier.class);
}
} }

View File

@@ -0,0 +1,36 @@
// 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 dev.hgh.jai.psi.*;
public class JaiDerefCastExprImpl extends JaiExprImpl implements JaiDerefCastExpr {
public JaiDerefCastExprImpl(@NotNull ASTNode node) {
super(node);
}
@Override
public void accept(@NotNull JaiVisitor visitor) {
visitor.visitDerefCastExpr(this);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JaiVisitor) accept((JaiVisitor)visitor);
else super.accept(visitor);
}
@Override
@Nullable
public JaiExpr getExpr() {
return findChildByClass(JaiExpr.class);
}
}

View File

@@ -39,4 +39,10 @@ public class JaiDirectiveExprImpl extends JaiExprImpl implements JaiDirectiveExp
return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiExpr.class); return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiExpr.class);
} }
@Override
@NotNull
public List<JaiParameter> getParameterList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiParameter.class);
}
} }

View File

@@ -27,10 +27,4 @@ public class JaiReturnItemImpl extends ASTWrapperPsiElement implements JaiReturn
else super.accept(visitor); else super.accept(visitor);
} }
@Override
@Nullable
public JaiInitializer getInitializer() {
return findChildByClass(JaiInitializer.class);
}
} }

View File

@@ -156,8 +156,8 @@ statement ::= ';'
| operatorDeclaration | operatorDeclaration
| usingStatement | usingStatement
| noteStatement | noteStatement
| directiveStatement
| declaration | declaration
| directiveStatement
| expressionStatement | expressionStatement
block ::= '{' statement* '}' block ::= '{' statement* '}'
@@ -167,13 +167,17 @@ block ::= '{' statement* '}'
// `BODY :: #string DONE … DONE`. `x := 1` still needs one. // `BODY :: #string DONE … DONE`. `x := 1` still needs one.
private semi ::= ';' | <<prevEndsConstruct>> private semi ::= ';' | <<prevEndsConstruct>>
// Notes attach to the end of a declaration or statement. `<<prevEndsConstruct>>` has
// to be checked *before* the notes, because `} @NoProfile` ends at the `}`.
private semiWithNotes_ ::= <<prevEndsConstruct>> NOTE* | NOTE* ';'
noteStatement ::= NOTE+ noteStatement ::= NOTE+
// `#scope_file`, `#no_padding`, `#placeholder foo` … a directive that takes no operand // `#scope_file`, `#no_padding`, `#placeholder foo` … a directive that takes no operand
// is a statement on its own and carries no `;`. Directives that *do* take an operand // is a statement on its own and carries no `;`. Directives that *do* take an operand
// (`#run f()`, `#import "Basic"`) fall through to expressionStatement, which requires // (`#run f()`, `#import "Basic"`) fall through to expressionStatement, which requires
// one. // one.
directiveStatement ::= <<dirBare>> [',' IDENT] [';'] directiveStatement ::= <<dirBare>> directiveFlag_* [';']
// `#if` is spelled as a directive but is structurally an `if`, and it pairs with the // `#if` is spelled as a directive but is structurally an `if`, and it pairs with the
// ordinary `else` keyword (see modules/File_Watcher/module.jai). // ordinary `else` keyword (see modules/File_Watcher/module.jai).
@@ -194,7 +198,7 @@ forStatement ::= 'for' [':' expr] forModifier_* [<<isForNamesAhead>> forNames ':
private forModifier_ ::= '<' | '*' private forModifier_ ::= '<' | '*'
forNames ::= IDENT (',' IDENT)* forNames ::= IDENT (',' IDENT)*
returnStatement ::= 'return' [expr (',' expr)*] NOTE* semi returnStatement ::= 'return' [expr (',' expr)*] semiWithNotes_
breakStatement ::= 'break' [IDENT] semi breakStatement ::= 'break' [IDENT] semi
continueStatement ::= 'continue' [IDENT] semi continueStatement ::= 'continue' [IDENT] semi
removeStatement ::= 'remove' [expr] semi removeStatement ::= 'remove' [expr] semi
@@ -202,23 +206,25 @@ 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)* NOTE* semi expressionStatement ::= expr (',' expr)* semiWithNotes_
// ------------------------------------------------------------------- declarations // ------------------------------------------------------------------- declarations
// Jai has no declaration keyword: `a : int = 1`, `a := 1`, `a :: 1`, `Foo :: struct {}` // Jai has no declaration keyword: `a : int = 1`, `a := 1`, `a :: 1`, `Foo :: struct {}`
// 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_ NOTE* semi declaration ::= <<isDeclarationAhead>> declModifier_* declNames declTail_ semiWithNotes_
private declModifier_ ::= <<dirPlain>> | 'using' // `#as using base: Document;`, `#overlay (unknown.vtable) using vtable: *Vtable;`
declNames ::= IDENT (',' IDENT)* private declModifier_ ::= procModifier | 'using'
private declTail_ ::= ':' [<<exprNoAssign>>] [('=' | ':') initializer] declNames ::= declName (',' declName)*
declName ::= ['`'] IDENT
private declTail_ ::= ':' [<<exprNoAssign>>] procModifier* [('=' | ':') initializer]
| ':=' initializer | ':=' initializer
| '::' initializer | '::' initializer
initializer ::= '---' | expr initializer ::= '---' | expr
// `operator + :: (a: T, b: T) -> T { }` // `operator + :: (a: T, b: T) -> T { }`
operatorDeclaration ::= 'operator' operatorSymbol '::' expr NOTE* semi operatorDeclaration ::= 'operator' operatorSymbol '::' expr semiWithNotes_
operatorSymbol ::= '+' | '-' | '*' | '/' | '%' | '==' | '!=' | '<' | '>' | '<=' | '>=' operatorSymbol ::= '+' | '-' | '*' | '/' | '%' | '==' | '!=' | '<' | '>' | '<=' | '>='
| '&' | '|' | '^' | '~' | '<<' | '>>' | '<<<' | '>>>' | '&' | '|' | '^' | '~' | '<<' | '>>' | '<<<' | '>>>'
| '[' ']' | '[' ']' '=' | '[' ']' | '[' ']' '='
@@ -239,6 +245,7 @@ expr ::= assignExpr
| addExpr | addExpr
| mulExpr | mulExpr
| prefixExpr | prefixExpr
| derefCastExpr
| arrayTypeExpr | arrayTypeExpr
| castExpr | castExpr
| autoCastExpr | autoCastExpr
@@ -279,10 +286,14 @@ private prefixOp_ ::= '-' | '+' | '!' | '~' | '*' | '..' | '$' | '$$' | '<<' | '
// element type. Distinct from indexExpr, which needs a left operand. // element type. Distinct from indexExpr, which needs a left operand.
arrayTypeExpr ::= '[' ['..' | expr] ']' expr arrayTypeExpr ::= '[' ['..' | expr] ']' expr
// `(.*) cast(*u32) p` — the postfix dereference written prefix-style in parentheses
// (modules/Shared_Memory_Channel/module.jai:113).
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 ::= 'ifx' expr ['then'] [expr] ['else' expr]
callExpr ::= expr '(' [argList] ')' callExpr ::= expr '(' [argList] ')'
indexExpr ::= expr '[' [expr] ']' indexExpr ::= expr '[' [expr] ']'
@@ -339,7 +350,8 @@ procLiteralExpr ::= <<isProcHeaderAhead>> '(' [paramList] ')' ['->' returnTypes_
| '->' returnTypes_ procModifier* [block] | '->' returnTypes_ procModifier* [block]
private paramList ::= parameter (',' parameter)* [','] private paramList ::= parameter (',' parameter)* [',']
parameter ::= ['using'] parameterTail_ parameter ::= paramModifier_* parameterTail_
private paramModifier_ ::= <<dirPlain>> | 'using'
private parameterTail_ ::= <<isParamNameAhead>> paramNames paramTypeTail_ | '..' | expr private parameterTail_ ::= <<isParamNameAhead>> paramNames paramTypeTail_ | '..' | expr
paramNames ::= paramName (',' paramName)* paramNames ::= paramName (',' paramName)*
paramName ::= ['$' | '$$'] IDENT paramName ::= ['$' | '$$'] IDENT
@@ -349,12 +361,12 @@ private paramTypeTail_ ::= ':' [<<exprNoAssign>>] ['=' initializer]
private returnTypes_ ::= <<isReturnGroupAhead>> returnGroup | returnItem (',' returnItem)* private returnTypes_ ::= <<isReturnGroupAhead>> returnGroup | returnItem (',' returnItem)*
returnGroup ::= '(' [returnItem (',' returnItem)*] ')' returnGroup ::= '(' [returnItem (',' returnItem)*] ')'
returnItem ::= [<<isParamNameAhead>> IDENT ':'] <<exprNoAssign>> ['=' initializer] returnItem ::= [<<isParamNameAhead>> IDENT ':'] <<exprNoAssign>>
// `#foreign lib`, `#modify { ... }`, `#c_call`, `#expand`, … // `#foreign lib`, `#modify { ... }`, `#c_call`, `#expand`, …
procModifier ::= <<dirWithBlock>> block procModifier ::= <<dirWithBlock>> directiveFlag_* block
| <<dirWithOperand>> [',' IDENT] [expr] | <<dirWithOperand>> directiveFlag_* [expr]
| <<dirPlain>> [',' IDENT] | <<dirPlain>> directiveFlag_*
structExpr ::= 'struct' ['(' [paramList] ')'] structModifier_* block structExpr ::= 'struct' ['(' [paramList] ')'] structModifier_* block
enumExpr ::= ('enum' | 'enum_flags') [!'{' expr] structModifier_* block enumExpr ::= ('enum' | 'enum_flags') [!'{' expr] structModifier_* block
@@ -365,7 +377,13 @@ private structModifier_ ::= procModifier
// `#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.
directiveExpr ::= <<dir "#assert">> expr [expr] directiveExpr ::= <<dir "#asm">> directiveFlag_* <<opaqueBlock>>
| <<dirWithBlock>> [',' IDENT] block | <<dir "#assert">> expr [expr]
| <<dirWithOperand>> [',' IDENT] [expr] | <<dir "#module_parameters">> '(' [paramList] ')' ['(' [paramList] ')'] [block]
| <<dirPlain>> [',' IDENT] | <<dirWithBlock>> directiveFlag_* block
| <<dirWithOperand>> directiveFlag_* [expr]
| <<dirPlain>> directiveFlag_*
// `#import,file`, `#library,system,link_always`, `#run,stallable` — a directive can
// carry any number of comma-separated flags.
private directiveFlag_ ::= ',' IDENT

View File

@@ -71,6 +71,7 @@ object JaiParserUtil : GeneratedParserUtilBase() {
"add_context", "add_context",
"module_parameters", "module_parameters",
"place", "place",
"overlay",
"procedure_of_call", "procedure_of_call",
"body_text", "body_text",
"version", "version",
@@ -85,7 +86,6 @@ object JaiParserUtil : GeneratedParserUtilBase() {
"elsewhere", "elsewhere",
"expand", "expand",
"specified", "specified",
"discard",
"location", "location",
"this", "this",
) )
@@ -286,9 +286,13 @@ object JaiParserUtil : GeneratedParserUtilBase() {
): Boolean = b.tokenType === T.LPAREN && !isProcHeaderAhead(b, level) ): Boolean = b.tokenType === T.LPAREN && !isProcHeaderAhead(b, level)
/** /**
* `[#directive|using]* IDENT (',' IDENT)* (':' | '::' | ':=')` — a declaration. * `[#directive [(…)] | using | `]* IDENT (',' IDENT)* (':' | '::' | ':=')` — a
* Jai declarations have no introducer keyword, so this is what tells * declaration. Jai declarations have no introducer keyword, so this is what tells
* `foo :: () {}` apart from `foo();`. * `foo :: () {}` apart from `foo();`.
*
* The prefix skip covers `#as using base: Document;`,
* `#overlay (unknown.vtable) using vtable: *Vtable;` and the macro-exported
* `` `it := entry.value; ``.
*/ */
@JvmStatic @JvmStatic
fun isDeclarationAhead( fun isDeclarationAhead(
@@ -296,11 +300,24 @@ object JaiParserUtil : GeneratedParserUtilBase() {
level: Int, level: Int,
): Boolean { ): Boolean {
var i = 0 var i = 0
while (true) { loop@ while (true) {
val t = b.lookAhead(i) ?: return false when (b.lookAhead(i)) {
if (t === T.DIRECTIVE || t === T.KW_USING) i++ else break T.DIRECTIVE, T.KW_USING -> {
i++
}
T.LPAREN -> {
i = skipBalancedParens(b, i)
if (i < 0) return false
}
else -> {
break@loop
}
}
} }
while (true) { while (true) {
if (b.lookAhead(i) === T.BACKTICK) i++
if (b.lookAhead(i) !== T.IDENT) return false if (b.lookAhead(i) !== T.IDENT) return false
i++ i++
when (b.lookAhead(i)) { when (b.lookAhead(i)) {
@@ -311,6 +328,61 @@ object JaiParserUtil : GeneratedParserUtilBase() {
} }
} }
/** Index just past the `)` matching the `(` at [start], or -1 if unbalanced. */
private fun skipBalancedParens(
b: PsiBuilder,
start: Int,
): Int {
var depth = 0
var i = start
while (i - start <= MAX_LOOKAHEAD) {
when (b.lookAhead(i) ?: return -1) {
T.LPAREN -> {
depth++
}
T.RPAREN -> {
depth--
if (depth == 0) return i + 1
}
else -> {}
}
i++
}
return -1
}
/**
* Consumes a `{ … }` block as opaque tokens.
*
* Used for `#asm`, whose body is x86-64 assembly (`movd source:, byte;`) and not
* Jai at all. Giving it structure is a separate job; tiling it keeps the
* surrounding file parseable.
*/
@JvmStatic
fun opaqueBlock(
b: PsiBuilder,
level: Int,
): Boolean {
if (b.tokenType !== T.LBRACE) return false
var depth = 0
while (!b.eof()) {
val t = b.tokenType
if (t === T.LBRACE) {
depth++
} else if (t === T.RBRACE) {
depth--
if (depth == 0) {
b.advanceLexer()
return true
}
}
b.advanceLexer()
}
return false
}
/** `[$|$$] IDENT (',' [$|$$] IDENT)* (':' | '::' | ':=')` — a named parameter. */ /** `[$|$$] IDENT (',' [$|$$] IDENT)* (':' | '::' | ':=')` — a named parameter. */
@JvmStatic @JvmStatic
fun isParamNameAhead( fun isParamNameAhead(

View File

@@ -0,0 +1,104 @@
package dev.hgh.jai.parser
import com.intellij.psi.PsiErrorElement
import com.intellij.psi.PsiFileFactory
import com.intellij.psi.PsiRecursiveElementWalkingVisitor
import com.intellij.testFramework.fixtures.BasePlatformTestCase
import dev.hgh.jai.JaiLanguage
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.
*/
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",
)
/** Corpus files to dump the first error of; edit freely while working. */
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",
)
fun testCorpusFiles() {
val root = File(System.getProperty("user.home"), ".local/jai")
if (!root.exists()) return
for (relative in corpusFiles) {
val file = File(root, relative)
if (file.exists()) dumpFile(file) else println("missing: $relative")
}
}
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) {
val file = factory.createFileFromText("t.jai", JaiLanguage, text)
val error = firstError(file)
if (error == null) {
println("ok ${text.replace("\n", "\\n")}")
} else {
failures++
val at = text.substring(error.textOffset).take(28).replace("\n", "\\n")
println("FAIL ${text.replace("\n", "\\n")}")
println(" ${error.errorDescription} | at '$at'")
}
}
println("$failures/${snippets.size} snippets failed")
}
private fun dumpFile(file: File) {
val text = file.readText()
val psi = PsiFileFactory.getInstance(project).createFileFromText(file.name, JaiLanguage, text)
val error = firstError(psi)
if (error == null) {
println("${file.name}: clean")
return
}
val line = text.substring(0, error.textOffset).count { it == '\n' } + 1
println("${file.name}:$line: ${error.errorDescription}")
println(" at '${text.substring(error.textOffset).take(80).replace("\n", "\\n")}'")
}
private fun firstError(file: com.intellij.psi.PsiFile): PsiErrorElement? {
var first: PsiErrorElement? = null
file.accept(
object : PsiRecursiveElementWalkingVisitor() {
override fun visitErrorElement(element: PsiErrorElement) {
if (first == null) first = element
super.visitErrorElement(element)
}
},
)
return first
}
}

View File

@@ -2,7 +2,8 @@ Jai File(0,49)
JaiStatementImpl(STATEMENT)(0,17) JaiStatementImpl(STATEMENT)(0,17)
JaiDeclarationImpl(DECLARATION)(0,17) JaiDeclarationImpl(DECLARATION)(0,17)
JaiDeclNamesImpl(DECL_NAMES)(0,1) JaiDeclNamesImpl(DECL_NAMES)(0,1)
PsiElement(Jai:IDENT)('a')(0,1) JaiDeclNameImpl(DECL_NAME)(0,1)
PsiElement(Jai:IDENT)('a')(0,1)
PsiElement(Jai::)(':')(2,3) PsiElement(Jai::)(':')(2,3)
JaiRefExprImpl(REF_EXPR)(4,9) JaiRefExprImpl(REF_EXPR)(4,9)
PsiElement(Jai:IDENT)('float')(4,9) PsiElement(Jai:IDENT)('float')(4,9)
@@ -14,7 +15,8 @@ Jai File(0,49)
JaiStatementImpl(STATEMENT)(18,26) JaiStatementImpl(STATEMENT)(18,26)
JaiDeclarationImpl(DECLARATION)(18,26) JaiDeclarationImpl(DECLARATION)(18,26)
JaiDeclNamesImpl(DECL_NAMES)(18,19) JaiDeclNamesImpl(DECL_NAMES)(18,19)
PsiElement(Jai:IDENT)('b')(18,19) JaiDeclNameImpl(DECL_NAME)(18,19)
PsiElement(Jai:IDENT)('b')(18,19)
PsiElement(Jai::=)(':=')(20,22) PsiElement(Jai::=)(':=')(20,22)
JaiInitializerImpl(INITIALIZER)(23,25) JaiInitializerImpl(INITIALIZER)(23,25)
JaiLiteralExprImpl(LITERAL_EXPR)(23,25) JaiLiteralExprImpl(LITERAL_EXPR)(23,25)
@@ -23,7 +25,8 @@ Jai File(0,49)
JaiStatementImpl(STATEMENT)(27,35) JaiStatementImpl(STATEMENT)(27,35)
JaiDeclarationImpl(DECLARATION)(27,35) JaiDeclarationImpl(DECLARATION)(27,35)
JaiDeclNamesImpl(DECL_NAMES)(27,28) JaiDeclNamesImpl(DECL_NAMES)(27,28)
PsiElement(Jai:IDENT)('c')(27,28) JaiDeclNameImpl(DECL_NAME)(27,28)
PsiElement(Jai:IDENT)('c')(27,28)
PsiElement(Jai:::)('::')(29,31) PsiElement(Jai:::)('::')(29,31)
JaiInitializerImpl(INITIALIZER)(32,34) JaiInitializerImpl(INITIALIZER)(32,34)
JaiLiteralExprImpl(LITERAL_EXPR)(32,34) JaiLiteralExprImpl(LITERAL_EXPR)(32,34)