@@ -346,7 +346,7 @@ private List<TopLevelItem> parseTopLevelItem(List<CppLexerToken> leadingComments
346346 if (checkKeyword ("enum" )) {
347347 return List .of (parseEnumDecl (leadingComments ));
348348 }
349- if (checkKeyword ("namespace" )) {
349+ if (checkKeyword ("namespace" ) || ( checkKeyword ( "inline" ) && pos + 1 < tokens . size () && tokens . get ( pos + 1 ). isKeyword ( "namespace" )) ) {
350350 return List .of (parseNamespaceDecl (leadingComments ));
351351 }
352352 // typedef -- emit verbatim as-is (covers function-pointer typedefs, etc.)
@@ -430,6 +430,25 @@ private List<TopLevelItem> parseTopLevelItem(List<CppLexerToken> leadingComments
430430 return List .of (parseFunctionOrConstructorOrDestructor (leadingComments , templateParams ));
431431 }
432432
433+ // Deduction guide: "Wrapper(const char*) -> Wrapper<std::string>;"
434+ if (check (CppLexerTokenType .IDENTIFIER ) && pos + 1 < tokens .size () && tokens .get (pos + 1 ).isPunct ("(" )) {
435+ int scan = pos + 2 ; int depth = 1 ;
436+ while (scan < tokens .size () && depth > 0 ) {
437+ if (tokens .get (scan ).isPunct ("(" )) depth ++;
438+ else if (tokens .get (scan ).isPunct (")" )) depth --;
439+ scan ++;
440+ }
441+ if (scan < tokens .size () && tokens .get (scan ).isPunct ("->" )) {
442+ int startPos = pos ;
443+ while (!isAtEnd () && !checkPunct (";" )) advance ();
444+ matchPunct (";" );
445+ StringBuilder raw = new StringBuilder ();
446+ for (int i = startPos ; i < pos ; i ++) { if (i > startPos ) raw .append (" " ); raw .append (tokens .get (i ).text ()); }
447+ raw .append (";" );
448+ return List .of (new PreprocessorLine (raw .toString (), tokens .get (startPos ).line (), tokens .get (startPos ).col (), leadingComments ));
449+ }
450+ }
451+
433452 return parseFunctionOrVariable (leadingComments , templateParams , true );
434453 }
435454
@@ -778,6 +797,15 @@ private List<TopLevelItem> parseClassMember(List<CppLexerToken> leadingComments,
778797 if (checkKeyword ("enum" )) {
779798 return List .of (parseEnumDecl (leadingComments ));
780799 }
800+ // using X = Type; inside a struct/class body -- consume verbatim
801+ if (checkKeyword ("using" ) && !tokens .get (pos + 1 ).isKeyword ("namespace" )) {
802+ int startPos = pos ;
803+ { int _d =0 ; while (!isAtEnd ()){if (checkPunct ("{" ))_d ++;else if (checkPunct ("}" )){if (_d ==0 ){advance ();break ;}_d --;}else if (checkPunct (";" )&&_d ==0 )break ;advance ();} matchPunct (";" ); }
804+ StringBuilder raw = new StringBuilder ();
805+ for (int i = startPos ; i < pos - 1 ; i ++) { if (i > startPos ) raw .append (" " ); raw .append (tokens .get (i ).text ()); }
806+ raw .append (";" );
807+ return List .of (new PreprocessorLine (raw .toString (), tokens .get (startPos ).line (), tokens .get (startPos ).col (), leadingComments ));
808+ }
781809 // Destructor dispatch: "~Name() {...}" or "virtual ~Name() {...}" --
782810 // must look one token past an optional leading "virtual", since that
783811 // keyword (confirmed common on destructors, e.g. "virtual ~LSystem()")
@@ -830,8 +858,7 @@ private FunctionDecl parseFunctionOrConstructorOrDestructor(List<CppLexerToken>
830858 }
831859 }
832860
833- // Consume trailing qualifiers: noexcept, noexcept(expr), override, final
834- // These can appear after the param list in any order before "= 0" or body.
861+ // Consume trailing qualifiers: noexcept, noexcept(expr), override, final, requires
835862 while (true ) {
836863 if (checkKeyword ("noexcept" )) {
837864 advance ();
@@ -840,6 +867,10 @@ private FunctionDecl parseFunctionOrConstructorOrDestructor(List<CppLexerToken>
840867 advance ();
841868 } else if (check (CppLexerTokenType .IDENTIFIER ) && peek ().text ().equals ("final" )) {
842869 advance ();
870+ } else if (check (CppLexerTokenType .IDENTIFIER ) && peek ().text ().equals ("requires" )) {
871+ advance ();
872+ if (checkPunct ("(" )) { advance (); int d =1 ; while (!isAtEnd ()&&d >0 ){if (checkPunct ("(" ))d ++;else if (checkPunct (")" ))d --;advance ();} }
873+ else { while (!isAtEnd () && !checkPunct ("{" ) && !checkPunct (";" ) && !checkOp ("=" )) { if (checkOp ("<" )) { advance (); int d =1 ; while (!isAtEnd ()&&d >0 ){if (checkOp ("<" ))d ++;else if (checkOp (">" ))d --;advance ();} } else advance (); } }
843874 } else break ;
844875 }
845876
@@ -875,7 +906,8 @@ private FunctionDecl parseFunctionOrConstructorOrDestructor(List<CppLexerToken>
875906 }
876907
877908 private FunctionDecl .ConstructorInit parseConstructorInitEntry () {
878- String memberName = expectIdentifier ().text ();
909+ // Base class names can be qualified: "std::runtime_error(msg)"
910+ String memberName = parseQualifiedTypeName ();
879911 expectPunct ("(" );
880912 List <Expr > args = new ArrayList <>();
881913 if (!checkPunct (")" )) {
@@ -972,8 +1004,9 @@ && looksLikeParamList()) {
9721004 boolean isOverride = false ;
9731005 boolean isMethodConst = false ;
9741006 // trailing const/override may appear in either order
975- for (int i = 0 ; i < 2 ; i ++) {
1007+ for (int i = 0 ; i < 3 ; i ++) {
9761008 if (matchKeyword ("const" )) { isMethodConst = true ; continue ; }
1009+ if (matchKeyword ("volatile" )) { continue ; } // const volatile method
9771010 if (matchKeyword ("override" )) { isOverride = true ; continue ; }
9781011 }
9791012 // Trailing return type: "auto f() -> ReturnType"
@@ -984,7 +1017,7 @@ && looksLikeParamList()) {
9841017 trailingReturnType = parseTypeRef ();
9851018 }
9861019 TypeRef effectiveReturnType = (trailingReturnType != null ) ? trailingReturnType : type ;
987- // Consume trailing qualifiers: noexcept, noexcept(expr), override, final
1020+ // Consume trailing qualifiers: noexcept, noexcept(expr), override, final, requires
9881021 while (true ) {
9891022 if (checkKeyword ("noexcept" )) {
9901023 advance ();
@@ -993,6 +1026,16 @@ && looksLikeParamList()) {
9931026 isOverride = true ; advance ();
9941027 } else if (check (CppLexerTokenType .IDENTIFIER ) && peek ().text ().equals ("final" )) {
9951028 advance ();
1029+ } else if (check (CppLexerTokenType .IDENTIFIER ) && peek ().text ().equals ("requires" )) {
1030+ // trailing requires clause: "requires expr" -- consume to { or ;
1031+ advance ();
1032+ if (checkPunct ("(" )) { advance (); int d =1 ; while (!isAtEnd ()&&d >0 ){if (checkPunct ("(" ))d ++;else if (checkPunct (")" ))d --;advance ();} }
1033+ else { // bare expression like "requires std::is_arithmetic_v<T>"
1034+ while (!isAtEnd () && !checkPunct ("{" ) && !checkPunct (";" ) && !checkOp ("=" )) {
1035+ if (checkOp ("<" )) { advance (); int d =1 ; while (!isAtEnd ()&&d >0 ){if (checkOp ("<" ))d ++;else if (checkOp (">" ))d --;advance ();} }
1036+ else advance ();
1037+ }
1038+ }
9961039 } else break ;
9971040 }
9981041 // Pure-virtual specifier ("= 0") or = default / = delete
@@ -1153,7 +1196,10 @@ private String parseFunctionOrVariableName() {
11531196 }
11541197 if (checkKeyword ("new" ) || checkKeyword ("delete" )) {
11551198 CppLexerToken kw = advance ();
1156- return opKw .text () + " " + kw .text ();
1199+ String opName = opKw .text () + " " + kw .text ();
1200+ // operator new[] / operator delete[]
1201+ if (checkPunct ("[" )) { advance (); expectPunct ("]" ); opName += "[]" ; }
1202+ return opName ;
11571203 }
11581204 // Cast operator: "operator int", "operator float", "operator bool", etc.
11591205 // ONLY fire for actual C++ primitive type keywords, not arbitrary
@@ -1351,7 +1397,9 @@ private EnumDecl parseEnumDecl(List<CppLexerToken> leadingComments) {
13511397 }
13521398
13531399 private NamespaceDecl parseNamespaceDecl (List <CppLexerToken > leadingComments ) {
1354- CppLexerToken start = expectKeyword ("namespace" );
1400+ CppLexerToken start = peek ();
1401+ boolean isInlineNs = matchKeyword ("inline" ); // "inline namespace"
1402+ expectKeyword ("namespace" );
13551403 StringBuilder nameBuilder = new StringBuilder (expectIdentifier ().text ());
13561404 while (checkPunct ("::" )) { advance (); nameBuilder .append ("::" ).append (expectIdentifier ().text ()); }
13571405 String name = nameBuilder .toString ();
@@ -1364,7 +1412,7 @@ private NamespaceDecl parseNamespaceDecl(List<CppLexerToken> leadingComments) {
13641412 items .addAll (parseTopLevelItem (comments ));
13651413 }
13661414 expectPunct ("}" );
1367- return new NamespaceDecl (name , items , start .line (), start .col (), leadingComments );
1415+ return new NamespaceDecl (name , isInlineNs , items , start .line (), start .col (), leadingComments );
13681416 }
13691417
13701418 private UsingNamespaceDecl parseUsingNamespaceDecl (List <CppLexerToken > leadingComments ) {
@@ -1545,7 +1593,14 @@ else if (checkOp(">")) {
15451593 depth --; advance ();
15461594 }
15471595 else if (checkOp (">>" )) {
1548- if (depth <= 1 ) break ;
1596+ if (depth == 1 ) {
1597+ // Split ">>" into two ">" -- first closes inner template,
1598+ // second will close outer template param list
1599+ splitTrailingShiftIntoTwoCloseAngles ();
1600+ depth --; advance (); // consume first ">"
1601+ break ; // second ">" left for outer list
1602+ }
1603+ if (depth == 0 ) break ;
15491604 depth -= 2 ; advance ();
15501605 }
15511606 else if (depth == 0 && checkPunct ("," )) break ;
@@ -2021,6 +2076,14 @@ private Expr parseCast() {
20212076
20222077 private Expr parseNew () {
20232078 CppLexerToken start = expectKeyword ("new" );
2079+ // Placement new: "new (buf) Type(args)" -- consume placement args first
2080+ if (checkPunct ("(" )) {
2081+ advance (); int _pd =1 ;
2082+ while (!isAtEnd () && _pd > 0 ) {
2083+ if (checkPunct ("(" )) _pd ++; else if (checkPunct (")" )) _pd --;
2084+ advance ();
2085+ }
2086+ }
20242087 TypeRef type = parseTypeRef ();
20252088 if (matchPunct ("[" )) {
20262089 Expr sizeExpr = parseExpr ();
@@ -2074,7 +2137,14 @@ private Expr parsePostfix() {
20742137 expr = new BinaryExpr (isArrow ? "->*" : ".*" , expr , rhs , t .line (), t .col (), List .of ());
20752138 continue ;
20762139 }
2077- String member = expectIdentifierOrKeywordName ();
2140+ // Explicit destructor call: "p->~PoolObj()"
2141+ String member ;
2142+ if (checkOp ("~" )) {
2143+ advance (); // consume ~
2144+ member = "~" + expectIdentifier ().text ();
2145+ } else {
2146+ member = expectIdentifierOrKeywordName ();
2147+ }
20782148 // Sibling fix to the std::vector<int>(...) bug found via
20792149 // RealHeaderStressTest: a member name can ALSO be
20802150 // followed by explicit template arguments before the
@@ -2138,8 +2208,11 @@ private List<Expr> parseArgList() {
21382208 List <Expr > args = new ArrayList <>();
21392209 if (!checkPunct (")" )) {
21402210 args .add (parseExpr ());
2211+ matchPunct ("..." ); // pack expansion: "f(args...)"
21412212 while (matchPunct ("," )) {
2213+ if (checkPunct (")" )) break ;
21422214 args .add (parseExpr ());
2215+ matchPunct ("..." ); // pack expansion
21432216 }
21442217 }
21452218 expectPunct (")" );
@@ -2219,6 +2292,19 @@ else if (checkPunct(",") && depth == 0) {
22192292 if (checkPunct ("{" )) {
22202293 return parseInitializerList ();
22212294 }
2295+ // Global scope resolution: "::operator new(...)" or "::SomeFunc()"
2296+ if (checkPunct ("::" )) {
2297+ advance (); // consume ::
2298+ // Parse what follows as an identifier/operator name
2299+ if (checkKeyword ("operator" )) {
2300+ String opName = "::" + parseFunctionOrVariableName ();
2301+ return new Identifier (opName , t .line (), t .col (), List .of ());
2302+ }
2303+ if (check (CppLexerTokenType .IDENTIFIER )) {
2304+ String name = advance ().text ();
2305+ return new Identifier ("::" + name , t .line (), t .col (), List .of ());
2306+ }
2307+ }
22222308 // Wide/unicode string prefix: L"..." u"..." U"..." u8"..."
22232309 if (t .type () == CppLexerTokenType .IDENTIFIER
22242310 && (t .text ().equals ("L" ) || t .text ().equals ("u" ) || t .text ().equals ("U" ) || t .text ().equals ("u8" ))
@@ -2588,6 +2674,7 @@ private Param parseParam() {
25882674 }
25892675
25902676 TypeRef type = parseTypeRef ();
2677+ matchPunct ("..." ); // pack expansion after type: "Rest... rest"
25912678
25922679 // Member pointer parameter: "int Widget::* dp" or "int (Widget::* mp)(int) const"
25932680 if (check (CppLexerTokenType .IDENTIFIER ) && pos + 1 < tokens .size ()
@@ -2767,6 +2854,19 @@ private Block parseBlock() {
27672854 */
27682855 private List <Statement > parseStatementOrMultiDecl (List <CppLexerToken > leadingComments ) {
27692856 if (isStructuredBindingStart ()) return List .of (parseStructuredBinding (leadingComments ));
2857+ // Local struct/class definition: "struct Point { float x, y; }; Point p{...}"
2858+ if ((checkKeyword ("struct" ) || checkKeyword ("class" ))
2859+ && pos + 1 < tokens .size ()
2860+ && (tokens .get (pos + 1 ).type () == CppLexerTokenType .IDENTIFIER
2861+ || tokens .get (pos + 1 ).isPunct ("{" ))) {
2862+ TypeDef td = parseTypeDef (leadingComments , List .of ());
2863+ matchPunct (";" );
2864+ // If a variable declaration follows, parse it
2865+ if (looksLikeDeclaration ()) {
2866+ return new java .util .ArrayList <>(parseDeclStatementsDesugared (List .of ()));
2867+ }
2868+ return List .of (new ExprStatement (new Identifier ("" , td .line (), td .col (), List .of ()), td .line (), td .col (), leadingComments ));
2869+ }
27702870 if (looksLikeDeclaration ()) {
27712871 return new ArrayList <Statement >(parseDeclStatementsDesugared (leadingComments ));
27722872 }
@@ -2812,6 +2912,25 @@ private Statement parseStatement(List<CppLexerToken> leadingComments) {
28122912 CppLexerToken t0 = tokens .get (startPos );
28132913 return new ExprStatement (new Identifier (raw .toString (), t0 .line (), t0 .col (), List .of ()), t0 .line (), t0 .col (), leadingComments );
28142914 }
2915+ // throw statement: "throw expr;" or bare "throw;"
2916+ if (checkKeyword ("throw" )) {
2917+ CppLexerToken t0 = advance ();
2918+ if (checkPunct (";" )) { advance (); return new ReturnStatement (null , t0 .line (), t0 .col (), leadingComments ); }
2919+ Expr val = parseExpr ();
2920+ expectPunct (";" );
2921+ // Encode as ReturnStatement with a UnaryExpr("throw", val) -- CodeGen emits via renderExpr
2922+ return new ExprStatement (new UnaryExpr ("throw " , val , t0 .line (), t0 .col (), List .of ()), t0 .line (), t0 .col (), leadingComments );
2923+ }
2924+
2925+ // Local struct/class definition inside a function body
2926+ if ((checkKeyword ("struct" ) || checkKeyword ("class" ))
2927+ && pos + 1 < tokens .size ()
2928+ && (tokens .get (pos + 1 ).type () == CppLexerTokenType .IDENTIFIER
2929+ || tokens .get (pos + 1 ).isPunct ("{" ))) {
2930+ TypeDef td = parseTypeDef (leadingComments , List .of ());
2931+ matchPunct (";" );
2932+ return new ExprStatement (new Identifier ("" , td .line (), td .col (), List .of ()), td .line (), td .col (), leadingComments );
2933+ }
28152934 if (checkKeyword ("if" )) return parseIf (leadingComments );
28162935 if (checkKeyword ("for" )) return parseForOrRangeFor (leadingComments );
28172936 if (checkKeyword ("while" )) return parseWhile (leadingComments );
@@ -3150,7 +3269,13 @@ private boolean looksLikeDeclaration() {
31503269 if (checkKeyword ("static" )) advance ();
31513270 if (checkKeyword ("volatile" )) advance ();
31523271 if (checkKeyword ("const" )) advance ();
3153- if (checkKeyword ("volatile" )) advance (); // volatile after const
3272+ if (checkKeyword ("volatile" )) advance (); // vol
3273+ // alignas specifier: "alignas(T) type name"
3274+ if (checkKeyword ("alignas" ) && pos + 1 < tokens .size () && tokens .get (pos + 1 ).isPunct ("(" )) {
3275+ advance (); advance (); int _ad =1 ;
3276+ while (!isAtEnd () && _ad > 0 ) { if (checkPunct ("(" )) _ad ++; else if (checkPunct (")" )) _ad --; advance (); }
3277+ }
3278+ // volatile after const
31543279 if (checkKeyword ("constexpr" )) advance ();
31553280 if (checkKeyword ("inline" )) advance ();
31563281 if (checkKeyword ("static" )) advance (); // tolerate either order
@@ -3200,6 +3325,11 @@ private List<DeclStatement> parseDeclStatementsDesugared(List<CppLexerToken> lea
32003325 // statement, then "int" showed up where a ";" was expected).
32013326 // Tolerate either order ("static const" or "const static"),
32023327 // mirroring the top-level path's own tolerance.
3328+ // alignas specifier: "alignas(T) type name"
3329+ if (checkKeyword ("alignas" ) && pos + 1 < tokens .size () && tokens .get (pos + 1 ).isPunct ("(" )) {
3330+ advance (); advance (); int _ad =1 ;
3331+ while (!isAtEnd () && _ad > 0 ) { if (checkPunct ("(" )) _ad ++; else if (checkPunct (")" )) _ad --; advance (); }
3332+ }
32033333 boolean isStatic = matchKeyword ("static" );
32043334 matchKeyword ("volatile" ); // consume volatile qualifier at statement scope
32053335 boolean isConst = matchKeyword ("const" );
0 commit comments