@@ -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