Skip to content

Commit b1c30d7

Browse files
committed
Round 19: alignas, using alias, typename expr, NTTP brace-init, sizeof spacing
Parser: - alignas(expr) consumed in parseFunctionOrVariable qualifier section - parseConstructorInitEntry: pack expansion args... in init list - parseStatementOrMultiDecl: 'using T = Type;' local alias handled verbatim - parseStatement: 'typename T::member;' in requires body consumed as no-op - parsePrimary: 'typename' in expression context folds into qualified name - parseTemplateArg: Type{...} brace-init NTTP handled as template argument - trailing requires handler: 'requires requires { }' double-requires consumed - sizeof: space separator between identifier tokens prevents merging
1 parent bfa0368 commit b1c30d7

2 files changed

Lines changed: 109 additions & 7 deletions

File tree

mode/CppMode.jar

1.08 KB
Binary file not shown.

src/java/Parser.java

Lines changed: 109 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,9 +1082,14 @@ private FunctionDecl.ConstructorInit parseConstructorInitEntry() {
10821082
} else {
10831083
expectPunct("(");
10841084
if (!checkPunct(")")) {
1085-
args.add(parseExpr());
1085+
Expr a0 = parseExpr();
1086+
if (matchPunct("...")) a0 = new PostfixExpr("...", a0, a0.line(), a0.col(), List.of());
1087+
args.add(a0);
10861088
while (matchPunct(",")) {
1087-
args.add(parseExpr());
1089+
if (checkPunct(")")) break;
1090+
Expr ai = parseExpr();
1091+
if (matchPunct("...")) ai = new PostfixExpr("...", ai, ai.line(), ai.col(), List.of());
1092+
args.add(ai);
10881093
}
10891094
}
10901095
expectPunct(")");
@@ -1139,6 +1144,11 @@ private List<TopLevelItem> parseFunctionOrVariable(List<CppLexerToken> leadingCo
11391144
boolean isStatic = matchKeyword("static");
11401145
matchKeyword("inline");
11411146
matchKeyword("volatile"); // consume volatile qualifier
1147+
// alignas(expr): consume alignment specifier before type
1148+
if (checkKeyword("alignas") && pos + 1 < tokens.size() && tokens.get(pos + 1).isPunct("(")) {
1149+
advance(); advance(); int _aad=1;
1150+
while (!isAtEnd() && _aad > 0) { if (checkPunct("(")) _aad++; else if (checkPunct(")")) _aad--; advance(); }
1151+
}
11421152
boolean isConst = matchKeyword("const");
11431153
boolean isConstexprFn = matchKeyword("constexpr") || matchKeyword("consteval");
11441154
if (isConstexprFn && !isConst) isConst = true;
@@ -1210,10 +1220,31 @@ && looksLikeParamList()) {
12101220
// trailing requires clause: "requires expr" -- consume to { or ;
12111221
advance();
12121222
if (checkPunct("(")) { advance(); int d=1; while(!isAtEnd()&&d>0){if(checkPunct("("))d++;else if(checkPunct(")"))d--;advance();} }
1213-
else { // bare expression like "requires std::is_arithmetic_v<T>"
1214-
while (!isAtEnd() && !checkPunct("{") && !checkPunct(";") && !checkOp("=")) {
1215-
if (checkOp("<")) { advance(); int d=1; while(!isAtEnd()&&d>0){if(checkOp("<"))d++;else if(checkOp(">"))d--;advance();} }
1216-
else advance();
1223+
else if (checkPunct("{")) {
1224+
// requires { expr } body -- consume the whole braced block
1225+
advance(); int d=1;
1226+
while (!isAtEnd() && d > 0) {
1227+
if (checkPunct("{")) d++;
1228+
else if (checkPunct("}")) { if (--d == 0) { advance(); break; } }
1229+
advance();
1230+
}
1231+
} else { // bare expression like "requires std::is_arithmetic_v<T>"
1232+
// Also handle "requires requires { ... }" (nested)
1233+
if (check(CppLexerTokenType.IDENTIFIER) && peek().text().equals("requires")) {
1234+
advance(); // consume inner requires
1235+
}
1236+
if (checkPunct("{")) {
1237+
advance(); int d=1;
1238+
while (!isAtEnd() && d > 0) {
1239+
if (checkPunct("{")) d++;
1240+
else if (checkPunct("}")) { if (--d == 0) { advance(); break; } }
1241+
advance();
1242+
}
1243+
} else {
1244+
while (!isAtEnd() && !checkPunct("{") && !checkPunct(";") && !checkOp("=")) {
1245+
if (checkOp("<")) { advance(); int d=1; while(!isAtEnd()&&d>0){if(checkOp("<"))d++;else if(checkOp(">"))d--;advance();} }
1246+
else advance();
1247+
}
12171248
}
12181249
}
12191250
} else break;
@@ -1987,6 +2018,17 @@ private TypeRef parseTemplateArg() {
19872018
return new NamedType(sof.toString(), List.of(), 0, false, false, false);
19882019
}
19892020
TypeRef maybeReturnType = parseTypeRef();
2021+
// NTTP brace-init: "Point19{0.0f, 0.0f}" as template argument
2022+
if (checkPunct("{") && maybeReturnType instanceof NamedType _nttp) {
2023+
StringBuilder _nb = new StringBuilder(_nttp.baseName()).append("{");
2024+
int _nd = 1; advance();
2025+
while (!isAtEnd() && _nd > 0) {
2026+
if (checkPunct("{")) { _nd++; _nb.append("{"); advance(); }
2027+
else if (checkPunct("}")) { _nd--; if (_nd == 0) { _nb.append("}"); advance(); break; } _nb.append("}"); advance(); }
2028+
else { _nb.append(peek().text()); advance(); }
2029+
}
2030+
return new NamedType(_nb.toString(), List.of(), 0, false, false, false);
2031+
}
19902032
// Compound boolean expression in template arg: "is_arithmetic_v<T> && !is_same_v<T,bool>"
19912033
// The && was consumed as rvalue-ref by parseTypeRef; check if ! or || follows
19922034
// The && was already consumed by parseTypeRef as rvalue-ref
@@ -2679,7 +2721,15 @@ else if (checkPunct(",") && depth == 0) {
26792721
while(!isAtEnd()&&d>0){
26802722
if(checkPunct("(")){ d++; sizeofText.append("("); advance(); }
26812723
else if(checkPunct(")")){ d--; if(d>0)sizeofText.append(")"); advance(); }
2682-
else { sizeofText.append(peek().text()); advance(); }
2724+
else {
2725+
// Add space before identifier/keyword tokens to avoid merging
2726+
String _st = peek().text();
2727+
if (sizeofText.length() > 0) {
2728+
char _last = sizeofText.charAt(sizeofText.length()-1);
2729+
if (Character.isLetterOrDigit(_last) || _last == '_') sizeofText.append(" ");
2730+
}
2731+
sizeofText.append(_st); advance();
2732+
}
26832733
}
26842734
sizeofText.append(")");
26852735
} else {
@@ -2698,6 +2748,39 @@ else if (checkPunct(",") && depth == 0) {
26982748
return new Literal(Literal.Kind.INT, "alignof(...)", t.line(), t.col(), List.of());
26992749
}
27002750
if (t.type() == CppLexerTokenType.IDENTIFIER || t.type() == CppLexerTokenType.KEYWORD) {
2751+
// "typename T::member" in expression context -- fold typename into the following qualified name
2752+
if (t.text().equals("typename")) {
2753+
advance(); // consume typename
2754+
// Parse the following type and prepend "typename "
2755+
CppLexerToken next = peek();
2756+
if (next.type() == CppLexerTokenType.IDENTIFIER || next.type() == CppLexerTokenType.KEYWORD) {
2757+
String typeName = advance().text();
2758+
// Consume :: qualified parts
2759+
while (checkPunct("::")) {
2760+
advance();
2761+
if (check(CppLexerTokenType.IDENTIFIER) || check(CppLexerTokenType.KEYWORD))
2762+
typeName += "::" + advance().text();
2763+
}
2764+
// Consume template args if present
2765+
if (checkOp("<") && looksLikeTemplateArgList()) {
2766+
int _as = pos; advance(); int _d=1;
2767+
while (!isAtEnd() && _d > 0) {
2768+
if (checkOp("<")) { _d++; advance(); }
2769+
else if (checkOp(">")) { _d--; advance(); }
2770+
else if (checkOp(">>")) { _d-=2; splitTrailingShiftIntoTwoCloseAngles(); advance(); }
2771+
else advance();
2772+
}
2773+
StringBuilder _ta = new StringBuilder(typeName).append("<");
2774+
for (int _i=_as+1; _i<pos-1; _i++) _ta.append(tokens.get(_i).text());
2775+
_ta.append(">");
2776+
typeName = _ta.toString();
2777+
}
2778+
// Consume trailing :: member
2779+
if (checkPunct("::")) { advance(); if (check(CppLexerTokenType.IDENTIFIER)||check(CppLexerTokenType.KEYWORD)) typeName += "::" + advance().text(); }
2780+
return new Identifier("typename " + typeName, t.line(), t.col(), List.of());
2781+
}
2782+
return new Identifier("typename", t.line(), t.col(), List.of());
2783+
}
27012784
if (t.text().equals("requires")) { advance(); if(checkPunct("(")){ advance();int d=1;while(!isAtEnd()&&d>0){if(checkPunct("("))d++;else if(checkPunct(")"))d--;advance();}} if(checkPunct("{")){ advance();int d=1;while(!isAtEnd()&&d>0){if(checkPunct("{"))d++;else if(checkPunct("}"))d--;advance();}} return new Literal(Literal.Kind.BOOL,"true",t.line(),t.col(),List.of()); }
27022785
if (t.text().equals("R") && !isAtEnd() && check(CppLexerTokenType.STRING_LITERAL)) { advance(); String raw=advance().text(); return new Literal(Literal.Kind.STRING,"R"+raw,t.line(),t.col(),List.of()); }
27032786
// Could be a plain identifier, the start of a "::"-qualified
@@ -3296,6 +3379,18 @@ private List<Statement> parseStatementOrMultiDecl(List<CppLexerToken> leadingCom
32963379
}
32973380
return List.of(structStmt);
32983381
}
3382+
// "using T = Type;" local alias -- consume verbatim as ExprStatement
3383+
if (checkKeyword("using") && pos + 1 < tokens.size()
3384+
&& tokens.get(pos + 1).type() == CppLexerTokenType.IDENTIFIER
3385+
&& pos + 2 < tokens.size() && tokens.get(pos + 2).isOp("=")) {
3386+
int _us = pos;
3387+
while (!isAtEnd() && !checkPunct(";")) advance();
3388+
matchPunct(";");
3389+
StringBuilder _ur = new StringBuilder();
3390+
for (int _i = _us; _i < pos - 1; _i++) { if (_i > _us) _ur.append(" "); _ur.append(tokens.get(_i).text()); }
3391+
_ur.append(";");
3392+
return List.of(new ExprStatement(new Identifier(_ur.toString(), tokens.get(_us).line(), tokens.get(_us).col(), List.of()), tokens.get(_us).line(), tokens.get(_us).col(), leadingComments));
3393+
}
32993394
if (looksLikeDeclaration()) {
33003395
return new ArrayList<Statement>(parseDeclStatementsDesugared(leadingComments));
33013396
}
@@ -3326,6 +3421,13 @@ private Statement parseStatement(List<CppLexerToken> leadingComments) {
33263421
if (checkKeyword("constexpr") && pos + 1 < tokens.size() && tokens.get(pos + 1).isKeyword("if")) {
33273422
advance(); // consume constexpr, leave "if" for parseIf
33283423
}
3424+
// "typename T::member;" inside requires body -- type validity assertion
3425+
if (checkKeyword("typename")) {
3426+
CppLexerToken _t0 = peek(); advance();
3427+
try { parseTypeRef(); } catch (ParseException _e) {}
3428+
matchPunct(";");
3429+
return new ExprStatement(new Identifier("typename", _t0.line(), _t0.col(), List.of()), _t0.line(), _t0.col(), leadingComments);
3430+
}
33293431
// static_assert: consume entirely and emit as-is
33303432
if (checkKeyword("static_assert")) {
33313433
int startPos = pos; advance(); // consume static_assert

0 commit comments

Comments
 (0)