@@ -861,6 +861,14 @@ private List<TopLevelItem> parseClassMember(List<CppLexerToken> leadingComments,
861861 if (checkKeyword ("enum" )) {
862862 return List .of (parseEnumDecl (leadingComments ));
863863 }
864+ // static_assert inside class body
865+ if (checkKeyword ("static_assert" )) {
866+ int startPos = pos ; advance ();
867+ expectPunct ("(" ); int _d =1 ;
868+ while (!isAtEnd () && _d > 0 ) { if (checkPunct ("(" )) _d ++; else if (checkPunct (")" )) _d --; advance (); }
869+ matchPunct (";" );
870+ return List .of (new PreprocessorLine ("// static_assert" , tokens .get (startPos ).line (), tokens .get (startPos ).col (), leadingComments ));
871+ }
864872 // using X = Type; inside a struct/class body -- consume verbatim
865873 if (checkKeyword ("using" ) && !tokens .get (pos + 1 ).isKeyword ("namespace" )) {
866874 int startPos = pos ;
@@ -1229,7 +1237,7 @@ && looksLikeParamList()) {
12291237 TypeRef declaratorType = type ;
12301238 if (type instanceof NamedType nt ) {
12311239 declaratorType = new NamedType (nt .baseName (), nt .templateArgs (),
1232- extraPointerDepth , extraIsReference , nt .isConst ());
1240+ extraPointerDepth , extraIsReference , nt .isConst (), false );
12331241 }
12341242 result .add (parseOneTopLevelDeclarator (declaratorType , nextName , isConst , isStatic , List .of (), start , List .of ()));
12351243 }
@@ -1372,6 +1380,7 @@ private String parseFunctionOrVariableName() {
13721380 if (check (CppLexerTokenType .KEYWORD ) && !checkKeyword ("const" ) && !checkKeyword ("override" )
13731381 && !checkKeyword ("virtual" ) && !checkKeyword ("static" )
13741382 && !checkKeyword ("inline" ) && !checkKeyword ("explicit" )
1383+ && !checkKeyword ("operator" )
13751384 && !PSEUDO_TYPE_KEYWORDS_USABLE_AS_NAMES .contains (peek ().text ())) {
13761385 CppLexerToken castTok = advance ();
13771386 String suffix = "" ;
@@ -1541,6 +1550,12 @@ private NamespaceDecl parseNamespaceDecl(List<CppLexerToken> leadingComments) {
15411550 StringBuilder nameBuilder = new StringBuilder (expectIdentifier ().text ());
15421551 while (checkPunct ("::" )) { advance (); nameBuilder .append ("::" ).append (expectIdentifier ().text ()); }
15431552 String name = nameBuilder .toString ();
1553+ if (matchOp ("=" )) {
1554+ StringBuilder alias = new StringBuilder ();
1555+ while (!isAtEnd () && !checkPunct (";" )) { alias .append (peek ().text ()); advance (); }
1556+ matchPunct (";" );
1557+ return new NamespaceDecl (name , false , List .of (), start .line (), start .col (), leadingComments );
1558+ }
15441559 expectPunct ("{" );
15451560 List <TopLevelItem > items = new ArrayList <>();
15461561 while (!checkPunct ("}" )) {
@@ -1614,7 +1629,7 @@ private TypeRef parseTypeRefAfterConst(boolean isConst) {
16141629 else { dtExpr .append (peek ().text ()); advance (); }
16151630 }
16161631 dtExpr .append (")" );
1617- return new NamedType (dtExpr .toString (), List .of (), 0 , false , isConst );
1632+ return new NamedType (dtExpr .toString (), List .of (), 0 , false , isConst , false );
16181633 }
16191634
16201635 String baseName = parseQualifiedTypeName ();
@@ -1808,30 +1823,30 @@ private void splitTrailingShiftIntoTwoCloseAngles() {
18081823 private TypeRef parseTemplateArg () {
18091824 if (checkKeyword ("true" ) || checkKeyword ("false" )) {
18101825 String val = advance ().text ();
1811- return new NamedType (val , List .of (), 0 , false , false );
1826+ return new NamedType (val , List .of (), 0 , false , false , false );
18121827 }
18131828 if (check (CppLexerTokenType .INT_LITERAL ) || check (CppLexerTokenType .FLOAT_LITERAL )
18141829 || check (CppLexerTokenType .CHAR_LITERAL )) {
18151830 String val = advance ().text ();
1816- return new NamedType (val , List .of (), 0 , false , false );
1831+ return new NamedType (val , List .of (), 0 , false , false , false );
18171832 }
18181833 if (checkOp ("-" ) && pos + 1 < tokens .size () &&
18191834 (tokens .get (pos + 1 ).type () == CppLexerTokenType .INT_LITERAL ||
18201835 tokens .get (pos + 1 ).type () == CppLexerTokenType .FLOAT_LITERAL )) {
18211836 advance (); String val = "-" + advance ().text ();
1822- return new NamedType (val , List .of (), 0 , false , false );
1837+ return new NamedType (val , List .of (), 0 , false , false , false );
18231838 }
18241839 // Address-of non-type template argument: "&Widget::value", "&Class::method"
18251840 if (checkOp ("&" )) {
18261841 advance (); // consume &
18271842 String name = parseQualifiedTypeName (); // Widget::value
1828- return new NamedType ("&" + name , List .of (), 0 , false , false );
1843+ return new NamedType ("&" + name , List .of (), 0 , false , false , false );
18291844 }
18301845 // Logical negation: "!std::is_integral<T>::value" in enable_if<!...>
18311846 if (checkOp ("!" )) {
18321847 advance (); // consume '!'
18331848 parseTemplateDefaultValue (); // consume the rest of the expression
1834- return new NamedType ("!..." , List .of (), 0 , false , false );
1849+ return new NamedType ("!..." , List .of (), 0 , false , false , false );
18351850 }
18361851 // decltype as template argument: "Pair<decltype(x), decltype(z)>"
18371852 // Must be handled before parseTypeRef() which would consume "decltype" as a type.
@@ -1846,13 +1861,13 @@ private TypeRef parseTemplateArg() {
18461861 else { dt .append (peek ().text ()); advance (); }
18471862 }
18481863 dt .append (")" );
1849- return new NamedType (dt .toString (), List .of (), 0 , false , false );
1864+ return new NamedType (dt .toString (), List .of (), 0 , false , false , false );
18501865 }
18511866 // Pack expansion "..." trailing a type: "Ts..." in template args
18521867 // Also handles standalone "..." as a variadic marker
18531868 if (checkPunct ("..." )) {
18541869 advance ();
1855- return new NamedType ("..." , List .of (), 0 , false , false );
1870+ return new NamedType ("..." , List .of (), 0 , false , false , false );
18561871 }
18571872 // sizeof expression: sizeof(T) or sizeof...(Args)
18581873 if (checkKeyword ("sizeof" )) {
@@ -1862,7 +1877,7 @@ private TypeRef parseTemplateArg() {
18621877 advance (); int d = 1 ;
18631878 while (!isAtEnd () && d > 0 ) { if (checkPunct ("(" )) d ++; else if (checkPunct (")" )) d --; advance (); }
18641879 }
1865- return new NamedType ("sizeof(...)" , List .of (), 0 , false , false );
1880+ return new NamedType ("sizeof(...)" , List .of (), 0 , false , false , false );
18661881 }
18671882 TypeRef maybeReturnType = parseTypeRef ();
18681883 if (checkPunct ("(" )) {
@@ -1879,7 +1894,7 @@ private TypeRef parseTemplateArg() {
18791894 }
18801895 }
18811896 if (expr .length () > nt .baseName ().length ()) {
1882- return new NamedType (expr .toString (), List .of (), 0 , false , false );
1897+ return new NamedType (expr .toString (), List .of (), 0 , false , false , false );
18831898 }
18841899 }
18851900 return maybeReturnType ;
@@ -2260,6 +2275,9 @@ private Expr parseNew() {
22602275
22612276 private Expr parsePostfix () {
22622277 Expr expr = parsePrimary ();
2278+ if (checkPunct ("..." ) && pos + 1 < tokens .size () && tokens .get (pos + 1 ).isPunct ("[" )) {
2279+ advance (); // pack indexing: args...[0]
2280+ }
22632281 while (true ) {
22642282 if (checkPunct ("::" )) {
22652283 // Static member / scope resolution in expression context:
@@ -2336,6 +2354,7 @@ private Expr parsePostfix() {
23362354 } else if (checkPunct ("[" )) {
23372355 CppLexerToken t = advance ();
23382356 Expr index = parseExpr ();
2357+ while (matchPunct ("," )) parseExpr (); // multi-dim subscript C++23
23392358 expectPunct ("]" );
23402359 expr = new IndexExpr (expr , index , t .line (), t .col (), List .of ());
23412360 } else if (checkOp ("++" ) || checkOp ("--" )) {
@@ -2664,7 +2683,7 @@ private Statement parseStructuredBinding(List<CppLexerToken> leadingComments) {
26642683 Expr initializer = parseExpr ();
26652684 expectPunct (";" );
26662685 String bindingName = "[" + String .join (", " , names ) + "]" ;
2667- return new DeclStatement (new NamedType ("auto" , List .of (), 0 , false , false ),
2686+ return new DeclStatement (new NamedType ("auto" , List .of (), 0 , false , false , false ),
26682687 bindingName , List .of (), initializer , false , false ,
26692688 start .line (), start .col (), leadingComments );
26702689 }
@@ -2771,6 +2790,8 @@ private Expr parseLambda() {
27712790
27722791 // mutable, noexcept, attributes
27732792 boolean isMutable = matchKeyword ("mutable" );
2793+ matchKeyword ("constexpr" );
2794+ matchKeyword ("consteval" );
27742795 if (checkKeyword ("noexcept" )) { advance (); if (checkPunct ("(" )){advance ();int _d =1 ;while (!isAtEnd ()&&_d >0 ){if (checkPunct ("(" ))_d ++;else if (checkPunct (")" ))_d --;advance ();}} }
27752796 consumeAttributes ();
27762797
@@ -2779,6 +2800,17 @@ private Expr parseLambda() {
27792800 returnType = parseTypeRef ();
27802801 }
27812802
2803+ if (check (CppLexerTokenType .IDENTIFIER ) && peek ().text ().equals ("requires" )) {
2804+ advance ();
2805+ int _rd = 0 ;
2806+ while (!isAtEnd ()) {
2807+ if (checkPunct ("(" ) || checkOp ("<" )) _rd ++;
2808+ else if (checkPunct (")" ) || checkOp (">" )) _rd --;
2809+ else if (checkOp (">>" )) _rd -= 2 ;
2810+ else if (checkPunct ("{" ) && _rd == 0 ) break ;
2811+ advance ();
2812+ }
2813+ }
27822814 Block body = parseBlock ();
27832815 return new LambdaExpr (captures , params , returnType , isMutable , body , start .line (), start .col (), List .of ());
27842816 }
@@ -2844,9 +2876,10 @@ private Param parseParam() {
28442876 // C-style variadic: bare "..." as a parameter (e.g. "void f(int, ...)")
28452877 if (checkPunct ("..." )) {
28462878 advance ();
2847- return new Param (new NamedType ("..." , List .of (), 0 , false , false ), "..." , null , List .of (), false );
2879+ return new Param (new NamedType ("..." , List .of (), 0 , false , false , false ), "..." , null , List .of (), false );
28482880 }
28492881
2882+ if (checkKeyword ("this" )) advance (); // explicit object param (C++23)
28502883 TypeRef type = parseTypeRef ();
28512884 boolean isTypePackExpansion = matchPunct ("..." ); // pack expansion after type: "Rest... rest"
28522885
@@ -2974,7 +3007,7 @@ private Param parseParam() {
29743007 }
29753008 // Represent as a pointer type
29763009 if (type instanceof NamedType nt ) {
2977- type = new NamedType (nt .baseName (), nt .templateArgs (), nt .pointerDepth () + 1 , false , nt .isConst ());
3010+ type = new NamedType (nt .baseName (), nt .templateArgs (), nt .pointerDepth () + 1 , false , nt .isConst (), false );
29783011 }
29793012 }
29803013 Expr defaultValue = null ;
@@ -2986,7 +3019,7 @@ private Param parseParam() {
29863019
29873020 private TypeRef bumpPointerDepth (TypeRef type ) {
29883021 if (type instanceof NamedType nt ) {
2989- return new NamedType (nt .baseName (), nt .templateArgs (), nt .pointerDepth () + 1 , nt .isReference (), nt .isConst ());
3022+ return new NamedType (nt .baseName (), nt .templateArgs (), nt .pointerDepth () + 1 , nt .isReference (), nt .isConst (), false );
29903023 }
29913024 // Function-pointer/function-signature types can't sensibly gain a
29923025 // C-style array-parameter pointer bump this way; not encountered by
@@ -3127,6 +3160,15 @@ private Statement parseStatement(List<CppLexerToken> leadingComments) {
31273160 if (checkKeyword ("while" )) return parseWhile (leadingComments );
31283161 if (checkKeyword ("do" )) return parseDoWhile (leadingComments );
31293162 if (checkKeyword ("switch" )) return parseSwitch (leadingComments );
3163+ if (checkKeyword ("using" ) && pos + 1 < tokens .size () && tokens .get (pos + 1 ).isKeyword ("enum" )) {
3164+ int startPos = pos ;
3165+ while (!isAtEnd () && !checkPunct (";" )) advance ();
3166+ matchPunct (";" );
3167+ StringBuilder raw = new StringBuilder ();
3168+ for (int i = startPos ; i < pos - 1 ; i ++) { if (i > startPos ) raw .append (" " ); raw .append (tokens .get (i ).text ()); }
3169+ raw .append (";" );
3170+ return new ExprStatement (new Identifier (raw .toString (), tokens .get (startPos ).line (), tokens .get (startPos ).col (), List .of ()), tokens .get (startPos ).line (), tokens .get (startPos ).col (), leadingComments );
3171+ }
31303172 if (checkKeyword ("return" )) return parseReturn (leadingComments );
31313173 if (checkKeyword ("break" )) return parseBreak (leadingComments );
31323174 if (checkKeyword ("continue" )) return parseContinue (leadingComments );
@@ -3145,6 +3187,16 @@ private Statement parseStatement(List<CppLexerToken> leadingComments) {
31453187 private Statement parseIf (List <CppLexerToken > leadingComments ) {
31463188 CppLexerToken start = expectKeyword ("if" );
31473189 boolean isConstexpr = matchKeyword ("constexpr" ); // C++17 if constexpr
3190+ if (checkKeyword ("consteval" ) || (checkOp ("!" ) && pos + 1 < tokens .size () && tokens .get (pos +1 ).isKeyword ("consteval" ))) {
3191+ if (checkOp ("!" )) advance ();
3192+ advance (); // consume consteval
3193+ Statement thenBr = parseStatement (consumeLeadingComments ());
3194+ Statement elseBr = null ;
3195+ consumeLeadingComments ();
3196+ if (checkKeyword ("else" )) { advance (); elseBr = parseStatement (consumeLeadingComments ()); }
3197+ return new IfStatement (new Identifier ("true" , start .line (), start .col (), List .of ()),
3198+ thenBr , elseBr , false , start .line (), start .col (), leadingComments );
3199+ }
31483200 expectPunct ("(" );
31493201 // C++17 if-init-statement: if (init; cond) -- collect init decls,
31503202 // wrap the IfStatement in a Block so the init vars are in scope.
@@ -3193,14 +3245,14 @@ private Statement parseForOrRangeFor(List<CppLexerToken> leadingComments) {
31933245 Expr sbIterable = parseExpr (); expectPunct (")" );
31943246 Statement sbBody = parseStatement (consumeLeadingComments ());
31953247 String sbName = "[" + String .join (", " , sbNames ) + "]" ;
3196- return new RangeForStatement (new NamedType ("auto" ,List .of (),0 ,false ,false ), sbName , isRef , sbIterable , sbBody , start .line (), start .col (), leadingComments );
3248+ return new RangeForStatement (new NamedType ("auto" ,List .of (),0 ,false ,false , false ), sbName , isRef , sbIterable , sbBody , start .line (), start .col (), leadingComments );
31973249 }
31983250 if (looksLikeRangeFor ()) {
31993251 TypeRef declType = parseTypeRef ();
32003252 boolean isReference = false ;
32013253 if (declType instanceof NamedType nt && nt .isReference ()) {
32023254 isReference = true ;
3203- declType = new NamedType (nt .baseName (), nt .templateArgs (), nt .pointerDepth (), false , nt .isConst ());
3255+ declType = new NamedType (nt .baseName (), nt .templateArgs (), nt .pointerDepth (), false , nt .isConst (), false );
32043256 }
32053257 String declName = expectIdentifier ().text ();
32063258 expectPunct (":" );
@@ -3559,7 +3611,7 @@ private List<DeclStatement> parseDeclStatementsDesugared(List<CppLexerToken> lea
35593611 TypeRef declaratorType = type ;
35603612 if (type instanceof NamedType nt ) {
35613613 declaratorType = new NamedType (nt .baseName (), nt .templateArgs (),
3562- extraPointerDepth , extraIsReference , nt .isConst ());
3614+ extraPointerDepth , extraIsReference , nt .isConst (), false );
35633615 }
35643616 result .add (parseOneDeclarator (declaratorType , isStatic , isConst , start , List .of ()));
35653617 }
0 commit comments