Skip to content

Commit 8f17e52

Browse files
committed
Round 11 CodeGen fixes + AST field additions
CodeGen: - operator[] and operator() no longer get friend prefix (C++23 member operators) - Template args in expression context: AutoParam<42>::value parsed correctly AST: - NamedType: added isRvalueRef field for && references - IfStatement: added isConstexpr field - Param: added isVariadic field Parser: - Deduction guide reconstruction now includes spaces between tokens - Friend functions parsed via parseFunctionOrVariable instead of swallowed
1 parent 1be0428 commit 8f17e52

3 files changed

Lines changed: 37 additions & 18 deletions

File tree

mode/CppMode.jar

314 Bytes
Binary file not shown.

src/java/CodeGen.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,9 @@ private static void emitTypeDef(StringBuilder sb, TypeDef td, int depth) {
193193
if (member instanceof FunctionDecl fd && fd.body() != null
194194
&& !fd.isConstructor() && !fd.isDestructor() && !fd.isStatic()
195195
&& fd.params().size() >= 2
196-
&& fd.name().startsWith("operator")) {
196+
&& fd.name().startsWith("operator")
197+
&& !fd.name().equals("operator[]")
198+
&& !fd.name().equals("operator()")) {
197199
indent(sb, depth + 1);
198200
sb.append("friend ");
199201
emitFunctionDecl(sb, fd, 0);
@@ -560,7 +562,7 @@ private static void emitParamList(StringBuilder sb, List<Param> params) {
560562
TypeRef base = p.type();
561563
if (base instanceof NamedType nt && nt.pointerDepth() > 0) {
562564
base = new NamedType(nt.baseName(), nt.templateArgs(),
563-
nt.pointerDepth() - 1, nt.isReference(), nt.isConst());
565+
nt.pointerDepth() - 1, nt.isReference(), nt.isConst(), false);
564566
}
565567
sb.append(renderTypeRef(base)).append(" (*").append(p.name()).append(")");
566568
for (int dim : p.innerArrayDims()) {

src/java/Parser.java

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -478,8 +478,9 @@ private List<TopLevelItem> parseTopLevelItem(List<CppLexerToken> leadingComments
478478
int startPos = pos;
479479
while (!isAtEnd() && !checkPunct(";")) advance();
480480
matchPunct(";");
481+
// Reconstruct without spaces, up to but not including the ";" we consumed
481482
StringBuilder raw = new StringBuilder();
482-
for (int i = startPos; i < pos; i++) { if (i > startPos) raw.append(" "); raw.append(tokens.get(i).text()); }
483+
for (int i = startPos; i < pos - 1; i++) { if (i > startPos) raw.append(" "); raw.append(tokens.get(i).text()); }
483484
raw.append(";");
484485
return List.of(new PreprocessorLine(raw.toString(), tokens.get(startPos).line(), tokens.get(startPos).col(), leadingComments));
485486
}
@@ -891,22 +892,17 @@ private List<TopLevelItem> parseClassMember(List<CppLexerToken> leadingComments,
891892
// friend declaration: "friend class Foo;" or "friend Box<U> makeBox(U v);"
892893
if (checkKeyword("friend")) {
893894
int startPos = pos; advance(); // consume friend
894-
// Consume to ; skipping over <> and ()
895-
int _fd = 0;
896-
while (!isAtEnd()) {
897-
if (checkPunct("(") || checkOp("<")) { _fd++; advance(); }
898-
else if (checkPunct(")") || checkOp(">")) { _fd--; advance(); }
899-
else if (checkOp(">>")) { _fd -= 2; advance(); }
900-
else if (checkPunct(";") && _fd == 0) { advance(); break; }
901-
else if (checkPunct("{") && _fd == 0) {
902-
// friend function with body
903-
int bd = 1; advance();
904-
while (!isAtEnd() && bd > 0) { if (checkPunct("{")) bd++; else if (checkPunct("}")) bd--; advance(); }
905-
break;
906-
}
907-
else advance();
895+
// "friend class/struct Foo" -- forward decl, consume verbatim
896+
if (checkKeyword("class") || checkKeyword("struct")) {
897+
while (!isAtEnd() && !checkPunct(";")) advance();
898+
matchPunct(";");
899+
return List.of(new PreprocessorLine("// friend class", tokens.get(startPos).line(), tokens.get(startPos).col(), leadingComments));
908900
}
909-
return List.of(new PreprocessorLine("// friend", tokens.get(startPos).line(), tokens.get(startPos).col(), leadingComments));
901+
// "friend RetType funcName(...)" or "friend RetType operator...()" -- parse as function
902+
// Consume template params if present
903+
List<String> friendTemplateParams = List.of();
904+
if (matchKeyword("template")) friendTemplateParams = parseTemplateParamList();
905+
return parseFunctionOrVariable(leadingComments, friendTemplateParams, false);
910906
}
911907
// explicit(...): conditional explicit specifier (C++20)
912908
if (checkKeyword("explicit") && pos + 1 < tokens.size() && tokens.get(pos + 1).isPunct("(")) {
@@ -2293,6 +2289,27 @@ private Expr parsePostfix() {
22932289
expr = new Identifier("::" + member,
22942290
peek().line(), peek().col(), List.of());
22952291
}
2292+
// Template args in expression: "AutoParam<42>::value"
2293+
} else if (checkOp("<") && expr instanceof Identifier eid && looksLikeTemplateArgList()) {
2294+
int argStart = pos;
2295+
advance(); // consume <
2296+
int depth = 1, pd = 0, bd = 0;
2297+
while (!isAtEnd() && depth > 0) {
2298+
if (checkPunct("(") || checkPunct("[")) pd++;
2299+
else if (checkPunct(")") || checkPunct("]")) pd--;
2300+
else if (checkPunct("{")) bd++;
2301+
else if (checkPunct("}")) bd--;
2302+
else if (pd == 0 && bd == 0) {
2303+
if (checkOp("<")) depth++;
2304+
else if (checkOp(">")) { depth--; if (depth == 0) { advance(); break; } }
2305+
else if (checkOp(">>")) { depth -= 2; splitTrailingShiftIntoTwoCloseAngles(); if (depth <= 0) { advance(); break; } }
2306+
}
2307+
if (depth > 0) advance();
2308+
}
2309+
StringBuilder targs = new StringBuilder(eid.name()).append("<");
2310+
for (int i = argStart + 1; i < pos - 1; i++) targs.append(tokens.get(i).text());
2311+
targs.append(">");
2312+
expr = new Identifier(targs.toString(), eid.line(), eid.col(), List.of());
22962313
} else if (checkOp("->*")) {
22972314
// "->*" lexed as a single token
22982315
CppLexerToken t = advance();

0 commit comments

Comments
 (0)