diff --git a/src/main/gen/dev/hgh/jai/parser/JaiParser.java b/src/main/gen/dev/hgh/jai/parser/JaiParser.java index af7befa..4a6c3e9 100644 --- a/src/main/gen/dev/hgh/jai/parser/JaiParser.java +++ b/src/main/gen/dev/hgh/jai/parser/JaiParser.java @@ -43,10 +43,11 @@ public class JaiParser implements PsiParser, LightPsiParser { ENUM_EXPR, EQUALITY_EXPR, EXPR, IFX_EXPR, INDEX_EXPR, INLINE_EXPR, INTERFACE_EXPR, LAMBDA_EXPR, LITERAL_EXPR, MEMBER_EXPR, MUL_EXPR, OR_EXPR, - PAREN_EXPR, PREFIX_EXPR, PRIMARY_EXPR, PROC_LITERAL_EXPR, - RANGE_EXPR, REF_EXPR, RELATIONAL_EXPR, SHIFT_EXPR, - STRUCT_EXPR, STRUCT_LITERAL_EXPR, TYPED_ARRAY_LITERAL_EXPR, TYPED_STRUCT_LITERAL_EXPR, - UNARY_DOT_EXPR, UNINITIALIZED_EXPR, UNION_EXPR), + PAREN_EXPR, POSTFIX_CAST_EXPR, PREFIX_EXPR, PRIMARY_EXPR, + PROC_LITERAL_EXPR, RANGE_EXPR, REF_EXPR, RELATIONAL_EXPR, + SHIFT_EXPR, STRUCT_EXPR, STRUCT_LITERAL_EXPR, TYPED_ARRAY_LITERAL_EXPR, + TYPED_STRUCT_LITERAL_EXPR, UNARY_DOT_EXPR, UNINITIALIZED_EXPR, UNION_EXPR, + ZERO_LITERAL_EXPR), }; /* ********************************************************** */ @@ -361,12 +362,79 @@ public class JaiParser implements PsiParser, LightPsiParser { } /* ********************************************************** */ - // procModifier | usingModifier_ + // <> directiveFlag_* block + // | <> directiveFlag_* [parenExpr | STRING] + // | usingModifier_ static boolean declModifier_(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "declModifier_")) return false; boolean result_; - result_ = procModifier(builder_, level_ + 1); + Marker marker_ = enter_section_(builder_); + result_ = declModifier__0(builder_, level_ + 1); + if (!result_) result_ = declModifier__1(builder_, level_ + 1); if (!result_) result_ = usingModifier_(builder_, level_ + 1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + // <> directiveFlag_* block + private static boolean declModifier__0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "declModifier__0")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = dirWithBlock(builder_, level_ + 1); + result_ = result_ && declModifier__0_1(builder_, level_ + 1); + result_ = result_ && block(builder_, level_ + 1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + // directiveFlag_* + private static boolean declModifier__0_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "declModifier__0_1")) return false; + while (true) { + int pos_ = current_position_(builder_); + if (!directiveFlag_(builder_, level_ + 1)) break; + if (!empty_element_parsed_guard_(builder_, "declModifier__0_1", pos_)) break; + } + return true; + } + + // <> directiveFlag_* [parenExpr | STRING] + private static boolean declModifier__1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "declModifier__1")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = dirPlain(builder_, level_ + 1); + result_ = result_ && declModifier__1_1(builder_, level_ + 1); + result_ = result_ && declModifier__1_2(builder_, level_ + 1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + // directiveFlag_* + private static boolean declModifier__1_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "declModifier__1_1")) return false; + while (true) { + int pos_ = current_position_(builder_); + if (!directiveFlag_(builder_, level_ + 1)) break; + if (!empty_element_parsed_guard_(builder_, "declModifier__1_1", pos_)) break; + } + return true; + } + + // [parenExpr | STRING] + private static boolean declModifier__1_2(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "declModifier__1_2")) return false; + declModifier__1_2_0(builder_, level_ + 1); + return true; + } + + // parenExpr | STRING + private static boolean declModifier__1_2_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "declModifier__1_2_0")) return false; + boolean result_; + result_ = parenExpr(builder_, level_ + 1); + if (!result_) result_ = consumeToken(builder_, STRING); return result_; } @@ -587,7 +655,7 @@ public class JaiParser implements PsiParser, LightPsiParser { } /* ********************************************************** */ - // <> directiveFlag_* <> + // <> directiveFlag_* [expr (',' expr)*] <> // | <> directiveFlag_* [<>] [STRING] // | <> directiveFlag_* [<>] [STRING] // | <> directiveFlag_* ['(' [argList] ')'] [block | expr] @@ -613,13 +681,14 @@ public class JaiParser implements PsiParser, LightPsiParser { return result_; } - // <> directiveFlag_* <> + // <> directiveFlag_* [expr (',' expr)*] <> private static boolean directiveExpr_0(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "directiveExpr_0")) return false; boolean result_; Marker marker_ = enter_section_(builder_); result_ = dir(builder_, level_ + 1, "#asm"); result_ = result_ && directiveExpr_0_1(builder_, level_ + 1); + result_ = result_ && directiveExpr_0_2(builder_, level_ + 1); result_ = result_ && opaqueBlock(builder_, level_ + 1); exit_section_(builder_, marker_, null, result_); return result_; @@ -636,6 +705,46 @@ public class JaiParser implements PsiParser, LightPsiParser { return true; } + // [expr (',' expr)*] + private static boolean directiveExpr_0_2(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "directiveExpr_0_2")) return false; + directiveExpr_0_2_0(builder_, level_ + 1); + return true; + } + + // expr (',' expr)* + private static boolean directiveExpr_0_2_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "directiveExpr_0_2_0")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = expr(builder_, level_ + 1, -1); + result_ = result_ && directiveExpr_0_2_0_1(builder_, level_ + 1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + // (',' expr)* + private static boolean directiveExpr_0_2_0_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "directiveExpr_0_2_0_1")) return false; + while (true) { + int pos_ = current_position_(builder_); + if (!directiveExpr_0_2_0_1_0(builder_, level_ + 1)) break; + if (!empty_element_parsed_guard_(builder_, "directiveExpr_0_2_0_1", pos_)) break; + } + return true; + } + + // ',' expr + private static boolean directiveExpr_0_2_0_1_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "directiveExpr_0_2_0_1_0")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, COMMA); + result_ = result_ && expr(builder_, level_ + 1, -1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + // <> directiveFlag_* [<>] [STRING] private static boolean directiveExpr_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "directiveExpr_1")) return false; @@ -1076,30 +1185,75 @@ public class JaiParser implements PsiParser, LightPsiParser { } /* ********************************************************** */ - // '<' | '*' + // '<=' expr | '*=' expr | '<' | '*' static boolean forModifier_(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "forModifier_")) return false; - if (!nextTokenIs(builder_, "", LT, STAR)) return false; boolean result_; - result_ = consumeToken(builder_, LT); + Marker marker_ = enter_section_(builder_); + result_ = forModifier__0(builder_, level_ + 1); + if (!result_) result_ = forModifier__1(builder_, level_ + 1); + if (!result_) result_ = consumeToken(builder_, LT); if (!result_) result_ = consumeToken(builder_, STAR); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + // '<=' expr + private static boolean forModifier__0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "forModifier__0")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, LT_EQ); + result_ = result_ && expr(builder_, level_ + 1, -1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + // '*=' expr + private static boolean forModifier__1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "forModifier__1")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, STAR_EQ); + result_ = result_ && expr(builder_, level_ + 1, -1); + exit_section_(builder_, marker_, null, result_); return result_; } /* ********************************************************** */ - // IDENT (',' IDENT)* - public static boolean forNames(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "forNames")) return false; - if (!nextTokenIs(builder_, IDENT)) return false; + // ['`'] IDENT + public static boolean forName(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "forName")) return false; + if (!nextTokenIs(builder_, "", BACKTICK, IDENT)) return false; boolean result_; - Marker marker_ = enter_section_(builder_); - result_ = consumeToken(builder_, IDENT); - result_ = result_ && forNames_1(builder_, level_ + 1); - exit_section_(builder_, marker_, FOR_NAMES, result_); + Marker marker_ = enter_section_(builder_, level_, _NONE_, FOR_NAME, ""); + result_ = forName_0(builder_, level_ + 1); + result_ = result_ && consumeToken(builder_, IDENT); + exit_section_(builder_, level_, marker_, result_, false, null); return result_; } - // (',' IDENT)* + // ['`'] + private static boolean forName_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "forName_0")) return false; + consumeToken(builder_, BACKTICK); + return true; + } + + /* ********************************************************** */ + // forName (',' forName)* + public static boolean forNames(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "forNames")) return false; + if (!nextTokenIs(builder_, "", BACKTICK, IDENT)) return false; + boolean result_; + Marker marker_ = enter_section_(builder_, level_, _NONE_, FOR_NAMES, ""); + result_ = forName(builder_, level_ + 1); + result_ = result_ && forNames_1(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, result_, false, null); + return result_; + } + + // (',' forName)* private static boolean forNames_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "forNames_1")) return false; while (true) { @@ -1110,12 +1264,13 @@ public class JaiParser implements PsiParser, LightPsiParser { return true; } - // ',' IDENT + // ',' forName private static boolean forNames_1_0(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "forNames_1_0")) return false; boolean result_; Marker marker_ = enter_section_(builder_); - result_ = consumeTokens(builder_, 0, COMMA, IDENT); + result_ = consumeToken(builder_, COMMA); + result_ = result_ && forName(builder_, level_ + 1); exit_section_(builder_, marker_, null, result_); return result_; } @@ -1479,6 +1634,8 @@ public class JaiParser implements PsiParser, LightPsiParser { /* ********************************************************** */ // '+' | '-' | '*' | '/' | '%' | '==' | '!=' | '<' | '>' | '<=' | '>=' // | '&' | '|' | '^' | '~' | '<<' | '>>' | '<<<' | '>>>' + // | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' + // | '<<=' | '>>=' | '<<<=' | '>>>=' // | '[' ']' '=' | '[' ']' public static boolean operatorSymbol(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "operatorSymbol")) return false; @@ -1503,6 +1660,18 @@ 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_ = consumeToken(builder_, PLUS_EQ); + if (!result_) result_ = consumeToken(builder_, MINUS_EQ); + if (!result_) result_ = consumeToken(builder_, STAR_EQ); + if (!result_) result_ = consumeToken(builder_, SLASH_EQ); + if (!result_) result_ = consumeToken(builder_, PERCENT_EQ); + if (!result_) result_ = consumeToken(builder_, AND_EQ); + if (!result_) result_ = consumeToken(builder_, OR_EQ); + if (!result_) result_ = consumeToken(builder_, XOR_EQ); + if (!result_) result_ = consumeToken(builder_, SHL_EQ); + if (!result_) result_ = consumeToken(builder_, SHR_EQ); + if (!result_) result_ = consumeToken(builder_, ROL_EQ); + if (!result_) result_ = consumeToken(builder_, ROR_EQ); if (!result_) result_ = parseTokens(builder_, 0, LBRACKET, RBRACKET, EQ); if (!result_) result_ = parseTokens(builder_, 0, LBRACKET, RBRACKET); exit_section_(builder_, level_, marker_, result_, false, null); @@ -1934,7 +2103,7 @@ public class JaiParser implements PsiParser, LightPsiParser { } /* ********************************************************** */ - // ['`'] 'push_context' [expr] block + // ['`'] 'push_context' directiveFlag_* [expr] block public static boolean pushContextStatement(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "pushContextStatement")) return false; if (!nextTokenIs(builder_, "", BACKTICK, KW_PUSH_CONTEXT)) return false; @@ -1943,6 +2112,7 @@ public class JaiParser implements PsiParser, LightPsiParser { result_ = pushContextStatement_0(builder_, level_ + 1); result_ = result_ && consumeToken(builder_, KW_PUSH_CONTEXT); result_ = result_ && pushContextStatement_2(builder_, level_ + 1); + result_ = result_ && pushContextStatement_3(builder_, level_ + 1); result_ = result_ && block(builder_, level_ + 1); exit_section_(builder_, level_, marker_, result_, false, null); return result_; @@ -1955,9 +2125,20 @@ public class JaiParser implements PsiParser, LightPsiParser { return true; } - // [expr] + // directiveFlag_* private static boolean pushContextStatement_2(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "pushContextStatement_2")) return false; + while (true) { + int pos_ = current_position_(builder_); + if (!directiveFlag_(builder_, level_ + 1)) break; + if (!empty_element_parsed_guard_(builder_, "pushContextStatement_2", pos_)) break; + } + return true; + } + + // [expr] + private static boolean pushContextStatement_3(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "pushContextStatement_3")) return false; expr(builder_, level_ + 1, -1); return true; } @@ -2080,51 +2261,59 @@ public class JaiParser implements PsiParser, LightPsiParser { } /* ********************************************************** */ - // 'return' [expr (',' expr)*] semiWithNotes_ + // ['`'] 'return' [expr (',' expr)*] semiWithNotes_ public static boolean returnStatement(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "returnStatement")) return false; - if (!nextTokenIs(builder_, KW_RETURN)) return false; + if (!nextTokenIs(builder_, "", BACKTICK, KW_RETURN)) return false; boolean result_; - Marker marker_ = enter_section_(builder_); - result_ = consumeToken(builder_, KW_RETURN); - result_ = result_ && returnStatement_1(builder_, level_ + 1); + Marker marker_ = enter_section_(builder_, level_, _NONE_, RETURN_STATEMENT, ""); + result_ = returnStatement_0(builder_, level_ + 1); + result_ = result_ && consumeToken(builder_, KW_RETURN); + result_ = result_ && returnStatement_2(builder_, level_ + 1); result_ = result_ && semiWithNotes_(builder_, level_ + 1); - exit_section_(builder_, marker_, RETURN_STATEMENT, result_); + exit_section_(builder_, level_, marker_, result_, false, null); return result_; } + // ['`'] + private static boolean returnStatement_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "returnStatement_0")) return false; + consumeToken(builder_, BACKTICK); + return true; + } + // [expr (',' expr)*] - private static boolean returnStatement_1(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "returnStatement_1")) return false; - returnStatement_1_0(builder_, level_ + 1); + private static boolean returnStatement_2(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "returnStatement_2")) return false; + returnStatement_2_0(builder_, level_ + 1); return true; } // expr (',' expr)* - private static boolean returnStatement_1_0(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "returnStatement_1_0")) return false; + private static boolean returnStatement_2_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "returnStatement_2_0")) return false; boolean result_; Marker marker_ = enter_section_(builder_); result_ = expr(builder_, level_ + 1, -1); - result_ = result_ && returnStatement_1_0_1(builder_, level_ + 1); + result_ = result_ && returnStatement_2_0_1(builder_, level_ + 1); exit_section_(builder_, marker_, null, result_); return result_; } // (',' expr)* - private static boolean returnStatement_1_0_1(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "returnStatement_1_0_1")) return false; + private static boolean returnStatement_2_0_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "returnStatement_2_0_1")) return false; while (true) { int pos_ = current_position_(builder_); - if (!returnStatement_1_0_1_0(builder_, level_ + 1)) break; - if (!empty_element_parsed_guard_(builder_, "returnStatement_1_0_1", pos_)) break; + if (!returnStatement_2_0_1_0(builder_, level_ + 1)) break; + if (!empty_element_parsed_guard_(builder_, "returnStatement_2_0_1", pos_)) break; } return true; } // ',' expr - private static boolean returnStatement_1_0_1_0(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "returnStatement_1_0_1_0")) return false; + private static boolean returnStatement_2_0_1_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "returnStatement_2_0_1_0")) return false; boolean result_; Marker marker_ = enter_section_(builder_); result_ = consumeToken(builder_, COMMA); @@ -2605,6 +2794,18 @@ public class JaiParser implements PsiParser, LightPsiParser { return result_; } + /* ********************************************************** */ + // '{' '}' + public static boolean zeroLiteralExpr(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "zeroLiteralExpr")) return false; + if (!nextTokenIs(builder_, LBRACE)) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = consumeTokens(builder_, 0, LBRACE, RBRACE); + exit_section_(builder_, marker_, ZERO_LITERAL_EXPR, result_); + return result_; + } + /* ********************************************************** */ // Expression root: expr // Operator priority table: @@ -2629,12 +2830,13 @@ public class JaiParser implements PsiParser, LightPsiParser { // 18: PREFIX(inlineExpr) // 19: ATOM(ifxExpr) // 20: POSTFIX(callExpr) - // 21: POSTFIX(indexExpr) - // 22: POSTFIX(memberExpr) - // 23: POSTFIX(derefExpr) - // 24: POSTFIX(typedStructLiteralExpr) - // 25: POSTFIX(typedArrayLiteralExpr) - // 26: ATOM(primaryExpr) + // 21: POSTFIX(postfixCastExpr) + // 22: POSTFIX(indexExpr) + // 23: POSTFIX(memberExpr) + // 24: POSTFIX(derefExpr) + // 25: POSTFIX(typedStructLiteralExpr) + // 26: POSTFIX(typedArrayLiteralExpr) + // 27: ATOM(primaryExpr) public static boolean expr(PsiBuilder builder_, int level_, int priority_) { if (!recursion_guard_(builder_, level_, "expr")) return false; addVariant(builder_, ""); @@ -2715,23 +2917,27 @@ public class JaiParser implements PsiParser, LightPsiParser { result_ = true; exit_section_(builder_, level_, marker_, CALL_EXPR, result_, true, null); } - else if (priority_ < 21 && indexExpr_0(builder_, level_ + 1)) { + else if (priority_ < 21 && postfixCastExpr_0(builder_, level_ + 1)) { + result_ = true; + exit_section_(builder_, level_, marker_, POSTFIX_CAST_EXPR, result_, true, null); + } + else if (priority_ < 22 && indexExpr_0(builder_, level_ + 1)) { result_ = true; exit_section_(builder_, level_, marker_, INDEX_EXPR, result_, true, null); } - else if (priority_ < 22 && memberExpr_0(builder_, level_ + 1)) { + else if (priority_ < 23 && memberExpr_0(builder_, level_ + 1)) { result_ = true; exit_section_(builder_, level_, marker_, MEMBER_EXPR, result_, true, null); } - else if (priority_ < 23 && consumeTokenSmart(builder_, POSTFIX_DEREFERENCE)) { + else if (priority_ < 24 && consumeTokenSmart(builder_, POSTFIX_DEREFERENCE)) { result_ = true; exit_section_(builder_, level_, marker_, DEREF_EXPR, result_, true, null); } - else if (priority_ < 24 && typedStructLiteralExpr_0(builder_, level_ + 1)) { + else if (priority_ < 25 && typedStructLiteralExpr_0(builder_, level_ + 1)) { result_ = true; exit_section_(builder_, level_, marker_, TYPED_STRUCT_LITERAL_EXPR, result_, true, null); } - else if (priority_ < 25 && typedArrayLiteralExpr_0(builder_, level_ + 1)) { + else if (priority_ < 26 && typedArrayLiteralExpr_0(builder_, level_ + 1)) { result_ = true; exit_section_(builder_, level_, marker_, TYPED_ARRAY_LITERAL_EXPR, result_, true, null); } @@ -2849,7 +3055,7 @@ public class JaiParser implements PsiParser, LightPsiParser { return result_; } - // 'cast' [',' IDENT] '(' [expr] ')' expr + // 'cast' directiveFlag_* '(' [expr (',' expr)*] ')' [expr] public static boolean castExpr(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "castExpr")) return false; if (!nextTokenIsSmart(builder_, KW_CAST)) return false; @@ -2860,21 +3066,65 @@ public class JaiParser implements PsiParser, LightPsiParser { result_ = result_ && consumeToken(builder_, LPAREN); result_ = result_ && castExpr_3(builder_, level_ + 1); result_ = result_ && consumeToken(builder_, RPAREN); - result_ = result_ && expr(builder_, level_ + 1, -1); + result_ = result_ && castExpr_5(builder_, level_ + 1); exit_section_(builder_, marker_, CAST_EXPR, result_); return result_; } - // [',' IDENT] + // directiveFlag_* private static boolean castExpr_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "castExpr_1")) return false; - parseTokensSmart(builder_, 0, COMMA, IDENT); + while (true) { + int pos_ = current_position_(builder_); + if (!directiveFlag_(builder_, level_ + 1)) break; + if (!empty_element_parsed_guard_(builder_, "castExpr_1", pos_)) break; + } return true; } - // [expr] + // [expr (',' expr)*] private static boolean castExpr_3(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "castExpr_3")) return false; + castExpr_3_0(builder_, level_ + 1); + return true; + } + + // expr (',' expr)* + private static boolean castExpr_3_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "castExpr_3_0")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = expr(builder_, level_ + 1, -1); + result_ = result_ && castExpr_3_0_1(builder_, level_ + 1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + // (',' expr)* + private static boolean castExpr_3_0_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "castExpr_3_0_1")) return false; + while (true) { + int pos_ = current_position_(builder_); + if (!castExpr_3_0_1_0(builder_, level_ + 1)) break; + if (!empty_element_parsed_guard_(builder_, "castExpr_3_0_1", pos_)) break; + } + return true; + } + + // ',' expr + private static boolean castExpr_3_0_1_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "castExpr_3_0_1_0")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = consumeTokenSmart(builder_, COMMA); + result_ = result_ && expr(builder_, level_ + 1, -1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + // [expr] + private static boolean castExpr_5(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "castExpr_5")) return false; expr(builder_, level_ + 1, -1); return true; } @@ -2995,6 +3245,25 @@ public class JaiParser implements PsiParser, LightPsiParser { return true; } + // '.' '(' [expr] ')' + private static boolean postfixCastExpr_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "postfixCastExpr_0")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = consumeTokensSmart(builder_, 0, DOT, LPAREN); + result_ = result_ && postfixCastExpr_0_2(builder_, level_ + 1); + result_ = result_ && consumeToken(builder_, RPAREN); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + // [expr] + private static boolean postfixCastExpr_0_2(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "postfixCastExpr_0_2")) return false; + expr(builder_, level_ + 1, -1); + return true; + } + // '[' [expr] ']' private static boolean indexExpr_0(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "indexExpr_0")) return false; @@ -3076,6 +3345,7 @@ public class JaiParser implements PsiParser, LightPsiParser { // | builtinCallExpr // | interfaceExpr // | literalExpr + // | zeroLiteralExpr // | refExpr // | uninitializedExpr public static boolean primaryExpr(PsiBuilder builder_, int level_) { @@ -3095,6 +3365,7 @@ public class JaiParser implements PsiParser, LightPsiParser { if (!result_) result_ = builtinCallExpr(builder_, level_ + 1); if (!result_) result_ = interfaceExpr(builder_, level_ + 1); if (!result_) result_ = literalExpr(builder_, level_ + 1); + if (!result_) result_ = zeroLiteralExpr(builder_, level_ + 1); if (!result_) result_ = refExpr(builder_, level_ + 1); if (!result_) result_ = uninitializedExpr(builder_, level_ + 1); exit_section_(builder_, level_, marker_, result_, false, null); diff --git a/src/main/gen/dev/hgh/jai/psi/JaiDeclaration.java b/src/main/gen/dev/hgh/jai/psi/JaiDeclaration.java index 2ce8e9a..fdb1bc6 100644 --- a/src/main/gen/dev/hgh/jai/psi/JaiDeclaration.java +++ b/src/main/gen/dev/hgh/jai/psi/JaiDeclaration.java @@ -10,12 +10,18 @@ public interface JaiDeclaration extends PsiElement { @NotNull List getArgumentList(); + @NotNull + List getBlockList(); + @NotNull JaiDeclNames getDeclNames(); @NotNull List getInitializerList(); + @NotNull + List getParenExprList(); + @NotNull List getProcModifierList(); diff --git a/src/main/gen/dev/hgh/jai/psi/JaiDirectiveExpr.java b/src/main/gen/dev/hgh/jai/psi/JaiDirectiveExpr.java index 8c5bd30..ff2915c 100644 --- a/src/main/gen/dev/hgh/jai/psi/JaiDirectiveExpr.java +++ b/src/main/gen/dev/hgh/jai/psi/JaiDirectiveExpr.java @@ -13,8 +13,8 @@ public interface JaiDirectiveExpr extends JaiExpr { @Nullable JaiBlock getBlock(); - @Nullable - JaiExpr getExpr(); + @NotNull + List getExprList(); @NotNull List getParameterList(); diff --git a/src/main/gen/dev/hgh/jai/psi/JaiForName.java b/src/main/gen/dev/hgh/jai/psi/JaiForName.java new file mode 100644 index 0000000..fb3e812 --- /dev/null +++ b/src/main/gen/dev/hgh/jai/psi/JaiForName.java @@ -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 JaiForName extends PsiElement { + +} diff --git a/src/main/gen/dev/hgh/jai/psi/JaiForNames.java b/src/main/gen/dev/hgh/jai/psi/JaiForNames.java index 65ae503..084f647 100644 --- a/src/main/gen/dev/hgh/jai/psi/JaiForNames.java +++ b/src/main/gen/dev/hgh/jai/psi/JaiForNames.java @@ -7,4 +7,7 @@ import com.intellij.psi.PsiElement; public interface JaiForNames extends PsiElement { + @NotNull + List getForNameList(); + } diff --git a/src/main/gen/dev/hgh/jai/psi/JaiPostfixCastExpr.java b/src/main/gen/dev/hgh/jai/psi/JaiPostfixCastExpr.java new file mode 100644 index 0000000..e977f33 --- /dev/null +++ b/src/main/gen/dev/hgh/jai/psi/JaiPostfixCastExpr.java @@ -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 JaiPostfixCastExpr extends JaiExpr { + + @NotNull + List getExprList(); + +} diff --git a/src/main/gen/dev/hgh/jai/psi/JaiTypes.java b/src/main/gen/dev/hgh/jai/psi/JaiTypes.java index d06825d..2500459 100644 --- a/src/main/gen/dev/hgh/jai/psi/JaiTypes.java +++ b/src/main/gen/dev/hgh/jai/psi/JaiTypes.java @@ -40,6 +40,7 @@ public interface JaiTypes { IElementType EQUALITY_EXPR = new JaiElementType("EQUALITY_EXPR"); IElementType EXPR = new JaiElementType("EXPR"); IElementType EXPRESSION_STATEMENT = new JaiElementType("EXPRESSION_STATEMENT"); + IElementType FOR_NAME = new JaiElementType("FOR_NAME"); IElementType FOR_NAMES = new JaiElementType("FOR_NAMES"); IElementType FOR_STATEMENT = new JaiElementType("FOR_STATEMENT"); IElementType IFX_EXPR = new JaiElementType("IFX_EXPR"); @@ -62,6 +63,7 @@ public interface JaiTypes { IElementType PARAM_NAME = new JaiElementType("PARAM_NAME"); IElementType PARAM_NAMES = new JaiElementType("PARAM_NAMES"); IElementType PAREN_EXPR = new JaiElementType("PAREN_EXPR"); + IElementType POSTFIX_CAST_EXPR = new JaiElementType("POSTFIX_CAST_EXPR"); IElementType PREFIX_EXPR = new JaiElementType("PREFIX_EXPR"); IElementType PRIMARY_EXPR = new JaiElementType("PRIMARY_EXPR"); IElementType PROC_LITERAL_EXPR = new JaiElementType("PROC_LITERAL_EXPR"); @@ -86,6 +88,7 @@ public interface JaiTypes { IElementType UNION_EXPR = new JaiElementType("UNION_EXPR"); IElementType USING_STATEMENT = new JaiElementType("USING_STATEMENT"); IElementType WHILE_STATEMENT = new JaiElementType("WHILE_STATEMENT"); + IElementType ZERO_LITERAL_EXPR = new JaiElementType("ZERO_LITERAL_EXPR"); IElementType AND = JaiTokenTypes.byName("&"); IElementType AND_AND = JaiTokenTypes.byName("&&"); @@ -289,6 +292,9 @@ public interface JaiTypes { else if (type == EXPRESSION_STATEMENT) { return new JaiExpressionStatementImpl(node); } + else if (type == FOR_NAME) { + return new JaiForNameImpl(node); + } else if (type == FOR_NAMES) { return new JaiForNamesImpl(node); } @@ -355,6 +361,9 @@ public interface JaiTypes { else if (type == PAREN_EXPR) { return new JaiParenExprImpl(node); } + else if (type == POSTFIX_CAST_EXPR) { + return new JaiPostfixCastExprImpl(node); + } else if (type == PREFIX_EXPR) { return new JaiPrefixExprImpl(node); } @@ -424,6 +433,9 @@ public interface JaiTypes { else if (type == WHILE_STATEMENT) { return new JaiWhileStatementImpl(node); } + else if (type == ZERO_LITERAL_EXPR) { + return new JaiZeroLiteralExprImpl(node); + } throw new AssertionError("Unknown element type: " + type); } } diff --git a/src/main/gen/dev/hgh/jai/psi/JaiVisitor.java b/src/main/gen/dev/hgh/jai/psi/JaiVisitor.java index 9c8fb30..b9d2c27 100644 --- a/src/main/gen/dev/hgh/jai/psi/JaiVisitor.java +++ b/src/main/gen/dev/hgh/jai/psi/JaiVisitor.java @@ -131,6 +131,10 @@ public class JaiVisitor extends PsiElementVisitor { visitPsiElement(o); } + public void visitForName(@NotNull JaiForName o) { + visitPsiElement(o); + } + public void visitForNames(@NotNull JaiForNames o) { visitPsiElement(o); } @@ -219,6 +223,10 @@ public class JaiVisitor extends PsiElementVisitor { visitExpr(o); } + public void visitPostfixCastExpr(@NotNull JaiPostfixCastExpr o) { + visitExpr(o); + } + public void visitPrefixExpr(@NotNull JaiPrefixExpr o) { visitExpr(o); } @@ -315,6 +323,10 @@ public class JaiVisitor extends PsiElementVisitor { visitPsiElement(o); } + public void visitZeroLiteralExpr(@NotNull JaiZeroLiteralExpr o) { + visitExpr(o); + } + public void visitPsiElement(@NotNull PsiElement o) { visitElement(o); } diff --git a/src/main/gen/dev/hgh/jai/psi/JaiZeroLiteralExpr.java b/src/main/gen/dev/hgh/jai/psi/JaiZeroLiteralExpr.java new file mode 100644 index 0000000..57e2550 --- /dev/null +++ b/src/main/gen/dev/hgh/jai/psi/JaiZeroLiteralExpr.java @@ -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 JaiZeroLiteralExpr extends JaiExpr { + +} diff --git a/src/main/gen/dev/hgh/jai/psi/impl/JaiDeclarationImpl.java b/src/main/gen/dev/hgh/jai/psi/impl/JaiDeclarationImpl.java index 7b45ebe..3668771 100644 --- a/src/main/gen/dev/hgh/jai/psi/impl/JaiDeclarationImpl.java +++ b/src/main/gen/dev/hgh/jai/psi/impl/JaiDeclarationImpl.java @@ -33,6 +33,12 @@ public class JaiDeclarationImpl extends ASTWrapperPsiElement implements JaiDecla return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiArgument.class); } + @Override + @NotNull + public List getBlockList() { + return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiBlock.class); + } + @Override @NotNull public JaiDeclNames getDeclNames() { @@ -45,6 +51,12 @@ public class JaiDeclarationImpl extends ASTWrapperPsiElement implements JaiDecla return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiInitializer.class); } + @Override + @NotNull + public List getParenExprList() { + return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiParenExpr.class); + } + @Override @NotNull public List getProcModifierList() { diff --git a/src/main/gen/dev/hgh/jai/psi/impl/JaiDirectiveExprImpl.java b/src/main/gen/dev/hgh/jai/psi/impl/JaiDirectiveExprImpl.java index 9fe298b..2a2e180 100644 --- a/src/main/gen/dev/hgh/jai/psi/impl/JaiDirectiveExprImpl.java +++ b/src/main/gen/dev/hgh/jai/psi/impl/JaiDirectiveExprImpl.java @@ -40,9 +40,9 @@ public class JaiDirectiveExprImpl extends JaiExprImpl implements JaiDirectiveExp } @Override - @Nullable - public JaiExpr getExpr() { - return findChildByClass(JaiExpr.class); + @NotNull + public List getExprList() { + return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiExpr.class); } @Override diff --git a/src/main/gen/dev/hgh/jai/psi/impl/JaiForNameImpl.java b/src/main/gen/dev/hgh/jai/psi/impl/JaiForNameImpl.java new file mode 100644 index 0000000..cbf204b --- /dev/null +++ b/src/main/gen/dev/hgh/jai/psi/impl/JaiForNameImpl.java @@ -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 JaiForNameImpl extends ASTWrapperPsiElement implements JaiForName { + + public JaiForNameImpl(@NotNull ASTNode node) { + super(node); + } + + public void accept(@NotNull JaiVisitor visitor) { + visitor.visitForName(this); + } + + @Override + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JaiVisitor) accept((JaiVisitor)visitor); + else super.accept(visitor); + } + +} diff --git a/src/main/gen/dev/hgh/jai/psi/impl/JaiForNamesImpl.java b/src/main/gen/dev/hgh/jai/psi/impl/JaiForNamesImpl.java index 8464f19..b959867 100644 --- a/src/main/gen/dev/hgh/jai/psi/impl/JaiForNamesImpl.java +++ b/src/main/gen/dev/hgh/jai/psi/impl/JaiForNamesImpl.java @@ -27,4 +27,10 @@ public class JaiForNamesImpl extends ASTWrapperPsiElement implements JaiForNames else super.accept(visitor); } + @Override + @NotNull + public List getForNameList() { + return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiForName.class); + } + } diff --git a/src/main/gen/dev/hgh/jai/psi/impl/JaiPostfixCastExprImpl.java b/src/main/gen/dev/hgh/jai/psi/impl/JaiPostfixCastExprImpl.java new file mode 100644 index 0000000..8ff9e08 --- /dev/null +++ b/src/main/gen/dev/hgh/jai/psi/impl/JaiPostfixCastExprImpl.java @@ -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 JaiPostfixCastExprImpl extends JaiExprImpl implements JaiPostfixCastExpr { + + public JaiPostfixCastExprImpl(@NotNull ASTNode node) { + super(node); + } + + @Override + public void accept(@NotNull JaiVisitor visitor) { + visitor.visitPostfixCastExpr(this); + } + + @Override + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JaiVisitor) accept((JaiVisitor)visitor); + else super.accept(visitor); + } + + @Override + @NotNull + public List getExprList() { + return PsiTreeUtil.getChildrenOfTypeAsList(this, JaiExpr.class); + } + +} diff --git a/src/main/gen/dev/hgh/jai/psi/impl/JaiZeroLiteralExprImpl.java b/src/main/gen/dev/hgh/jai/psi/impl/JaiZeroLiteralExprImpl.java new file mode 100644 index 0000000..61809b2 --- /dev/null +++ b/src/main/gen/dev/hgh/jai/psi/impl/JaiZeroLiteralExprImpl.java @@ -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 dev.hgh.jai.psi.*; + +public class JaiZeroLiteralExprImpl extends JaiExprImpl implements JaiZeroLiteralExpr { + + public JaiZeroLiteralExprImpl(@NotNull ASTNode node) { + super(node); + } + + @Override + public void accept(@NotNull JaiVisitor visitor) { + visitor.visitZeroLiteralExpr(this); + } + + @Override + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JaiVisitor) accept((JaiVisitor)visitor); + else super.accept(visitor); + } + +} diff --git a/src/main/grammar/Jai.bnf b/src/main/grammar/Jai.bnf index 8060531..5a907f2 100644 --- a/src/main/grammar/Jai.bnf +++ b/src/main/grammar/Jai.bnf @@ -195,15 +195,16 @@ whileStatement ::= 'while' [<> IDENT ':'] expr statement // `for < * name, index : iterable` — `<` reverses, `*` iterates by pointer, and // `for :expansion` selects a named for_expansion. forStatement ::= 'for' [':' expr] forModifier_* [<> forNames ':'] expr statement -private forModifier_ ::= '<' | '*' -forNames ::= IDENT (',' IDENT)* +private forModifier_ ::= '<=' expr | '*=' expr | '<' | '*' +forNames ::= forName (',' forName)* +forName ::= ['`'] IDENT -returnStatement ::= 'return' [expr (',' expr)*] semiWithNotes_ +returnStatement ::= ['`'] 'return' [expr (',' expr)*] semiWithNotes_ breakStatement ::= 'break' [IDENT] semi continueStatement ::= 'continue' [IDENT] semi removeStatement ::= 'remove' [expr] semi deferStatement ::= ['`'] 'defer' statement -pushContextStatement ::= ['`'] 'push_context' [expr] block +pushContextStatement ::= ['`'] 'push_context' directiveFlag_* [expr] block usingStatement ::= 'using' [',' expr] expr semi expressionStatement ::= expr (',' expr)* semiWithNotes_ @@ -216,7 +217,9 @@ expressionStatement ::= expr (',' expr)* semiWithNotes_ declaration ::= <> declModifier_* declNames declTail_ semiWithNotes_ // `#as using base: Document;`, `#overlay (unknown.vtable) using vtable: *Vtable;`, // `#as using,except(vtable) iunknown: IUnknown;` -private declModifier_ ::= procModifier | usingModifier_ +private declModifier_ ::= <> directiveFlag_* block + | <> directiveFlag_* [parenExpr | STRING] + | usingModifier_ private usingModifier_ ::= 'using' [directiveFlag_ ['(' [argList] ')']] declNames ::= declName (',' declName)* declName ::= ['`'] IDENT @@ -234,6 +237,8 @@ initializer ::= '---' | expr operatorDeclaration ::= 'operator' operatorSymbol '::' expr semiWithNotes_ operatorSymbol ::= '+' | '-' | '*' | '/' | '%' | '==' | '!=' | '<' | '>' | '<=' | '>=' | '&' | '|' | '^' | '~' | '<<' | '>>' | '<<<' | '>>>' + | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' + | '<<=' | '>>=' | '<<<=' | '>>>=' | '[' ']' '=' | '[' ']' // -------------------------------------------------------------------- expressions @@ -259,6 +264,7 @@ expr ::= assignExpr | inlineExpr | ifxExpr | callExpr + | postfixCastExpr | indexExpr | memberExpr | derefExpr @@ -297,7 +303,7 @@ arrayTypeExpr ::= '[' ['..' | expr] ']' expr // (modules/Shared_Memory_Channel/module.jai:113). derefCastExpr ::= '(' '.*' ')' expr -castExpr ::= 'cast' [',' IDENT] '(' [expr] ')' expr +castExpr ::= 'cast' directiveFlag_* '(' [expr (',' expr)*] ')' [expr] autoCastExpr ::= 'xx' [',' IDENT] expr inlineExpr ::= ('inline' | 'no_inline') expr ifxExpr ::= ifxKeyword_ expr ['then'] [ifxBranch_] ['else' ifxBranch_] @@ -305,6 +311,7 @@ private ifxKeyword_ ::= 'ifx' | <> private ifxBranch_ ::= block | expr callExpr ::= expr '(' [argList] ')' +postfixCastExpr ::= expr '.' '(' [expr] ')' indexExpr ::= expr '[' [expr] ']' memberExpr ::= expr '.' memberName derefExpr ::= expr '.*' @@ -337,12 +344,16 @@ primaryExpr ::= procLiteralExpr | builtinCallExpr | interfaceExpr | literalExpr + | zeroLiteralExpr | refExpr | uninitializedExpr refExpr ::= IDENT literalExpr ::= NUMBER | STRING | HERE_STRING | 'true' | 'false' | 'null' | 'context' uninitializedExpr ::= '---' | '--' +// `table.* = {};` zero-initialises. Only the empty form is an expression; a +// non-empty `{ … }` in expression position would collide with a block statement. +zeroLiteralExpr ::= '{' '}' backtickExpr ::= '`' (IDENT | 'defer' | 'return' | 'push_context' | 'operator') unaryDotExpr ::= '.' memberName structLiteralExpr ::= '.{' [argList] '}' @@ -388,7 +399,7 @@ private structModifier_ ::= procModifier // `#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 ::= <> directiveFlag_* <> +directiveExpr ::= <> directiveFlag_* [expr (',' expr)*] <> | <> directiveFlag_* [<>] [STRING] | <> directiveFlag_* [<>] [STRING] | <> directiveFlag_* ['(' [argList] ')'] [block | expr] diff --git a/src/main/kotlin/dev/hgh/jai/lexer/JaiLexer.kt b/src/main/kotlin/dev/hgh/jai/lexer/JaiLexer.kt index 6eb1076..d77e4e4 100644 --- a/src/main/kotlin/dev/hgh/jai/lexer/JaiLexer.kt +++ b/src/main/kotlin/dev/hgh/jai/lexer/JaiLexer.kt @@ -579,11 +579,16 @@ open class JaiLexer : LexerBase() { private fun scanHereString(from: Int): Int { var p = scanWhile(from) { isSpace(it) } - // Optional `,cr` modifier. + // Optional modifier: `#string,cr ID` in the compiler's lexer + // (module.jai:487), and `#string,\% ID` in how_to/018_print_functions.jai, + // which the shipped Jai_Lexer module does not accept. Any non-space run is + // taken as the modifier; a here-string still has to produce a terminator + // identifier and a newline after it, so this cannot misfire. if (ch(p) == ','.code) { p = scanWhile(p + 1) { isSpace(it) } - if (!startsIdentifier(ch(p))) return -1 - p = scanIdentifier(p) + val modifierStart = p + p = scanWhile(p) { !isSpace(it) && it != -1 } + if (p == modifierStart) return -1 p = scanWhile(p) { isSpace(it) } } diff --git a/src/main/kotlin/dev/hgh/jai/parser/JaiParserUtil.kt b/src/main/kotlin/dev/hgh/jai/parser/JaiParserUtil.kt index dda9c8a..80e36aa 100644 --- a/src/main/kotlin/dev/hgh/jai/parser/JaiParserUtil.kt +++ b/src/main/kotlin/dev/hgh/jai/parser/JaiParserUtil.kt @@ -282,11 +282,15 @@ object JaiParserUtil : GeneratedParserUtilBase() { T.RPAREN -> { depth-- if (depth == 0) { + // A `name:` or `$T` inside the parentheses can only be a + // parameter list, so the header stands on its own: a bare + // proc *type* like `proc: (info: *Info, data: T)` has no + // arrow, directive or body after it. + if (sawParamMarker) return true val next = b.lookAhead(i + 1) - return when { - next === T.RIGHT_ARROW -> true - next === T.DIRECTIVE -> true - next === T.LBRACE -> empty || sawParamMarker + return when (next) { + T.RIGHT_ARROW, T.DIRECTIVE -> true + T.LBRACE -> empty else -> false } } @@ -459,6 +463,7 @@ object JaiParserUtil : GeneratedParserUtilBase() { ): Boolean { var i = 0 while (true) { + if (b.lookAhead(i) === T.BACKTICK) i++ if (b.lookAhead(i) !== T.IDENT) return false i++ when (b.lookAhead(i)) { diff --git a/src/test/kotlin/dev/hgh/jai/parser/JaiCorpusParserTest.kt b/src/test/kotlin/dev/hgh/jai/parser/JaiCorpusParserTest.kt index 0560518..218ffdc 100644 --- a/src/test/kotlin/dev/hgh/jai/parser/JaiCorpusParserTest.kt +++ b/src/test/kotlin/dev/hgh/jai/parser/JaiCorpusParserTest.kt @@ -106,7 +106,7 @@ class JaiCorpusParserTest : BasePlatformTestCase() { private companion object { /** Ratchet. Raise it as the grammar improves; never lower it. */ - const val MIN_CLEAN_FILES = 575 + const val MIN_CLEAN_FILES = 640 const val REPORTED_ERRORS = 25 const val REPORTED_KINDS = 20 const val GOT_WIDTH = 14