@@ -74,8 +74,9 @@ private void skipCommentsAt() {
7474 }
7575
7676 private CppLexerToken peek () {
77- skipCommentsAt ();
78- return tokens .get (pos );
77+ int p = pos ;
78+ while (p < tokens .size () && (tokens .get (p ).type () == CppLexerTokenType .LINE_COMMENT || tokens .get (p ).type () == CppLexerTokenType .BLOCK_COMMENT )) p ++;
79+ return p < tokens .size () ? tokens .get (p ) : tokens .get (tokens .size () - 1 );
7980 }
8081
8182 private CppLexerToken peek (int ahead ) {
@@ -276,7 +277,17 @@ private List<TopLevelItem> parseTopLevelItem(List<CppLexerToken> leadingComments
276277 }
277278
278279 List <String > templateParams = List .of ();
279- if (checkKeyword ("template" )) {
280+ if (matchKeyword ("template" )) {
281+ // Explicit template instantiation: "template class Foo<int>;" (no < after template)
282+ if (!checkOp ("<" )) {
283+ int startPos = pos - 1 ;
284+ while (!isAtEnd () && !checkPunct (";" )) advance ();
285+ matchPunct (";" );
286+ StringBuilder raw = new StringBuilder ();
287+ for (int i = startPos ; i < pos - 1 ; i ++) { if (i > startPos ) raw .append (" " ); raw .append (tokens .get (i ).text ()); }
288+ raw .append (";" );
289+ return List .of (new PreprocessorLine (raw .toString (), tokens .get (startPos ).line (), tokens .get (startPos ).col (), leadingComments ));
290+ }
280291 templateParams = parseTemplateParamList ();
281292 consumeLeadingComments ();
282293
@@ -430,6 +441,11 @@ private List<TopLevelItem> parseTopLevelItem(List<CppLexerToken> leadingComments
430441 return List .of (parseFunctionOrConstructorOrDestructor (leadingComments , templateParams ));
431442 }
432443
444+ // Global structured binding: "auto [a, b] = expr;"
445+ if (isStructuredBindingStart ()) {
446+ Statement sb2 = parseStructuredBinding (leadingComments );
447+ return List .of (new TopLevelStatement (sb2 , sb2 .line (), sb2 .col (), leadingComments ));
448+ }
433449 // Deduction guide: "Wrapper(const char*) -> Wrapper<std::string>;"
434450 if (check (CppLexerTokenType .IDENTIFIER ) && pos + 1 < tokens .size () && tokens .get (pos + 1 ).isPunct ("(" )) {
435451 int scan = pos + 2 ; int depth = 1 ;
@@ -454,7 +470,8 @@ private List<TopLevelItem> parseTopLevelItem(List<CppLexerToken> leadingComments
454470
455471 /** "template<typename T, typename U, ...>" -- returns just the param names. */
456472 private List <String > parseTemplateParamList () {
457- expectKeyword ("template" );
473+ // "template" already consumed by the caller; just consume "<...>"
474+ if (checkKeyword ("template" )) advance (); // in case called with template still present
458475 expectOp ("<" );
459476 List <String > params = new ArrayList <>();
460477 // template<> is a valid explicit full specialization marker -- emit as empty list
@@ -558,6 +575,20 @@ private String parseTemplateParamName() {
558575 return "<template-template>" ;
559576 }
560577
578+ // --- concept-constrained type parameter: "Numeric T" ---
579+ if (check (CppLexerTokenType .IDENTIFIER ) && pos + 1 < tokens .size ()
580+ && tokens .get (pos + 1 ).type () == CppLexerTokenType .IDENTIFIER
581+ && pos + 2 < tokens .size ()
582+ && (tokens .get (pos + 2 ).isOp (">" ) || tokens .get (pos + 2 ).isOp (">>" )
583+ || tokens .get (pos + 2 ).isPunct ("," )
584+ || tokens .get (pos + 2 ).isPunct ("..." )
585+ || tokens .get (pos + 2 ).isOp ("=" ))) {
586+ advance ();
587+ if (checkPunct ("..." )) advance ();
588+ String name = advance ().text ();
589+ if (matchOp ("=" )) parseTemplateDefaultValue ();
590+ return name ;
591+ }
561592 // --- typename / class type parameter ---
562593 if (checkKeyword ("typename" ) || checkKeyword ("class" )) {
563594 advance (); // consume typename/class
@@ -886,7 +917,7 @@ private FunctionDecl parseFunctionOrConstructorOrDestructor(List<CppLexerToken>
886917 // using "virtual void draw() = 0;" on an abstract base class --
887918 // confirmed real, ordinary OOP, not exotic. Must be checked
888919 // BEFORE the body/";" check below, since "= 0;" replaces both.
889- boolean isPureVirtual = false ;
920+ boolean isPureVirtual = false , isDefault = false , isDelete = false ;
890921 if (checkOp ("=" )) {
891922 int save = pos ;
892923 advance ();
@@ -903,11 +934,11 @@ private FunctionDecl parseFunctionOrConstructorOrDestructor(List<CppLexerToken>
903934 }
904935
905936 Block body = checkPunct ("{" ) ? parseBlock () : null ;
906- if (body == null && !isPureVirtual ) expectPunct (";" );
907- else if (isPureVirtual ) expectPunct (";" );
937+ if (body == null && !isPureVirtual && ! isDefault && ! isDelete ) expectPunct (";" );
938+ else if (isPureVirtual || isDefault || isDelete ) expectPunct (";" );
908939
909940 return new FunctionDecl (null , name , templateParams , params , initList , body ,
910- !isDestructor , isDestructor , isVirtual , isOverride , isConst , false , false , isPureVirtual ,
941+ !isDestructor , isDestructor , isVirtual , isOverride , isConst , false , false , isPureVirtual , isDefault , isDelete ,
911942 start .line (), start .col (), leadingComments );
912943 }
913944
@@ -974,7 +1005,8 @@ private List<TopLevelItem> parseFunctionOrVariable(List<CppLexerToken> leadingCo
9741005 matchKeyword ("inline" );
9751006 matchKeyword ("volatile" ); // consume volatile qualifier
9761007 boolean isConst = matchKeyword ("const" );
977- boolean isConstexprFn = matchKeyword ("constexpr" ); if (isConstexprFn ) isConst = true ;
1008+ boolean isConstexprFn = matchKeyword ("constexpr" ) || matchKeyword ("consteval" ); if (isConstexprFn ) isConst = true ;
1009+ matchKeyword ("constinit" );
9781010 if (!isVirtual ) isVirtual = matchKeyword ("virtual" ); // constexpr virtual
9791011 if (!isStatic ) isStatic = matchKeyword ("static" );
9801012 if (!isConst ) isConst = matchKeyword ("const" );
@@ -1024,6 +1056,11 @@ && looksLikeParamList()) {
10241056 trailingReturnType = parseTypeRef ();
10251057 }
10261058 TypeRef effectiveReturnType = (trailingReturnType != null ) ? trailingReturnType : type ;
1059+ // Consume __attribute__((...)): GCC attribute syntax before trailing qualifiers
1060+ if (check (CppLexerTokenType .IDENTIFIER ) && peek ().text ().equals ("__attribute__" )) {
1061+ advance (); // __attribute__
1062+ if (checkPunct ("(" )) { advance (); int _ad =1 ; while (!isAtEnd ()&&_ad >0 ){if (checkPunct ("(" ))_ad ++;else if (checkPunct (")" ))_ad --;advance ();} }
1063+ }
10271064 // Consume trailing qualifiers: noexcept, noexcept(expr), override, final, requires
10281065 while (true ) {
10291066 if (checkKeyword ("noexcept" )) {
@@ -1046,14 +1083,16 @@ && looksLikeParamList()) {
10461083 } else break ;
10471084 }
10481085 // Pure-virtual specifier ("= 0") or = default / = delete
1049- boolean isPureVirtual = false ;
1086+ boolean isPureVirtual = false , isDefault = false , isDelete = false ;
10501087 if (checkOp ("=" )) {
10511088 int save = pos ;
10521089 advance ();
10531090 if (checkLiteralZero ()) {
10541091 advance (); isPureVirtual = true ;
1055- } else if (checkKeyword ("default" ) || checkKeyword ("delete" )) {
1056- advance (); // = default or = delete
1092+ } else if (checkKeyword ("default" )) {
1093+ advance (); isDefault = true ;
1094+ } else if (checkKeyword ("delete" )) {
1095+ advance (); isDelete = true ;
10571096 } else {
10581097 pos = save ;
10591098 }
@@ -1073,12 +1112,16 @@ && looksLikeParamList()) {
10731112 Block body = checkPunct ("{" ) ? parseBlock () : null ;
10741113 if (body == null ) expectPunct (";" );
10751114 FunctionDecl fn = new FunctionDecl (effectiveReturnType , name , templateParams , params , List .of (), body ,
1076- false , false , isVirtual , isOverride , isMethodConst , isConstexprFn , isStatic , isPureVirtual ,
1115+ false , false , isVirtual , isOverride , isMethodConst , isConstexprFn , isStatic , isPureVirtual , isDefault , isDelete ,
10771116 start .line (), start .col (), leadingComments );
10781117 return List .of (fn );
10791118 }
10801119
10811120 // Variable declaration, possibly multi-declarator.
1121+ // Bit field: "unsigned int read : 1" -- consume ": N" width specifier
1122+ if (checkPunct (":" ) && pos + 1 < tokens .size () && tokens .get (pos + 1 ).type () == CppLexerTokenType .INT_LITERAL ) {
1123+ advance (); advance (); // consume ":" and bit width
1124+ }
10821125 List <TopLevelItem > result = new ArrayList <>();
10831126 result .add (parseOneTopLevelDeclarator (type , name , isConst , isStatic , templateParams , start , leadingComments ));
10841127 while (matchPunct ("," )) {
@@ -1142,6 +1185,8 @@ private boolean looksLikeTopLevelDeclarationOrFunction() {
11421185 matchKeyword ("volatile" );
11431186 matchKeyword ("const" );
11441187 matchKeyword ("constexpr" );
1188+ matchKeyword ("consteval" );
1189+ matchKeyword ("constinit" );
11451190 matchKeyword ("inline" );
11461191 matchKeyword ("static" ); // tolerate either order, mirroring the real parse path
11471192
0 commit comments