Skip to content

Commit 1aa51ca

Browse files
committed
Round 5: constexpr virtual, designated init, pack expansion, if constexpr fix
Parser: - constexpr virtual: consume virtual after constexpr in qualifier loop - Designated initializers: .field = expr in brace-init - Pack expansion in base class list: Bases... consumed and preserved - Pack expansion in constructor init list: Bases()... - if constexpr: fix double-consume of constexpr keyword - NTTP arithmetic expressions: N-1, N+1 in template args - parseArgList: consume ... after args (pack expansion) - inline namespace: preserve isInline in NamespaceDecl - parseBaseClassEntry: preserve ... in returned base name CodeGen: - NamespaceDecl.isInline emitted as inline keyword - ConstructorInit pack expansion: Bases()... not Bases...()
1 parent f903ec4 commit 1aa51ca

3 files changed

Lines changed: 40 additions & 6 deletions

File tree

mode/CppMode.jar

583 Bytes
Binary file not shown.

src/java/CodeGen.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,12 +512,17 @@ private static void emitFunctionDecl(StringBuilder sb, FunctionDecl fd, int dept
512512
for (int i = 0; i < fd.initializerList().size(); i++) {
513513
if (i > 0) sb.append(", ");
514514
FunctionDecl.ConstructorInit e = fd.initializerList().get(i);
515-
sb.append(e.memberName()).append('(');
515+
// Pack expansion: "Bases()..." stored as memberName="Bases..."
516+
String mname = e.memberName();
517+
boolean isPack = mname.endsWith("...");
518+
if (isPack) mname = mname.substring(0, mname.length() - 3);
519+
sb.append(mname).append('(');
516520
for (int j = 0; j < e.args().size(); j++) {
517521
if (j > 0) sb.append(", ");
518522
sb.append(renderExpr(e.args().get(j)));
519523
}
520524
sb.append(')');
525+
if (isPack) sb.append("...");
521526
}
522527
}
523528

src/java/Parser.java

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,9 @@ private String parseBaseClassEntry() {
739739
sb.append('>');
740740
name = sb.toString();
741741
}
742-
return isVirtualBase ? "virtual " + name : name;
742+
boolean isPackExpansion = matchPunct("..."); // pack expansion in base class list: "Bases..."
743+
String suffix = isPackExpansion ? "..." : "";
744+
return isVirtualBase ? "virtual " + name + suffix : name + suffix;
743745
}
744746

745747
/**
@@ -852,9 +854,13 @@ private FunctionDecl parseFunctionOrConstructorOrDestructor(List<CppLexerToken>
852854

853855
List<FunctionDecl.ConstructorInit> initList = new ArrayList<>();
854856
if (!isDestructor && matchPunct(":")) {
855-
initList.add(parseConstructorInitEntry());
857+
FunctionDecl.ConstructorInit ci1 = parseConstructorInitEntry();
858+
if (matchPunct("...")) ci1 = new FunctionDecl.ConstructorInit(ci1.memberName() + "...", ci1.args());
859+
initList.add(ci1);
856860
while (matchPunct(",")) {
857-
initList.add(parseConstructorInitEntry());
861+
FunctionDecl.ConstructorInit ci = parseConstructorInitEntry();
862+
if (matchPunct("...")) ci = new FunctionDecl.ConstructorInit(ci.memberName() + "...", ci.args());
863+
initList.add(ci);
858864
}
859865
}
860866

@@ -969,6 +975,7 @@ private List<TopLevelItem> parseFunctionOrVariable(List<CppLexerToken> leadingCo
969975
matchKeyword("volatile"); // consume volatile qualifier
970976
boolean isConst = matchKeyword("const");
971977
boolean isConstexprFn = matchKeyword("constexpr"); if (isConstexprFn) isConst = true;
978+
if (!isVirtual) isVirtual = matchKeyword("virtual"); // constexpr virtual
972979
if (!isStatic) isStatic = matchKeyword("static");
973980
if (!isConst) isConst = matchKeyword("const");
974981
matchKeyword("volatile"); // volatile may appear after const
@@ -1053,6 +1060,7 @@ && looksLikeParamList()) {
10531060
}
10541061
// Constructor initializer list: ": mem(val), mem2(val2)"
10551062
if (matchPunct(":") && !checkPunct(":")) {
1063+
System.err.println("[INITV] consuming init list, next=" + peek().text());
10561064
// consume initializer list entries until { or ;
10571065
int _d = 0;
10581066
while (!isAtEnd()) {
@@ -1727,6 +1735,20 @@ private TypeRef parseTemplateArg() {
17271735
if (checkPunct("(")) {
17281736
return parseFunctionSignatureTail(maybeReturnType);
17291737
}
1738+
// NTTP arithmetic expression: "N-1", "N*2", "N+1" etc.
1739+
// After parsing the base type/value, consume arithmetic ops and operands
1740+
if (maybeReturnType instanceof NamedType nt && !nt.baseName().equals("void")) {
1741+
StringBuilder expr = new StringBuilder(nt.baseName());
1742+
while (!isAtEnd() && (checkOp("+") || checkOp("-") || checkOp("*") || checkOp("/") || checkOp("%"))) {
1743+
expr.append(advance().text());
1744+
if (!isAtEnd() && (check(CppLexerTokenType.INT_LITERAL) || check(CppLexerTokenType.IDENTIFIER))) {
1745+
expr.append(advance().text());
1746+
}
1747+
}
1748+
if (expr.length() > nt.baseName().length()) {
1749+
return new NamedType(expr.toString(), List.of(), 0, false, false);
1750+
}
1751+
}
17301752
return maybeReturnType;
17311753
}
17321754

@@ -2548,6 +2570,14 @@ private Expr parseInitializerElement() {
25482570
if (checkPunct("{")) {
25492571
return parseInitializerList(); // anonymous nested brace-init
25502572
}
2573+
// Designated initializer: ".field = expr" (C++20)
2574+
if (checkPunct(".") && pos + 1 < tokens.size()
2575+
&& tokens.get(pos + 1).type() == CppLexerTokenType.IDENTIFIER
2576+
&& pos + 2 < tokens.size() && tokens.get(pos + 2).isOp("=")) {
2577+
advance(); // consume "."
2578+
advance(); // consume field name
2579+
advance(); // consume "="
2580+
}
25512581
Expr e = parseExpr();
25522582
matchPunct("..."); // pack expansion in brace-init: "{args...}"
25532583
return e;
@@ -2953,8 +2983,7 @@ private Statement parseStatement(List<CppLexerToken> leadingComments) {
29532983

29542984
private Statement parseIf(List<CppLexerToken> leadingComments) {
29552985
CppLexerToken start = expectKeyword("if");
2956-
matchKeyword("constexpr"); // C++17 if constexpr
2957-
boolean isConstexpr = matchKeyword("constexpr");
2986+
boolean isConstexpr = matchKeyword("constexpr"); // C++17 if constexpr
29582987
expectPunct("(");
29592988
// C++17 if-init-statement: if (init; cond) -- collect init decls,
29602989
// wrap the IfStatement in a Block so the init vars are in scope.

0 commit comments

Comments
 (0)