├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── dist ├── index.d.cts └── index.d.ts ├── package.json ├── rollup.config.js ├── src ├── cpp.grammar ├── highlight.js └── tokens.js └── test ├── ambiguities.txt ├── cpp20.txt ├── declarations.txt ├── definitions.txt ├── expressions.txt ├── microsoft.txt ├── statements.txt ├── test-cpp.js └── types.txt /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /src/parser.* 3 | .tern-* 4 | /dist 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.1.3 (2025-03-16) 2 | 3 | ### Bug fixes 4 | 5 | Enable delimiter detection for the grammar, improving bracket matching and by-syntax cursor navigation. 6 | 7 | ## 1.1.2 (2023-12-28) 8 | 9 | ### Bug fixes 10 | 11 | Tag comments and strings as isolating for the purpose of bidirectional text. 12 | 13 | ## 1.1.1 (2023-07-03) 14 | 15 | ### Bug fixes 16 | 17 | Make the package work with new TS resolution styles. 18 | 19 | ## 1.1.0 (2023-02-08) 20 | 21 | ### New features 22 | 23 | Add support for a number of C++20 constructs. 24 | 25 | ## 1.0.0 (2022-06-06) 26 | 27 | ### New features 28 | 29 | First stable version. 30 | 31 | ## 0.16.0 (2022-04-20) 32 | 33 | ### Breaking changes 34 | 35 | Move to 0.16 serialized parser format. 36 | 37 | ## 0.15.3 (2022-03-28) 38 | 39 | ### Bug fixes 40 | 41 | Properly parse braced initializer lists in assignment expressions. 42 | 43 | ### New features 44 | 45 | The parser now includes syntax highlighting information in its node types. 46 | 47 | >>>>>>> 9081cc7 (Mark version 0.16.0) 48 | ## 0.15.2 (2022-01-24) 49 | 50 | ### Bug fixes 51 | 52 | Allow more explicit operator names, stop treating the 'operator' keyword as part of the operator name token. 53 | 54 | Allow comment after simple preprocessor directives. 55 | 56 | Support friend declarations in template declarations. 57 | 58 | Improve the parsing of some ambiguous cases in struct/enum/class specifiers. 59 | 60 | ## 0.15.1 (2022-01-21) 61 | 62 | ### Bug fixes 63 | 64 | Regenerate with \@lezer/generator 0.15.3 to fix a problem with parsing macros. 65 | 66 | ## 0.15.0 (2021-08-11) 67 | 68 | ### Breaking changes 69 | 70 | The module's name changed from `lezer-cpp` to `@lezer/cpp`. 71 | 72 | Upgrade to the 0.15.0 lezer interfaces. 73 | 74 | ## 0.13.2 (2021-03-23) 75 | 76 | ### Bug fixes 77 | 78 | Fix a crash that sometimes occurred during error-recovery around strings. 79 | 80 | ## 0.13.1 (2020-12-04) 81 | 82 | ### Bug fixes 83 | 84 | Fix versions of lezer packages depended on. 85 | 86 | ## 0.13.0 (2020-12-04) 87 | 88 | ## 0.12.0 (2020-10-23) 89 | 90 | ### Breaking changes 91 | 92 | Adjust to changed serialized parser format. 93 | 94 | ## 0.11.1 (2020-09-26) 95 | 96 | ### Bug fixes 97 | 98 | Fix lezer depencency versions 99 | 100 | ## 0.11.0 (2020-09-26) 101 | 102 | ### Breaking changes 103 | 104 | Follow change in serialized parser format. 105 | 106 | ## 0.10.1 (2020-09-10) 107 | 108 | ### Bug fixes 109 | 110 | Fix meaningless names for preprocessor directive tokens. 111 | 112 | Make `++`/`--` operators `UpdateOp` tokens. 113 | 114 | ## 0.10.0 (2020-09-02) 115 | 116 | ### Breaking changes 117 | 118 | First numbered release. 119 | 120 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2020 by Marijn Haverbeke and others 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @lezer/cpp 2 | 3 | This is a C++ grammar for the 4 | [Lezer](https://lezer.codemirror.net/) parser system. 5 | 6 | The grammar used is based in a large part on the corresponding 7 | [tree-sitter grammar](https://github.com/tree-sitter/tree-sitter-cpp). 8 | 9 | It should be noted that really parsing C++ without a symbol table and 10 | a preprocessor is not really something that is _possible_. The 11 | language is very, very ambiguous when parsed like that. This grammar 12 | tries to pick a likely parse, but is entirely capable of picking the 13 | wrong one. 14 | 15 | The code is licensed under an MIT license. 16 | -------------------------------------------------------------------------------- /dist/index.d.cts: -------------------------------------------------------------------------------- 1 | import {LRParser} from "@lezer/lr" 2 | 3 | export const parser: LRParser 4 | -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import {LRParser} from "@lezer/lr" 2 | 3 | export const parser: LRParser 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lezer/cpp", 3 | "version": "1.1.3", 4 | "description": "lezer-based C++ grammar", 5 | "main": "dist/index.cjs", 6 | "type": "module", 7 | "exports": { 8 | "import": "./dist/index.js", 9 | "require": "./dist/index.cjs" 10 | }, 11 | "module": "dist/index.js", 12 | "types": "dist/index.d.ts", 13 | "author": "Marijn Haverbeke ", 14 | "license": "MIT", 15 | "devDependencies": { 16 | "@lezer/generator": "^1.0.0", 17 | "mocha": "^10.2.0", 18 | "rollup": "^2.52.2", 19 | "@rollup/plugin-node-resolve": "^9.0.0" 20 | }, 21 | "dependencies": { 22 | "@lezer/common": "^1.2.0", 23 | "@lezer/highlight": "^1.0.0", 24 | "@lezer/lr": "^1.0.0" 25 | }, 26 | "repository": { 27 | "type" : "git", 28 | "url" : "https://github.com/lezer-parser/cpp.git" 29 | }, 30 | "scripts": { 31 | "build": "lezer-generator src/cpp.grammar -o src/parser && rollup -c", 32 | "build-debug": "lezer-generator src/cpp.grammar --names -o src/parser && rollup -c", 33 | "prepare": "npm run build", 34 | "test": "mocha test/test-*.js" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import {nodeResolve} from "@rollup/plugin-node-resolve" 2 | 3 | export default { 4 | input: "./src/parser.js", 5 | output: [{ 6 | format: "cjs", 7 | file: "./dist/index.cjs" 8 | }, { 9 | format: "es", 10 | file: "./dist/index.js" 11 | }], 12 | external(id) { return !/^[\.\/]/.test(id) }, 13 | plugins: [ 14 | nodeResolve() 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /src/cpp.grammar: -------------------------------------------------------------------------------- 1 | @precedence { 2 | capture 3 | subscript 4 | arguments 5 | typeSizeof 6 | placeholder 7 | baseClass 8 | suffix @left 9 | prefix @left 10 | pointer @left 11 | mult @left 12 | add @left 13 | bitShift @left 14 | kwExprExtra 15 | kwExpr 16 | greaterLess @left 17 | equal @left 18 | bitAnd @left 19 | bitXor @left 20 | bitOr @left 21 | logicAnd @left 22 | logicOr @left 23 | concat @left 24 | params 25 | array 26 | specifiers 27 | cast 28 | more 29 | arrowStar 30 | subscriptDesignator 31 | return 32 | typeIdentifier 33 | structName 34 | enumBase 35 | newOpArray 36 | namespace 37 | else @right 38 | caseLabel 39 | simpleTypeIdentifier 40 | qualifiers 41 | statement 42 | pack 43 | assign @right 44 | ternary @right 45 | absDecl 46 | } 47 | 48 | @top Program { 49 | topLevelItem* 50 | } 51 | 52 | topLevelItem { 53 | FunctionDefinition | 54 | LinkageSpecification | 55 | Declaration | 56 | ExportDeclaration | 57 | ImportDeclaration | 58 | statement | 59 | TypeDefinition | 60 | emptyDeclaration | 61 | NamespaceDefinition | 62 | ConceptDefinition | 63 | UsingDeclaration | 64 | AliasDeclaration | 65 | StaticAssertDeclaration | 66 | TemplateDeclaration | 67 | TemplateInstantiation | 68 | FunctionDefinition { constructorOrDestructorDefinition } | 69 | FunctionDefinition { operatorCastDefinition } | 70 | Declaration { operatorCastDeclaration } | 71 | ModuleDeclaration 72 | } 73 | 74 | @skip { ppSpace } { 75 | ppEnd { BlockComment* LineComment? "\n" } 76 | 77 | PreprocDirective { 78 | pp<"include"> (String | SystemLibString | Identifier ArgumentList?) ppEnd | 79 | pp<"define"> Identifier preprocParams? PreprocArg? "\n" | 80 | pp<"if"> PreprocArg "\n" | 81 | (pp<"ifdef"> | pp<"ifndef">) Identifier ppEnd | 82 | pp<"else"> ppEnd | 83 | pp<"endif"> ppEnd | 84 | pp<"elif"> PreprocArg "\n" | 85 | PreprocDirectiveName PreprocArg "\n" 86 | } 87 | } 88 | 89 | preprocParams { "(" commaSep ")" } 90 | 91 | FunctionDefinition { 92 | Attribute* msCallModifier? declarationSpecifiers declarator (CompoundStatement | TryStatement) 93 | } 94 | 95 | Declaration { 96 | Attribute* declarationSpecifiers commaSep1 ";" 97 | } 98 | 99 | TypeDefinition { 100 | kw<"typedef"> typeQualifier* typeSpecifier commaSep1 ";" 101 | } 102 | 103 | declarationSpecifiers { 104 | (storageClassSpecifier | typeQualifier | AttributeSpecifier | MsDeclspecModifier)* ~specifiers typeSpecifier ( 105 | storageClassSpecifier | 106 | typeQualifier | 107 | AttributeSpecifier | 108 | MsDeclspecModifier 109 | )* 110 | } 111 | 112 | LinkageSpecification { 113 | kw<"extern"> String (FunctionDefinition | Declaration | CompoundStatement) 114 | } 115 | 116 | AttributeSpecifier { 117 | kw<"__attribute__"> "(" ArgumentList ")" 118 | } 119 | 120 | MsDeclspecModifier { 121 | kw<"__declspec"> "(" Identifier ")" 122 | } 123 | 124 | MsBasedModifier { 125 | kw<"__based"> ArgumentList 126 | } 127 | 128 | msCallModifier { 129 | @specialize[@name=MsCallModifier] 131 | } 132 | 133 | msPointerModifier { 134 | @specialize[@name=MsPointerModifier] 135 | } 136 | 137 | declarator { 138 | PointerDeclarator[@dynamicPrecedence=1] { 139 | MsBasedModifier? "*" msPointerModifier* typeQualifier* declarator 140 | } | 141 | FunctionDeclarator | 142 | ArrayDeclarator { 143 | declarator !array "[" typeQualifier* (expression | "*")? "]" 144 | } | 145 | ParenthesizedDeclarator[@dynamicPrecedence=-10] { 146 | "(" declarator ")" 147 | } | 148 | Identifier ~identifier | 149 | ReferenceDeclarator[@dynamicPrecedence=1] { 150 | ("&" | "&&") declarator 151 | } | 152 | ScopedIdentifier ~identifier | 153 | TemplateFunction ~identifier | 154 | OperatorName> ~opDecl | 155 | DestructorName | 156 | StructuredBindingDeclarator[@dynamicPrecedence=-1] { 157 | "[" commaSep1 "]" 158 | } 159 | } 160 | 161 | functionSpecifiers { 162 | (typeQualifier | virtualSpecifier | "&" | "&&" | Noexcept | RequiresClause | ThrowSpecifier)* TrailingReturnType? 163 | } 164 | 165 | FunctionDeclarator { 166 | declarator !params ParameterList !specifiers functionSpecifiers AttributeSpecifier* 167 | (!specifiers )* 168 | } 169 | 170 | fieldDeclarator { 171 | PointerDeclarator[@dynamicPrecedence=1] { 172 | MsBasedModifier? "*" msPointerModifier* typeQualifier* fieldDeclarator 173 | } | 174 | FunctionDeclarator { 175 | fieldDeclarator !params ParameterList functionSpecifiers 176 | } | 177 | ArrayDeclarator { 178 | fieldDeclarator !array "[" typeQualifier* (expression | "*")? "]" 179 | } | 180 | ParenthesizedDeclarator[@dynamicPrecedence=-10] { 181 | "(" fieldDeclarator ")" 182 | } | 183 | FieldIdentifier | 184 | ReferenceDeclarator[@dynamicPrecedence=1] { 185 | ("&" | "&&") fieldDeclarator 186 | } | 187 | TemplateMethod | 188 | OperatorName> ~opDecl 189 | } 190 | 191 | typeDeclarator { 192 | PointerDeclarator[@dynamicPrecedence=1] { 193 | MsBasedModifier? "*" msPointerModifier* typeQualifier* typeDeclarator 194 | } | 195 | FunctionDeclarator { 196 | typeDeclarator !params ParameterList 197 | } | 198 | ArrayDeclarator { 199 | typeDeclarator !array "[" typeQualifier* (expression | "*")? "]" 200 | } | 201 | ParenthesizedDeclarator[@dynamicPrecedence=-10] { 202 | "(" typeDeclarator ")" 203 | } | 204 | TypeIdentifier 205 | } 206 | 207 | abstractDeclarator { 208 | AbstractPointerDeclarator[@dynamicPrecedence=1] { 209 | "*" (!qualifiers typeQualifier)* (!absDecl abstractDeclarator)? 210 | } | 211 | AbstractFunctionDeclarator | 212 | AbstractArrayDeclarator { 213 | abstractDeclarator? !array "[" typeQualifier* (expression | "*")? "]" 214 | } | 215 | AbstractParenthesizedDeclarator { 216 | "(" abstractDeclarator ")" 217 | } | 218 | AbstractReferenceDeclarator { 219 | ("&" | "&&") (!absDecl abstractDeclarator)? 220 | } 221 | } 222 | 223 | AbstractFunctionDeclarator { 224 | abstractDeclarator? !params ParameterList (typeQualifier | "&" | "&&" | Noexcept | ThrowSpecifier)* !return TrailingReturnType? 225 | } 226 | 227 | InitDeclarator { 228 | declarator "=" (InitializerList | expression) | 229 | declarator (!arguments ArgumentList | InitializerList) 230 | } 231 | 232 | CompoundStatement { 233 | !statement "{" topLevelItem* !statement "}" 234 | } 235 | 236 | storageClassSpecifier { 237 | kw<"extern"> | kw<"static"> | kw<"register"> | kw<"inline"> | kw<"thread_local"> 238 | } 239 | 240 | typeQualifier { 241 | kw<"const"> | kw<"volatile"> | kw<"restrict"> | kw<"_Atomic"> | kw<"mutable"> | kw<"constexpr"> | kw<"constinit"> | kw<"consteval"> 242 | } 243 | 244 | typeSpecifier[@isGroup=Type] { 245 | StructSpecifier { kw<"struct"> classSpecifier } | 246 | UnionSpecifier { kw<"union"> classSpecifier } | 247 | ClassSpecifier { kw<"class"> classSpecifier } | 248 | EnumSpecifier { 249 | kw<"enum"> (kw<"class"> | kw<"struct">)? 250 | (className (!enumBase enumBaseClause)? (!structName EnumeratorList)? | EnumeratorList) 251 | } | 252 | DependentType[@dynamicPrecedence=-1] { 253 | kw<"typename"> typeSpecifier 254 | } | 255 | Decltype | 256 | SizedTypeSpecifier | 257 | primitiveType ~afterPrimitive | 258 | kw<"auto"> | 259 | ScopedTypeIdentifier !simpleTypeIdentifier | 260 | TypeIdentifier !simpleTypeIdentifier | 261 | TemplateType | 262 | PlaceholderTypeSpecifier { typeSpecifier !placeholder (kw<"auto"> | Decltype) } 263 | } 264 | 265 | classSpecifier { 266 | MsDeclspecModifier? Attribute* 267 | (className | className? !structName virtualSpecifier? BaseClassClause? FieldDeclarationList) 268 | } 269 | 270 | Decltype { kw<"decltype"> "(" (expression | kw<"auto">) ")" } 271 | 272 | // FIXME this used to allow arbitrary TypeNames as well as primitive 273 | // types, which I guess might be useful with preprocessor-defined 274 | // types, but requires even more GLR magic. 275 | SizedTypeSpecifier { 276 | @specialize[@name=TypeSize]+ primitiveType? 277 | } 278 | 279 | EnumeratorList { 280 | "{" commaSepTrailing "}" 281 | } 282 | 283 | FieldDeclarationList { 284 | "{" fieldDeclarationListItem* "}" 285 | } 286 | 287 | fieldDeclarationListItem { 288 | FieldDeclaration { 289 | Attribute* kw<"virtual">? declarationSpecifiers (fieldDeclarator ("," fieldDeclarator)*)? 290 | (BitfieldClause | InitializerList | "=" (expression | InitializerList))? ";" 291 | } | 292 | TemplateDeclaration | 293 | FunctionDefinition { 294 | Attribute* kw<"virtual">? declarationSpecifiers 295 | fieldDeclarator (CompoundStatement | TryStatement | !more DefaultMethodClause | DeleteMethodClause) 296 | } | 297 | FunctionDefinition { constructorOrDestructorDefinition } | 298 | Declaration { 299 | (kw<"virtual"> | ExplicitFunctionSpecifier)? FunctionDeclarator ";" 300 | } | 301 | FunctionDefinition { operatorCastDefinition } | 302 | Declaration { operatorCastDeclaration } | 303 | FriendDeclaration | 304 | AccessSpecifier | 305 | AliasDeclaration | 306 | UsingDeclaration | 307 | TypeDefinition | 308 | StaticAssertDeclaration 309 | } 310 | 311 | BitfieldClause { 312 | ":" expression 313 | } 314 | 315 | Enumerator { 316 | Identifier ("=" expression)? 317 | } 318 | 319 | ParameterList { 320 | "(" ~argOrParam commaSep<(ParameterDeclaration | OptionalParameterDeclaration | VariadicParameterDeclaration | "..." ~argOrParam)> ")" 321 | } 322 | 323 | ParameterDeclaration { 324 | Attribute* declarationSpecifiers (declarator | abstractDeclarator)? 325 | } 326 | 327 | statement[@isGroup=Statement] { 328 | CaseStatement | 329 | nonCaseStatement | 330 | AttributeStatement | 331 | ForRangeLoop | 332 | TryStatement | 333 | ThrowStatement 334 | } 335 | 336 | nonCaseStatement { 337 | LabeledStatement | 338 | CompoundStatement | 339 | ExpressionStatement | 340 | IfStatement | 341 | SwitchStatement | 342 | DoStatement | 343 | WhileStatement | 344 | ForStatement | 345 | ReturnStatement | 346 | BreakStatement | 347 | ContinueStatement | 348 | GotoStatement | 349 | CoReturnStatement | 350 | CoYieldStatement 351 | } 352 | 353 | AttributeStatement { Attribute+ (CaseStatement | nonCaseStatement | ForRangeLoop | TryStatement) } 354 | 355 | LabeledStatement { 356 | StatementIdentifier ":" statement 357 | } 358 | 359 | ExpressionStatement { 360 | (expression | CommaExpression)? ";" 361 | } 362 | 363 | IfStatement { 364 | kw<"if"> kw<"constexpr">? ConditionClause statement (!else kw<"else"> statement)? 365 | } 366 | 367 | SwitchStatement { 368 | kw<"switch"> ConditionClause CompoundStatement 369 | } 370 | 371 | CaseStatement { 372 | (kw<"case"> expression | kw<"default">) ":" (!caseLabel (nonCaseStatement | AttributeStatement | Declaration | TypeDefinition))* 373 | } 374 | 375 | WhileStatement { 376 | kw<"while"> ConditionClause statement 377 | } 378 | 379 | DoStatement { 380 | kw<"do"> statement kw<"while"> ParenthesizedExpression ";" 381 | } 382 | 383 | ForStatement { 384 | kw<"for"> "(" (Declaration | (expression | CommaExpression)? ";") expression? ";" (expression | CommaExpression)? ")" statement 385 | } 386 | 387 | ReturnStatement { 388 | kw<"return"> (expression | CommaExpression)? ";" | 389 | kw<"return"> InitializerList ";" 390 | } 391 | 392 | BreakStatement { 393 | kw<"break"> ";" 394 | } 395 | 396 | ContinueStatement { 397 | kw<"continue"> ";" 398 | } 399 | 400 | GotoStatement { 401 | kw<"goto"> StatementIdentifier ";" 402 | } 403 | 404 | CoReturnStatement { 405 | kw<"co_return"> expression? ";" 406 | } 407 | 408 | CoYieldStatement { 409 | kw<"co_yield"> expression ";" 410 | } 411 | 412 | expression[@isGroup=Expression] { 413 | ConditionalExpression | 414 | AssignmentExpression | 415 | BinaryExpression | 416 | UnaryExpression | 417 | UpdateExpression | 418 | CastExpression | 419 | PointerExpression | 420 | SizeofExpression | 421 | CoAwaitExpression | 422 | RequiresExpression | 423 | SubscriptExpression | 424 | CallExpression | 425 | FieldExpression | 426 | CompoundLiteralExpression | 427 | Identifier ~identifier | 428 | Number | 429 | String | 430 | True | 431 | False | 432 | kw<"NULL"> | 433 | ConcatenatedString | 434 | CharLiteral | 435 | ParenthesizedExpression | 436 | TemplateFunction ~identifier | 437 | ScopedIdentifier ~identifier | 438 | OperatorName> ~opDecl | 439 | NewExpression | 440 | DeleteExpression | 441 | LambdaExpression | 442 | ParameterPackExpansion | 443 | kw<"nullptr"> | 444 | kw<"this"> | 445 | RawString | 446 | UserDefinedLiteral | 447 | ParamPack { "..." ~argOrParam } 448 | } 449 | 450 | CommaExpression { 451 | expression !more "," (expression | CommaExpression) 452 | } 453 | 454 | ConditionalExpression { 455 | expression !ternary "?" expression ":" expression 456 | } 457 | 458 | AssignmentExpression { 459 | (Identifier | 460 | CallExpression | 461 | FieldExpression | 462 | PointerExpression | 463 | SubscriptExpression | 464 | ParenthesizedExpression | 465 | ScopedNamespaceIdentifier) !assign (UpdateOp | "=") (expression | InitializerList) 466 | } 467 | 468 | PointerExpression { 469 | ("*" | "&") !pointer expression 470 | } 471 | 472 | UnaryExpression { 473 | (LogicOp<"!"> | ArithOp<"+" | "-"> | BitOp<"~">) !suffix expression 474 | } 475 | 476 | // Note: operators that conflict with other tokens are defined using 477 | // inline rules (so that the tokens can be shared), others directly using 478 | // ArithOp-style token helpers. 479 | BinaryExpression { 480 | expression !add ArithOp<"+" | "-"> expression | 481 | expression !mult (ArithOp { "*" } | ArithOp<"/" | "%">) expression | 482 | expression !logicAnd LogicOp { "&&" } expression | 483 | expression !logicOr LogicOp { "||" } expression | 484 | expression !bitOr BitOp<"|"> expression | 485 | expression !bitXor BitOp<"^"> expression | 486 | expression !bitAnd BitOp { "&" } expression | 487 | expression !equal CompareOp<"==" | "!="> expression | 488 | expression !greaterLess 489 | (CompareOp<"<=" | ">=" | "<=>"> | @extend[@name=CompareOp]<"<"> | @extend[@name=CompareOp]">) expression | 490 | expression !bitShift BitOp<"<<" | ">>"> expression | 491 | expression !concat incDec expression 492 | } 493 | 494 | UpdateExpression { 495 | incDec !prefix expression | expression !suffix incDec 496 | } 497 | 498 | CastExpression { 499 | "(" TypeDescriptor ")" expression 500 | } 501 | 502 | TypeDescriptor { 503 | typeQualifier* typeSpecifier typeQualifier* abstractDeclarator? 504 | } 505 | 506 | SizeofExpression { 507 | kw<"sizeof"> !kwExpr (expression | [@dynamicPrecedence=1] { "(" !typeSizeof TypeDescriptor ")" }) | 508 | kw<"sizeof"> "..." !kwExprExtra "(" Identifier ")" 509 | } 510 | 511 | CoAwaitExpression { 512 | kw<"co_await"> !kwExpr expression 513 | } 514 | 515 | RequiresExpression { 516 | kw<"requires"> !kwExpr ParameterList? RequirementList { "{" requirement* "}" } 517 | } 518 | 519 | requirement { 520 | SimpleRequirement { (expression | CommaExpression)? ";" } | 521 | TypeRequirement { kw<"typename"> className ";" } | 522 | CompoundRequirement { "{" expression "}" kw<"noexcept">? ReturnTypeRequirement? ";" } | 523 | ReturnTypeRequirement ";" | 524 | RequiresClause ";" 525 | } 526 | 527 | ReturnTypeRequirement { "->" expression } 528 | 529 | SubscriptExpression { 530 | expression !subscript "[" expression "]" 531 | } 532 | 533 | CallExpression { 534 | expression !arguments ArgumentList | 535 | primitiveType ~afterPrimitive ArgumentList 536 | } 537 | 538 | ArgumentList { 539 | "(" ~argOrParam commaSep<(expression | InitializerList)> ")" 540 | } 541 | 542 | FieldExpression { 543 | expression !subscript ("." | "->") FieldIdentifier | 544 | expression !subscript ("." | "->") (DestructorName | TemplateMethod) 545 | } 546 | 547 | CompoundLiteralExpression { 548 | "(" TypeDescriptor ")" InitializerList | 549 | (TypeIdentifier | TemplateType | ScopedTypeIdentifier) InitializerList 550 | } 551 | 552 | ParenthesizedExpression { 553 | "(" (expression | CommaExpression) ")" 554 | } 555 | 556 | InitializerList { 557 | "{" commaSepTrailing "}" 558 | } 559 | 560 | InitializerPair { 561 | (SubscriptDesignator | FieldDesignator)+ "=" (expression | InitializerList) 562 | } 563 | 564 | SubscriptDesignator { 565 | "[" expression !subscriptDesignator "]" 566 | } 567 | 568 | FieldDesignator { 569 | "." FieldIdentifier 570 | } 571 | 572 | @skip {} { 573 | CharLiteral { 574 | charLiteralStart (EscapeSequence | charLiteralContent) charLiteralEnd 575 | } 576 | 577 | String[isolate] { 578 | stringLiteralStart (stringLiteralContent | EscapeSequence)* stringLiteralEnd 579 | } 580 | 581 | Macro[@dynamicPrecedence=-10] { MacroName (whitespace? ArgumentList?) } 582 | } 583 | 584 | ConcatenatedString { 585 | (RawString | String) (RawString | String)+ 586 | } 587 | 588 | UserDefinedLiteral { 589 | (Number | CharLiteral | String | RawString | ConcatenatedString) Identifier 590 | } 591 | 592 | TypeIdentifier { 593 | identifier 594 | } 595 | 596 | FieldIdentifier { 597 | identifier 598 | } 599 | 600 | StatementIdentifier { 601 | identifier 602 | } 603 | 604 | Identifier { 605 | identifier 606 | } 607 | 608 | emptyDeclaration { 609 | Attribute* typeSpecifier ";" 610 | } 611 | 612 | className { 613 | (TypeIdentifier | ScopedTypeIdentifier | TemplateType) 614 | } 615 | 616 | virtualSpecifier { 617 | @specialize[@name=VirtualSpecifier] 618 | } 619 | 620 | ExplicitFunctionSpecifier { 621 | kw<"explicit"> | 622 | kw<"explicit"> !arguments "(" expression ")" 623 | } 624 | 625 | BaseClassClause { 626 | ":" Attribute* commaSep1<(access | kw<"virtual">)* className "..."?> 627 | } 628 | 629 | enumBaseClause { 630 | ":" (ScopedTypeIdentifier | TypeIdentifier | SizedTypeSpecifier | primitiveType) 631 | } 632 | 633 | TemplateDeclaration { 634 | kw<"template"> TemplateParameterList RequiresClause? ( 635 | emptyDeclaration | 636 | AliasDeclaration | 637 | Declaration | 638 | TemplateDeclaration | 639 | FriendDeclaration | 640 | FunctionDefinition | 641 | ConceptDefinition | 642 | FunctionDefinition { constructorOrDestructorDefinition } | 643 | FunctionDefinition { operatorCastDefinition } 644 | ) 645 | } 646 | 647 | RequiresClause { 648 | kw<"requires"> constraint 649 | } 650 | 651 | constraint { 652 | True | 653 | False | 654 | className | 655 | ParenthesizedExpression | 656 | LambdaExpression | 657 | RequiresExpression | 658 | ConstraintConjuction { constraint !logicAnd LogicOp { "&&" } constraint } | 659 | ConstraintDisjunction { constraint !logicOr LogicOp { "||" } constraint } 660 | } 661 | 662 | TemplateInstantiation { 663 | kw<"template"> declarationSpecifiers? declarator ";" 664 | } 665 | 666 | TemplateParameterList { 667 | "<" commaSep (templateArgsEnd | templateArgsEndFallback) 668 | } 669 | 670 | templateParameter { 671 | ParameterDeclaration | 672 | OptionalParameterDeclaration | 673 | TypeParameterDeclaration | 674 | VariadicParameterDeclaration | 675 | OptionalTypeParameterDeclaration | 676 | VariadicTypeParameterDeclaration | 677 | TemplateTemplateParameterDeclaration { 678 | kw<"template"> TemplateParameterList 679 | (TypeParameterDeclaration | VariadicTypeParameterDeclaration | OptionalTypeParameterDeclaration) 680 | } 681 | } 682 | 683 | TypeParameterDeclaration { 684 | (kw<"typename"> | kw<"class">) !typeIdentifier TypeIdentifier? !typeIdentifier 685 | } 686 | 687 | OptionalTypeParameterDeclaration { 688 | (kw<"typename"> | kw<"class">) TypeIdentifier? !typeIdentifier "=" typeSpecifier 689 | } 690 | 691 | VariadicTypeParameterDeclaration { 692 | (kw<"typename"> | kw<"class">) "..." !typeIdentifier TypeIdentifier? !typeIdentifier 693 | } 694 | 695 | OptionalParameterDeclaration { 696 | declarationSpecifiers declarator? "=" expression 697 | } 698 | 699 | VariadicParameterDeclaration { 700 | declarationSpecifiers ( 701 | VariadicDeclarator | 702 | ReferenceDeclarator { ("&&" | "&") VariadicDeclarator } 703 | ) 704 | } 705 | 706 | VariadicDeclarator { 707 | "..." Identifier? 708 | } 709 | 710 | OperatorCast { 711 | ((NamespaceIdentifier | TemplateType | ScopedNamespaceIdentifier)? "::" skw<"operator"> | kw<"operator">) 712 | declarationSpecifiers !cast abstractDeclarator 713 | } 714 | 715 | FieldInitializerList { 716 | ":" commaSep1 717 | } 718 | 719 | FieldInitializer { 720 | (FieldIdentifier | ScopedFieldIdentifier) !arguments (InitializerList | ArgumentList) "..."? 721 | } 722 | 723 | operatorCastDefinition { 724 | (storageClassSpecifier | typeQualifier | AttributeSpecifier)* 725 | ~specifiers (kw<"virtual"> | ExplicitFunctionSpecifier)? 726 | OperatorCast (CompoundStatement | TryStatement | DefaultMethodClause | DeleteMethodClause) 727 | } 728 | 729 | operatorCastDeclaration { 730 | (kw<"virtual"> | ExplicitFunctionSpecifier)? OperatorCast ("=" expression)? ";" 731 | } 732 | 733 | constructorOrDestructorDefinition { 734 | (storageClassSpecifier | typeQualifier | AttributeSpecifier)* 735 | ~specifiers 736 | (kw<"virtual"> | ExplicitFunctionSpecifier)? 737 | FunctionDeclarator 738 | FieldInitializerList? 739 | (CompoundStatement | TryStatement | DefaultMethodClause | DeleteMethodClause) 740 | } 741 | 742 | DefaultMethodClause { 743 | "=" kw<"default"> ";" 744 | } 745 | 746 | DeleteMethodClause { 747 | "=" kw<"delete"> ";" 748 | } 749 | 750 | FriendDeclaration { 751 | kw<"friend"> (Declaration | FunctionDefinition | (kw<"class"> | kw<"struct"> | kw<"union">)? className ";") 752 | } 753 | 754 | AccessSpecifier { 755 | access ":" 756 | } 757 | 758 | TrailingReturnType { 759 | "->" typeQualifier? typeSpecifier (!absDecl abstractDeclarator)? 760 | } 761 | 762 | Noexcept { 763 | kw<"noexcept"> (!arguments "(" expression? ")")? 764 | } 765 | 766 | ThrowSpecifier { 767 | kw<"throw"> "(" commaSep ")" 768 | } 769 | 770 | TemplateType { 771 | (TypeIdentifier | ScopedTypeIdentifier) ~identifier TemplateArgumentList 772 | } 773 | 774 | TemplateMethod { 775 | (FieldIdentifier | ScopedFieldIdentifier) ~identifier TemplateArgumentList 776 | } 777 | 778 | TemplateFunction { 779 | (Identifier | ScopedIdentifier) ~identifier TemplateArgumentList 780 | } 781 | 782 | TemplateArgumentList { 783 | "<" commaSep< 784 | [@dynamicPrecedence=3] { TypeDescriptor } | 785 | ParameterPackExpansion[@dynamicPrecedence=2] { TypeDescriptor "..." } | 786 | [@dynamicPrecedence=1] { expression } 787 | > (templateArgsEnd | templateArgsEndFallback) 788 | } 789 | 790 | ConceptDefinition { 791 | kw<"concept"> Identifier "=" expression ";" 792 | } 793 | 794 | NamespaceDefinition { 795 | kw<"inline">? kw<"namespace"> (Identifier ("::" kw<"inline">? Identifier)*)? 796 | (CompoundStatement | "=" (Identifier | ScopedIdentifier) ";") 797 | } 798 | 799 | UsingDeclaration { 800 | kw<"using"> (kw<"namespace"> | kw<"enum">)? (Identifier | ScopedIdentifier) ";" 801 | } 802 | 803 | AliasDeclaration { 804 | kw<"using"> TypeIdentifier Attribute* "=" TypeDescriptor ";" 805 | } 806 | 807 | StaticAssertDeclaration { 808 | kw<"static_assert"> "(" expression ("," (String | RawString | ConcatenatedString))? ")" ";" 809 | } 810 | 811 | ModuleDeclaration { 812 | kw<"module"> (ModuleName Attribute* | ":" access)? ";" 813 | } 814 | 815 | ExportDeclaration { 816 | kw<"export"> topLevelItem 817 | } 818 | 819 | ImportDeclaration { 820 | kw<"import"> (ModuleName | HeaderName) Attribute* ";" 821 | } 822 | 823 | ModuleName { 824 | Identifier ("." Identifier)* modulePartition? | 825 | modulePartition 826 | } 827 | 828 | modulePartition { ":" PartitionName { identifier } } 829 | 830 | ConditionClause { 831 | "(" ( 832 | (Declaration | ExpressionStatement)? (expression | CommaExpression) | 833 | Declaration { declarationSpecifiers declarator ("=" expression | InitializerList) } 834 | ) ")" 835 | } 836 | 837 | ForRangeLoop { 838 | kw<"for"> "(" 839 | (AliasDeclaration | TypeDefinition | Declaration | (expression | CommaExpression)? ";")? 840 | declarationSpecifiers declarator ":" (expression | InitializerList) ")" 841 | statement 842 | } 843 | 844 | ThrowStatement { 845 | kw<"throw"> expression? ";" 846 | } 847 | 848 | TryStatement { 849 | kw<"try"> CompoundStatement CatchClause+ 850 | } 851 | 852 | CatchClause { 853 | kw<"catch"> ParameterList CompoundStatement 854 | } 855 | 856 | Attribute { 857 | "[[" commaSep "..."? "]]" 858 | } 859 | 860 | AttributeName { attributeIdentifier ("::" attributeIdentifier)* } 861 | 862 | balancedTokens { 863 | "{" balancedTokens* "}" | 864 | "[" balancedTokens* "]" | 865 | "(" balancedTokens* ")" | 866 | attributeIdentifier | 867 | incDec | ArithOp<"+" | "-"> | ArithOp { "*" } | ArithOp<"/" | "%"> | LogicOp { "||" | "&&" } | 868 | BitOp<"|"> | BitOp<"^"> | BitOp { "&" } | CompareOp<"==" | "!="> | CompareOp<"<=" | ">=" | "<=>"> | 869 | @extend[@name=CompareOp]<"<"> | @extend[@name=CompareOp]"> | BitOp<"<<" | ">>"> | 870 | UpdateOp | 871 | ";" | ":" | "," | "..." | "::" | "." | "->" | 872 | Number | String | RawString | CharLiteral 873 | } 874 | 875 | NewExpression { 876 | ("::" skw<"new"> | kw<"new">) ArgumentList? typeSpecifier (!more NewDeclarator)? (!arguments (ArgumentList | InitializerList))? 877 | } 878 | 879 | NewDeclarator { 880 | "[" expression "]" (!more NewDeclarator)? 881 | } 882 | 883 | DeleteExpression { 884 | ("::" skw<"delete"> | kw<"delete">) (!more "[" "]")? expression 885 | } 886 | 887 | LambdaExpression { 888 | LambdaCaptureSpecifier (TemplateParameterList RequiresClause)? AbstractFunctionDeclarator? CompoundStatement 889 | } 890 | 891 | LambdaCaptureSpecifier { 892 | "[" ( 893 | ("=" | "&") ("," commaSep1)? | 894 | commaSep1 | 895 | "" 896 | ) "]" !capture 897 | } 898 | 899 | ParameterPackExpansion { 900 | expression !pack "..." 901 | } 902 | 903 | ScopedFieldIdentifier { 904 | (NamespaceIdentifier | TemplateType | ScopedNamespaceIdentifier | Decltype)? !namespace 905 | "::" (FieldIdentifier { scopedIdentifier } | OperatorName> | DestructorName) 906 | } 907 | 908 | ScopedIdentifier { 909 | (NamespaceIdentifier | TemplateType | ScopedNamespaceIdentifier)? !namespace 910 | "::" (Identifier { scopedIdentifier } | OperatorName> | DestructorName) 911 | } 912 | 913 | ScopedTypeIdentifier { 914 | (NamespaceIdentifier | TemplateType | ScopedNamespaceIdentifier)? !namespace 915 | "::" TypeIdentifier { scopedIdentifier } 916 | } 917 | 918 | ScopedNamespaceIdentifier { 919 | (NamespaceIdentifier | TemplateType | ScopedNamespaceIdentifier)? !namespace 920 | "::" NamespaceIdentifier { scopedIdentifier !namespace } 921 | } 922 | 923 | NamespaceIdentifier { 924 | identifier !namespace 925 | } 926 | 927 | access { @specialize[@name=Access] } 928 | 929 | True { @specialize } 930 | 931 | False { @specialize } 932 | 933 | primitiveType { 934 | @specialize[@name=PrimitiveType] 939 | } 940 | 941 | kw { @specialize[@name={term}] } 942 | 943 | skw { @specialize[@name={term}] } 944 | 945 | commaSep { "" | term ("," term)* } 946 | 947 | commaSep1 { term ("," term)* } 948 | 949 | commaSepTrailing { "" | term ("," term?)* } 950 | 951 | @skip { whitespace | LineComment | BlockComment | PreprocDirective | Macro } 952 | 953 | @external tokens rawString from "./tokens" { RawString } 954 | 955 | @external tokens fallback from "./tokens" { templateArgsEndFallback[@name=">"], MacroName } 956 | 957 | OperatorName { 958 | opKw ( 959 | UpdateOp | incDec | "=" | 960 | ArithOp<$[*/%+\-]> | 961 | BitOp<$[^~&|] | "<<" | ">>"> | 962 | CompareOp<"<" ("=" ">"?)? | ">" "="? | $[!=] "="> | 963 | LogicOp<"!" | "&&" | "||"> | 964 | "->" (!arrowStar "*")? | "(" ")" | "[" "]" | 965 | (kw<"new"> | kw<"delete">) (!newOpArray "[" "]")? | 966 | kw<"co_await"> | 967 | '""' Identifier 968 | ) 969 | } 970 | 971 | @tokens { 972 | whitespace { 973 | ($[ \t\r\n] | "\\" "\r"? "\n")+ 974 | } 975 | 976 | pp[@name="#" {name}] { "#" $[ \t]* name } 977 | 978 | PreprocDirectiveName { 979 | "#" $[ \t]* $[a-zA-Z] $[a-zA-Z0-9_]* 980 | } 981 | 982 | @precedence { pp, PreprocDirectiveName } 983 | 984 | PreprocArg { 985 | (![\n] | "\\" "\r"? "\n")+ 986 | } 987 | 988 | ppSpace { $[ \t]+ } 989 | 990 | @precedence { "(", PreprocArg, ppSpace } 991 | 992 | Number { 993 | ("0x" | "0b")? 994 | (($[0-9]+ ("'" $[0-9]+)* | 995 | "0b" $[0-9]+ ("'" $[0-9]+)* | 996 | "0x" $[0-9a-fA-F]+ ("'" $[0-9a-fA-F]+)*) 997 | ("." ($[0-9a-fA-F]+ ("'" $[0-9a-fA-F]+)*)?)? | 998 | "." $[0-9]+ ("'" $[0-9]+)*) 999 | ($[eEpP] ($[-\+]? $[0-9a-fA-F]+ ("'" $[0-9a-fA-F]+)*)?)? ("u" | "l" | "U" | "L" | "f" | "F")* 1000 | } 1001 | 1002 | @precedence { Number, "." } 1003 | 1004 | EscapeSequence { 1005 | "\\" ( 1006 | ![xuU] | 1007 | $[0-9] $[0-9] $[0-9]? | 1008 | "x" $[0-9a-fA-F] $[0-9a-fA-F] $[0-9a-fA-F]* | 1009 | "u" $[0-9a-fA-F] $[0-9a-fA-F] $[0-9a-fA-F] $[0-9a-fA-F] | 1010 | "U" $[0-9a-fA-F] $[0-9a-fA-F] $[0-9a-fA-F] $[0-9a-fA-F] $[0-9a-fA-F] $[0-9a-fA-F] $[0-9a-fA-F] $[0-9a-fA-F] 1011 | ) 1012 | } 1013 | 1014 | SystemLibString[isolate] { 1015 | "<" (![>\n\\] | "\\" _)* ">" 1016 | } 1017 | 1018 | identifier { 1019 | $[a-zA-Z_] $[a-zA-Z0-9_]* 1020 | } 1021 | 1022 | scopedIdentifier { identifier } 1023 | 1024 | attributeIdentifier[@name=Identifier] { identifier } 1025 | 1026 | DestructorName { 1027 | "~" $[ \t]* identifier 1028 | } 1029 | 1030 | @precedence { DestructorName, BitOp } 1031 | 1032 | HeaderName { "<" ![>]+ ">" } 1033 | 1034 | LineComment[isolate] { "//" ("\\" (![\n] | "\\r"? "\\n") | ![\n])* } 1035 | 1036 | BlockComment[isolate] { "/*" blockCommentRest } 1037 | 1038 | blockCommentRest { ![*] blockCommentRest | "*" blockCommentAfterStar } 1039 | 1040 | blockCommentAfterStar { "/" | "*" blockCommentAfterStar | ![/*] blockCommentRest } 1041 | 1042 | @precedence { LineComment, BlockComment, ArithOp } 1043 | 1044 | ArithOp { expr } 1045 | 1046 | BitOp { expr } 1047 | 1048 | CompareOp { expr } 1049 | 1050 | LogicOp { expr } 1051 | 1052 | UpdateOp { 1053 | ($[*/%+\-&^|] | "<<" | ">>") "=" 1054 | } 1055 | 1056 | incDec[@name=UpdateOp] { "++" | "--" } 1057 | 1058 | charLiteralStart { "L'" | "u'" | "U'" | "u8'" | "'" } 1059 | 1060 | charLiteralEnd { "'" } 1061 | 1062 | charLiteralContent { ![\\\n']+ } 1063 | 1064 | stringLiteralStart { "L\"" | "u\"" | "U\"" | "u8\"" | "\"" } 1065 | 1066 | stringLiteralEnd { "\"" } 1067 | 1068 | stringLiteralContent { ![\\\n"]+ } 1069 | 1070 | templateArgsEnd[@name=">"] { ">" } 1071 | 1072 | "(" ")" "{" "}" "[" "]" 1073 | "," "<" "::" 1074 | 1075 | @precedence { stringLiteralStart, charLiteralStart, identifier } 1076 | @precedence { stringLiteralStart, charLiteralStart, attributeIdentifier } 1077 | } 1078 | 1079 | @external propSource cppHighlighting from "./highlight" 1080 | 1081 | @detectDelim 1082 | -------------------------------------------------------------------------------- /src/highlight.js: -------------------------------------------------------------------------------- 1 | import {styleTags, tags as t} from "@lezer/highlight" 2 | 3 | export const cppHighlighting = styleTags({ 4 | "typedef struct union enum class typename decltype auto template operator friend noexcept namespace using requires concept import export module __attribute__ __declspec __based": t.definitionKeyword, 5 | "extern MsCallModifier MsPointerModifier extern static register thread_local inline const volatile restrict _Atomic mutable constexpr constinit consteval virtual explicit VirtualSpecifier Access": t.modifier, 6 | "if else switch for while do case default return break continue goto throw try catch": t.controlKeyword, 7 | "co_return co_yield co_await": t.controlKeyword, 8 | "new sizeof delete static_assert": t.operatorKeyword, 9 | "NULL nullptr": t.null, 10 | this: t.self, 11 | "True False": t.bool, 12 | "TypeSize PrimitiveType": t.standard(t.typeName), 13 | TypeIdentifier: t.typeName, 14 | FieldIdentifier: t.propertyName, 15 | "CallExpression/FieldExpression/FieldIdentifier": t.function(t.propertyName), 16 | "ModuleName/Identifier": t.namespace, 17 | "PartitionName": t.labelName, 18 | StatementIdentifier: t.labelName, 19 | "Identifier DestructorName": t.variableName, 20 | "CallExpression/Identifier": t.function(t.variableName), 21 | "CallExpression/ScopedIdentifier/Identifier": t.function(t.variableName), 22 | "FunctionDeclarator/Identifier FunctionDeclarator/DestructorName": t.function(t.definition(t.variableName)), 23 | NamespaceIdentifier: t.namespace, 24 | OperatorName: t.operator, 25 | ArithOp: t.arithmeticOperator, 26 | LogicOp: t.logicOperator, 27 | BitOp: t.bitwiseOperator, 28 | CompareOp: t.compareOperator, 29 | AssignOp: t.definitionOperator, 30 | UpdateOp: t.updateOperator, 31 | LineComment: t.lineComment, 32 | BlockComment: t.blockComment, 33 | Number: t.number, 34 | String: t.string, 35 | "RawString SystemLibString": t.special(t.string), 36 | CharLiteral: t.character, 37 | EscapeSequence: t.escape, 38 | "UserDefinedLiteral/Identifier": t.literal, 39 | PreProcArg: t.meta, 40 | "PreprocDirectiveName #include #ifdef #ifndef #if #define #else #endif #elif": t.processingInstruction, 41 | MacroName: t.special(t.name), 42 | "( )": t.paren, 43 | "[ ]": t.squareBracket, 44 | "{ }": t.brace, 45 | "< >": t.angleBracket, 46 | ". ->": t.derefOperator, 47 | ", ;": t.separator 48 | }) 49 | -------------------------------------------------------------------------------- /src/tokens.js: -------------------------------------------------------------------------------- 1 | import {ExternalTokenizer} from "@lezer/lr" 2 | import {RawString, templateArgsEndFallback, MacroName} from "./parser.terms.js" 3 | 4 | const R = 82, L = 76, u = 117, U = 85, 5 | a = 97, z = 122, A = 65, Z = 90, Underscore = 95, 6 | Zero = 48, 7 | Quote = 34, 8 | ParenL = 40, ParenR = 41, 9 | Space = 32, Newline = 10, 10 | GreaterThan = 62 11 | 12 | export const rawString = new ExternalTokenizer(input => { 13 | // Raw string literals can start with: R, LR, uR, UR, u8R 14 | if (input.next == L || input.next == U) { 15 | input.advance() 16 | } else if (input.next == u) { 17 | input.advance() 18 | if (input.next == Zero + 8) input.advance() 19 | } 20 | if (input.next != R) return 21 | input.advance() 22 | if (input.next != Quote) return 23 | input.advance() 24 | 25 | let marker = "" 26 | while (input.next != ParenL) { 27 | if (input.next == Space || input.next <= 13 || input.next == ParenR) return 28 | marker += String.fromCharCode(input.next) 29 | input.advance() 30 | } 31 | input.advance() 32 | 33 | for (;;) { 34 | if (input.next < 0) 35 | return input.acceptToken(RawString) 36 | if (input.next == ParenR) { 37 | let match = true 38 | for (let i = 0; match && i < marker.length; i++) 39 | if (input.peek(i + 1) != marker.charCodeAt(i)) match = false 40 | if (match && input.peek(marker.length + 1) == Quote) 41 | return input.acceptToken(RawString, 2 + marker.length) 42 | } 43 | input.advance() 44 | } 45 | }) 46 | 47 | export const fallback = new ExternalTokenizer(input => { 48 | if (input.next == GreaterThan) { 49 | // Provide a template-args-closing token when the next characters 50 | // are ">>", in which case the regular tokenizer will only see a 51 | // bit shift op. 52 | if (input.peek(1) == GreaterThan) 53 | input.acceptToken(templateArgsEndFallback, 1) 54 | } else { 55 | // Notice all-uppercase identifiers 56 | let sawLetter = false, i = 0 57 | for (;; i++) { 58 | if (input.next >= A && input.next <= Z) sawLetter = true 59 | else if (input.next >= a && input.next <= z) return 60 | else if (input.next != Underscore && !(input.next >= Zero && input.next <= Zero + 9)) break 61 | input.advance() 62 | } 63 | if (sawLetter && i > 1) input.acceptToken(MacroName) 64 | } 65 | }, {extend: true}) 66 | -------------------------------------------------------------------------------- /test/ambiguities.txt: -------------------------------------------------------------------------------- 1 | # template functions vs relational expressions 2 | 3 | T1 a = b < c > d; 4 | T2 e = f(g); 5 | int a = std::get<0>(t); 6 | 7 | ==> 8 | 9 | Program( 10 | Declaration( 11 | TypeIdentifier, 12 | InitDeclarator( 13 | Identifier, 14 | BinaryExpression( 15 | BinaryExpression(Identifier, CompareOp, Identifier), 16 | CompareOp, 17 | Identifier))), 18 | Declaration( 19 | TypeIdentifier, 20 | InitDeclarator( 21 | Identifier, 22 | CallExpression( 23 | TemplateFunction(Identifier, TemplateArgumentList( 24 | TypeDescriptor(TypeIdentifier))), 25 | ArgumentList(Identifier)))), 26 | Declaration( 27 | PrimitiveType, 28 | InitDeclarator( 29 | Identifier, 30 | CallExpression( 31 | TemplateFunction( 32 | ScopedIdentifier(NamespaceIdentifier, Identifier), 33 | TemplateArgumentList(Number)), 34 | ArgumentList(Identifier))))) 35 | 36 | 37 | # function declarations vs variable initializations 38 | 39 | // Function declarations 40 | T1 a(T2 *b); 41 | T3 c(T4 &d, T5 &&e); 42 | 43 | // Variable declarations with initializers 44 | T7 f(g.h); 45 | T6 i{j}; 46 | 47 | ==> 48 | 49 | Program( 50 | LineComment, 51 | Declaration( 52 | TypeIdentifier, 53 | FunctionDeclarator( 54 | Identifier, 55 | ParameterList(ParameterDeclaration(TypeIdentifier, PointerDeclarator(Identifier))))), 56 | Declaration( 57 | TypeIdentifier, 58 | FunctionDeclarator( 59 | Identifier, 60 | ParameterList( 61 | ParameterDeclaration(TypeIdentifier, ReferenceDeclarator(Identifier)), 62 | ParameterDeclaration(TypeIdentifier, ReferenceDeclarator(Identifier))))), 63 | 64 | LineComment, 65 | Declaration( 66 | TypeIdentifier, 67 | InitDeclarator( 68 | Identifier, 69 | ArgumentList(FieldExpression(Identifier, FieldIdentifier)))), 70 | Declaration( 71 | TypeIdentifier, 72 | InitDeclarator( 73 | Identifier, 74 | InitializerList(Identifier)))) 75 | 76 | 77 | # template classes vs relational expressions 78 | 79 | int main() { 80 | T1 v1; 81 | T1 v2 = v3; 82 | } 83 | 84 | ==> 85 | 86 | Program(FunctionDefinition( 87 | PrimitiveType, 88 | FunctionDeclarator(Identifier, ParameterList), 89 | CompoundStatement( 90 | Declaration( 91 | TemplateType(TypeIdentifier, 92 | TemplateArgumentList(TypeDescriptor(TypeIdentifier))), 93 | Identifier), 94 | Declaration( 95 | TemplateType(TypeIdentifier, 96 | TemplateArgumentList(TypeDescriptor(TypeIdentifier))), 97 | InitDeclarator(Identifier, Identifier))))) 98 | 99 | -------------------------------------------------------------------------------- /test/cpp20.txt: -------------------------------------------------------------------------------- 1 | # Concept definition 2 | 3 | template 4 | concept Derived = std::is_base_of::value; 5 | 6 | ==> 7 | 8 | Program(TemplateDeclaration( 9 | template, 10 | TemplateParameterList(TypeParameterDeclaration(class,TypeIdentifier),TypeParameterDeclaration(class,TypeIdentifier)), 11 | ConceptDefinition(concept,Identifier,ScopedIdentifier( 12 | TemplateType( 13 | ScopedTypeIdentifier(NamespaceIdentifier,TypeIdentifier), 14 | TemplateArgumentList(TypeDescriptor(TypeIdentifier),TypeDescriptor(TypeIdentifier))), 15 | Identifier)))) 16 | 17 | # Concept definition with requires expression 18 | 19 | template 20 | concept Hashable = requires(T a) { 21 | { std::hash{}(a) } -> std::convertible_to; 22 | }; 23 | 24 | ==> 25 | 26 | Program(TemplateDeclaration( 27 | template,TemplateParameterList(TypeParameterDeclaration(typename,TypeIdentifier)), 28 | ConceptDefinition(concept,Identifier, 29 | RequiresExpression(requires,ParameterList(ParameterDeclaration(TypeIdentifier,Identifier)),RequirementList( 30 | CompoundRequirement( 31 | CallExpression(CompoundLiteralExpression(TemplateType(ScopedTypeIdentifier(NamespaceIdentifier,TypeIdentifier), 32 | TemplateArgumentList(TypeDescriptor(TypeIdentifier))),InitializerList),ArgumentList(Identifier)), 33 | ReturnTypeRequirement(TemplateFunction(ScopedIdentifier(NamespaceIdentifier,Identifier), 34 | TemplateArgumentList(TypeDescriptor(ScopedTypeIdentifier(NamespaceIdentifier,TypeIdentifier))))))))))) 35 | 36 | # Requires clauses and expressions 37 | 38 | template 39 | void f(T&&) requires Eq; // can appear as the last element of a function declarator 40 | 41 | template requires Addable // or right after a template parameter list 42 | T add(T a, T b) { return a + b; } 43 | 44 | template 45 | concept Addable = requires (T x) { x + x; }; // requires-expression 46 | 47 | template 48 | requires requires (T x) { x + x; } // ad-hoc constraint, note keyword used twice 49 | T add(T a, T b) { return a + b; } 50 | 51 | template 52 | requires (!std::is_same_v) // parenthesized expressions are allowed 53 | void f(T); 54 | 55 | template requires Addable && Subtractable // conjunctions 56 | T f(T); 57 | 58 | template requires Addable || Subtractable // disjunctions 59 | T f(T); 60 | 61 | template requires false || true // boolean literals 62 | T f(T); 63 | 64 | template requires (... && Addable) // fold expressions 65 | T f(T); 66 | 67 | ==> 68 | 69 | Program( 70 | TemplateDeclaration(template,TemplateParameterList(TypeParameterDeclaration(typename,TypeIdentifier)), 71 | Declaration(PrimitiveType,FunctionDeclarator(Identifier, 72 | ParameterList(ParameterDeclaration(TypeIdentifier,AbstractReferenceDeclarator)), 73 | RequiresClause(requires,TemplateType(TypeIdentifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier))))))), 74 | LineComment, 75 | TemplateDeclaration( 76 | template, 77 | TemplateParameterList(TypeParameterDeclaration(typename,TypeIdentifier)), 78 | RequiresClause(requires,TemplateType(TypeIdentifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier)))), 79 | LineComment, 80 | FunctionDefinition(TypeIdentifier,FunctionDeclarator(Identifier,ParameterList( 81 | ParameterDeclaration(TypeIdentifier,Identifier), 82 | ParameterDeclaration(TypeIdentifier,Identifier))), 83 | CompoundStatement(ReturnStatement(return,BinaryExpression(Identifier,ArithOp,Identifier))))), 84 | TemplateDeclaration(template, 85 | TemplateParameterList(TypeParameterDeclaration(typename,TypeIdentifier)), 86 | ConceptDefinition(concept,Identifier, 87 | RequiresExpression(requires,ParameterList(ParameterDeclaration(TypeIdentifier,Identifier)), 88 | RequirementList(SimpleRequirement(BinaryExpression(Identifier,ArithOp,Identifier)))))), 89 | LineComment, 90 | TemplateDeclaration(template, 91 | TemplateParameterList(TypeParameterDeclaration(typename,TypeIdentifier)), 92 | RequiresClause(requires,RequiresExpression(requires, 93 | ParameterList(ParameterDeclaration(TypeIdentifier,Identifier)), 94 | RequirementList(SimpleRequirement(BinaryExpression(Identifier,ArithOp,Identifier))))), 95 | LineComment, 96 | FunctionDefinition(TypeIdentifier,FunctionDeclarator(Identifier,ParameterList( 97 | ParameterDeclaration(TypeIdentifier,Identifier), 98 | ParameterDeclaration(TypeIdentifier,Identifier))), 99 | CompoundStatement(ReturnStatement(return,BinaryExpression(Identifier,ArithOp,Identifier))))), 100 | TemplateDeclaration(template, 101 | TemplateParameterList(TypeParameterDeclaration(typename,TypeIdentifier)), 102 | RequiresClause(requires,ParenthesizedExpression(UnaryExpression(LogicOp,TemplateFunction( 103 | ScopedIdentifier(NamespaceIdentifier,Identifier), 104 | TemplateArgumentList(TypeDescriptor(TypeIdentifier),TypeDescriptor(PrimitiveType)))))), 105 | LineComment, 106 | Declaration(PrimitiveType,FunctionDeclarator(Identifier,ParameterList(ParameterDeclaration(TypeIdentifier))))), 107 | TemplateDeclaration(template, 108 | TemplateParameterList(TypeParameterDeclaration(typename,TypeIdentifier)), 109 | RequiresClause(requires,ConstraintConjuction( 110 | TemplateType(TypeIdentifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier))), 111 | LogicOp, 112 | TemplateType(TypeIdentifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier))))), 113 | LineComment, 114 | Declaration(TypeIdentifier,FunctionDeclarator(Identifier,ParameterList(ParameterDeclaration(TypeIdentifier))))), 115 | TemplateDeclaration(template, 116 | TemplateParameterList(TypeParameterDeclaration(typename,TypeIdentifier)), 117 | RequiresClause(requires,ConstraintDisjunction( 118 | TemplateType(TypeIdentifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier))), 119 | LogicOp, 120 | TemplateType(TypeIdentifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier))))), 121 | LineComment, 122 | Declaration(TypeIdentifier,FunctionDeclarator(Identifier,ParameterList(ParameterDeclaration(TypeIdentifier))))), 123 | TemplateDeclaration(template, 124 | TemplateParameterList(TypeParameterDeclaration(typename,TypeIdentifier)), 125 | RequiresClause(requires,ConstraintDisjunction(False,LogicOp,True)), 126 | LineComment, 127 | Declaration(TypeIdentifier,FunctionDeclarator(Identifier,ParameterList(ParameterDeclaration(TypeIdentifier))))), 128 | TemplateDeclaration(template, 129 | TemplateParameterList(VariadicTypeParameterDeclaration(typename,TypeIdentifier)), 130 | RequiresClause(requires,ParenthesizedExpression(BinaryExpression( 131 | ParamPack, 132 | LogicOp, 133 | TemplateFunction(Identifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier)))))), 134 | LineComment, 135 | Declaration(TypeIdentifier,FunctionDeclarator(Identifier,ParameterList(ParameterDeclaration(TypeIdentifier)))))) 136 | 137 | # Compound requirements 138 | 139 | template concept C2 = 140 | requires(T x) { 141 | {*x} -> std::convertible_to; // the expression *x must be valid 142 | // AND the type T::inner must be valid 143 | // AND the result of *x must be convertible to T::inner 144 | {x + 1} -> std::same_as; // the expression x + 1 must be valid 145 | // AND std::same_as must be satisfied 146 | // i.e., (x + 1) must be a prvalue of type int 147 | {x * 1} -> std::convertible_to; // the expression x * 1 must be valid 148 | // AND its result must be convertible to T 149 | }; 150 | 151 | ==> 152 | 153 | Program( 154 | TemplateDeclaration(template, 155 | TemplateParameterList(TypeParameterDeclaration(typename,TypeIdentifier)), 156 | ConceptDefinition(concept,Identifier,RequiresExpression( 157 | requires, 158 | ParameterList(ParameterDeclaration(TypeIdentifier,Identifier)), 159 | RequirementList(CompoundRequirement( 160 | PointerExpression(Identifier), 161 | ReturnTypeRequirement(TemplateFunction( 162 | ScopedIdentifier(NamespaceIdentifier,Identifier), 163 | TemplateArgumentList( 164 | TypeDescriptor(DependentType(typename,ScopedTypeIdentifier(NamespaceIdentifier,TypeIdentifier))))))), 165 | LineComment, 166 | LineComment, 167 | LineComment, 168 | CompoundRequirement( 169 | BinaryExpression(Identifier,ArithOp,Number), 170 | ReturnTypeRequirement(TemplateFunction(ScopedIdentifier(NamespaceIdentifier,Identifier), 171 | TemplateArgumentList(TypeDescriptor(PrimitiveType))))), 172 | LineComment, 173 | LineComment, 174 | LineComment, 175 | CompoundRequirement( 176 | BinaryExpression(Identifier,ArithOp,Number), 177 | ReturnTypeRequirement(TemplateFunction(ScopedIdentifier(NamespaceIdentifier,Identifier), 178 | TemplateArgumentList(TypeDescriptor(TypeIdentifier))))), 179 | LineComment, 180 | LineComment))))) 181 | 182 | # Nested requirements 183 | 184 | template 185 | concept Semiregular = DefaultConstructible && 186 | CopyConstructible && Destructible && CopyAssignable && 187 | requires(T a, size_t n) { 188 | requires Same; // nested: 189 | { a.~T() } noexcept; // compound: is a valid expression that doesn't throw 190 | requires Same; // nested: 191 | requires Same; // nested 192 | { delete new T }; // compound 193 | { delete new T[n] }; // compound 194 | }; 195 | 196 | ==> 197 | 198 | Program(TemplateDeclaration(template, 199 | TemplateParameterList(TypeParameterDeclaration(class,TypeIdentifier)), 200 | ConceptDefinition(concept,Identifier,BinaryExpression( 201 | BinaryExpression( 202 | BinaryExpression( 203 | BinaryExpression( 204 | TemplateFunction(Identifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier))), 205 | LogicOp, 206 | TemplateFunction(Identifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier)))), 207 | LogicOp, 208 | TemplateFunction(Identifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier)))), 209 | LogicOp, 210 | TemplateFunction(Identifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier)))), 211 | LogicOp, 212 | RequiresExpression(requires, 213 | ParameterList(ParameterDeclaration(TypeIdentifier,Identifier),ParameterDeclaration(PrimitiveType,Identifier)), 214 | RequirementList( 215 | RequiresClause(requires,TemplateType(TypeIdentifier,TemplateArgumentList( 216 | TypeDescriptor(TypeIdentifier,AbstractPointerDeclarator), 217 | TypeDescriptor(Decltype(decltype,PointerExpression(Identifier)))))), 218 | LineComment, 219 | CompoundRequirement(CallExpression(FieldExpression(Identifier,DestructorName),ArgumentList),noexcept), 220 | LineComment, 221 | RequiresClause(requires,TemplateType(TypeIdentifier,TemplateArgumentList( 222 | TypeDescriptor(TypeIdentifier,AbstractPointerDeclarator), 223 | TypeDescriptor(Decltype(decltype,NewExpression(new,TypeIdentifier)))))), 224 | LineComment, 225 | RequiresClause(requires,TemplateType(TypeIdentifier,TemplateArgumentList( 226 | TypeDescriptor(TypeIdentifier,AbstractPointerDeclarator), 227 | TypeDescriptor(Decltype(decltype,NewExpression(new,TypeIdentifier,NewDeclarator(Identifier))))))), 228 | LineComment, 229 | CompoundRequirement(DeleteExpression(delete,NewExpression(new,TypeIdentifier))), 230 | LineComment, 231 | CompoundRequirement(DeleteExpression(delete,NewExpression(new,TypeIdentifier,NewDeclarator(Identifier)))), 232 | LineComment)))))) 233 | 234 | # Constraints 235 | 236 | template 237 | void f(const T&); // constrained function template declaration 238 | 239 | void f(const EqualityComparable auto&); // constrained function template declaration 240 | 241 | Sortable auto foo = f(); 242 | Sortable auto bar = g(); 243 | NS::Concept auto baz = h(); 244 | 245 | Sortable decltype(auto) foo = i(); 246 | 247 | ==> 248 | 249 | Program( 250 | TemplateDeclaration(template, 251 | TemplateParameterList(ParameterDeclaration(TypeIdentifier,Identifier)), 252 | Declaration(PrimitiveType,FunctionDeclarator(Identifier,ParameterList(ParameterDeclaration( 253 | const,TypeIdentifier,AbstractReferenceDeclarator))))), 254 | LineComment, 255 | Declaration(PrimitiveType,FunctionDeclarator(Identifier,ParameterList( 256 | ParameterDeclaration(const,PlaceholderTypeSpecifier(TypeIdentifier,auto),AbstractReferenceDeclarator)))), 257 | LineComment, 258 | Declaration( 259 | PlaceholderTypeSpecifier(TypeIdentifier,auto),InitDeclarator(Identifier,CallExpression(Identifier,ArgumentList))), 260 | Declaration( 261 | PlaceholderTypeSpecifier(TemplateType(TypeIdentifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier))),auto), 262 | InitDeclarator(Identifier,CallExpression(Identifier,ArgumentList))), 263 | Declaration( 264 | PlaceholderTypeSpecifier(TemplateType(ScopedTypeIdentifier(NamespaceIdentifier,TypeIdentifier),TemplateArgumentList(TypeDescriptor(TypeIdentifier))),auto), 265 | InitDeclarator(Identifier,CallExpression(Identifier,ArgumentList))), 266 | Declaration( 267 | PlaceholderTypeSpecifier(TypeIdentifier,Decltype(decltype,auto)), 268 | InitDeclarator(Identifier,CallExpression(Identifier,ArgumentList)))) 269 | 270 | # Namespace definitions 271 | 272 | namespace std { 273 | 274 | int x; 275 | 276 | } // namespace std 277 | 278 | namespace A::B { } 279 | namespace A::B::inline C::D { } 280 | 281 | ==> 282 | 283 | Program( 284 | NamespaceDefinition(namespace,Identifier,CompoundStatement(Declaration(PrimitiveType,Identifier))), 285 | LineComment, 286 | NamespaceDefinition(namespace,Identifier,Identifier,CompoundStatement), 287 | NamespaceDefinition(namespace,Identifier,Identifier,inline,Identifier,Identifier,CompoundStatement)) 288 | 289 | # Namespace alias definitions 290 | 291 | namespace A = B; 292 | namespace C = ::D; 293 | namespace fs = std::filesystem; 294 | namespace bfs = ::boost::filesystem; 295 | namespace literals = std::chono::literals; 296 | 297 | ==> 298 | 299 | Program( 300 | NamespaceDefinition(namespace,Identifier,Identifier), 301 | NamespaceDefinition(namespace,Identifier,ScopedIdentifier(Identifier)), 302 | NamespaceDefinition(namespace,Identifier,ScopedIdentifier(NamespaceIdentifier,Identifier)), 303 | NamespaceDefinition(namespace,Identifier,ScopedIdentifier(ScopedNamespaceIdentifier(NamespaceIdentifier),Identifier)), 304 | NamespaceDefinition(namespace,Identifier,ScopedIdentifier( 305 | ScopedNamespaceIdentifier(NamespaceIdentifier,NamespaceIdentifier),Identifier))) 306 | 307 | # Reference declarations 308 | 309 | int main() { 310 | T &x = y(); 311 | } 312 | 313 | ==> 314 | 315 | Program(FunctionDefinition(PrimitiveType,FunctionDeclarator(Identifier,ParameterList),CompoundStatement( 316 | Declaration(TypeIdentifier,InitDeclarator(ReferenceDeclarator(Identifier),CallExpression( 317 | TemplateFunction(Identifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier,AbstractReferenceDeclarator))), 318 | ArgumentList)))))) 319 | 320 | # R-value reference declarations 321 | 322 | int main(T &&); 323 | 324 | int main(T &&t) { 325 | const U &&u = v; 326 | } 327 | 328 | ==> 329 | 330 | Program( 331 | Declaration(PrimitiveType, 332 | FunctionDeclarator(Identifier,ParameterList(ParameterDeclaration(TypeIdentifier,AbstractReferenceDeclarator)))), 333 | FunctionDefinition(PrimitiveType, 334 | FunctionDeclarator(Identifier,ParameterList(ParameterDeclaration(TypeIdentifier,ReferenceDeclarator(Identifier)))), 335 | CompoundStatement(Declaration(const,TypeIdentifier,InitDeclarator(ReferenceDeclarator(Identifier),Identifier))))) 336 | 337 | # Function-try-block definitions 338 | 339 | void foo() try {} catch(...) {} 340 | 341 | ==> 342 | 343 | Program(FunctionDefinition(PrimitiveType,FunctionDeclarator(Identifier,ParameterList),TryStatement( 344 | try,CompoundStatement,CatchClause(catch,ParameterList,CompoundStatement)))) 345 | 346 | # Inline try method definitions 347 | 348 | struct S { 349 | int getF2() const try { throw 1; } catch (...) { return f; } 350 | }; 351 | 352 | ==> 353 | 354 | Program(StructSpecifier(struct,TypeIdentifier,FieldDeclarationList( 355 | FunctionDefinition(PrimitiveType, 356 | FunctionDeclarator(FieldIdentifier,ParameterList,const), 357 | TryStatement(try, 358 | CompoundStatement(ThrowStatement(throw,Number)), 359 | CatchClause(catch,ParameterList,CompoundStatement(ReturnStatement(return,Identifier)))))))) 360 | 361 | # Classes with inheritance 362 | 363 | class F : [[deprecated]] public G {}; 364 | class H : public virtual I {}; 365 | class J : virtual protected I {}; 366 | 367 | ==> 368 | 369 | Program( 370 | ClassSpecifier(class,TypeIdentifier,BaseClassClause(Attribute(AttributeName(Identifier)),Access,TypeIdentifier), 371 | FieldDeclarationList), 372 | ClassSpecifier(class,TypeIdentifier,BaseClassClause(Access,virtual,TypeIdentifier),FieldDeclarationList), 373 | ClassSpecifier(class,TypeIdentifier,BaseClassClause(virtual,Access,TypeIdentifier),FieldDeclarationList)) 374 | 375 | # Attributes on declarations 376 | 377 | [[aaa]] 378 | int f() { } 379 | 380 | class [[gnu::visibility("default")]] A {}; 381 | struct [[gnu::visibility("default")]] A {}; 382 | union [[gnu::visibility("default")]] A {}; 383 | 384 | class [[gnu::visibility("default")]] [[deprecated]] A {}; 385 | class A final : [[deprecated]] public B {}; 386 | 387 | ==> 388 | 389 | Program( 390 | FunctionDefinition(Attribute(AttributeName(Identifier)),PrimitiveType, 391 | FunctionDeclarator(Identifier,ParameterList),CompoundStatement), 392 | ClassSpecifier(class,Attribute(AttributeName(Identifier,Identifier),AttributeArgs(String)),TypeIdentifier, 393 | FieldDeclarationList), 394 | StructSpecifier(struct,Attribute(AttributeName(Identifier,Identifier),AttributeArgs(String)),TypeIdentifier, 395 | FieldDeclarationList), 396 | UnionSpecifier(union,Attribute(AttributeName(Identifier,Identifier),AttributeArgs(String)),TypeIdentifier, 397 | FieldDeclarationList), 398 | ClassSpecifier(class, 399 | Attribute(AttributeName(Identifier,Identifier),AttributeArgs(String)), 400 | Attribute(AttributeName(Identifier)), 401 | TypeIdentifier,FieldDeclarationList), 402 | ClassSpecifier(class,TypeIdentifier,VirtualSpecifier, 403 | BaseClassClause(Attribute(AttributeName(Identifier)),Access,TypeIdentifier), 404 | FieldDeclarationList)) 405 | 406 | # Constinit/consteval declarations 407 | 408 | consteval int answer(); 409 | constinit int life = answer(); 410 | 411 | ==> 412 | 413 | Program( 414 | Declaration(consteval,PrimitiveType,FunctionDeclarator(Identifier,ParameterList)), 415 | Declaration(constinit,PrimitiveType,InitDeclarator(Identifier,CallExpression(Identifier,ArgumentList)))) 416 | 417 | # Ref-qualifiers 418 | 419 | class C 420 | { 421 | void f() &; 422 | void f() && noexcept; 423 | void f() & {} 424 | void f() & noexcept {} 425 | }; 426 | 427 | void C::f() &; 428 | void C::f() & noexcept; 429 | void C::f() && {} 430 | void C::f() & noexcept {} 431 | 432 | ==> 433 | 434 | Program( 435 | ClassSpecifier(class,TypeIdentifier,FieldDeclarationList( 436 | FieldDeclaration(PrimitiveType,FunctionDeclarator(FieldIdentifier,ParameterList)), 437 | FieldDeclaration(PrimitiveType,FunctionDeclarator(FieldIdentifier,ParameterList,Noexcept(noexcept))), 438 | FunctionDefinition(PrimitiveType,FunctionDeclarator(FieldIdentifier,ParameterList),CompoundStatement), 439 | FunctionDefinition(PrimitiveType,FunctionDeclarator(FieldIdentifier,ParameterList,Noexcept(noexcept)), 440 | CompoundStatement))), 441 | Declaration(PrimitiveType,FunctionDeclarator(ScopedIdentifier(NamespaceIdentifier,Identifier),ParameterList)), 442 | Declaration(PrimitiveType, 443 | FunctionDeclarator(ScopedIdentifier(NamespaceIdentifier,Identifier),ParameterList,Noexcept(noexcept))), 444 | FunctionDefinition(PrimitiveType, 445 | FunctionDeclarator(ScopedIdentifier(NamespaceIdentifier,Identifier),ParameterList),CompoundStatement), 446 | FunctionDefinition(PrimitiveType, 447 | FunctionDeclarator(ScopedIdentifier(NamespaceIdentifier,Identifier),ParameterList,Noexcept(noexcept)),CompoundStatement)) 448 | 449 | # Default comparison declarations 450 | 451 | struct A { 452 | auto operator<=>(A const &) = default; 453 | }; 454 | 455 | ==> 456 | 457 | Program(StructSpecifier(struct,TypeIdentifier,FieldDeclarationList( 458 | FunctionDefinition(auto,FunctionDeclarator( 459 | OperatorName(operator,CompareOp), 460 | ParameterList(ParameterDeclaration(TypeIdentifier,const,AbstractReferenceDeclarator))), 461 | DefaultMethodClause(default))))) 462 | 463 | # Parameter pack expansions 464 | 465 | container t1; 466 | container t2; 467 | 468 | typedef Tuple...> type; 469 | 470 | f(&args...); // expands to f(&E1, &E2, &E3) 471 | f(n, ++args...); // expands to f(n, ++E1, ++E2, ++E3); 472 | f(++args..., n); // expands to f(++E1, ++E2, ++E3, n); 473 | f(const_cast(&args)...); // f(const_cast(&X1), const_cast(&X2), const_cast(&X3)) 474 | f(h(args...) + args...); // expands to f(h(E1,E2,E3) + E1, h(E1,E2,E3) + E2, h(E1,E2,E3) + E3) 475 | 476 | const int size = sizeof...(args) + 2; 477 | int res[size] = {1,args...,2}; 478 | int dummy[sizeof...(Ts)] = { (std::cout << args, 0)... }; 479 | 480 | auto lm = [&, args...] { return g(args...); }; 481 | 482 | class X : public Mixins... { 483 | public: 484 | X(const Mixins&... mixins) : Mixins(mixins)... { } 485 | }; 486 | 487 | template 488 | void wrap(Args&&... args) { 489 | f(forward(args)...); 490 | } 491 | 492 | void f(T...) {} 493 | 494 | ==> 495 | 496 | Program( 497 | Declaration(TemplateType(TypeIdentifier,TemplateArgumentList( 498 | TypeDescriptor(TypeIdentifier), 499 | TypeDescriptor(TypeIdentifier), 500 | ParameterPackExpansion(TypeDescriptor(TypeIdentifier)) 501 | )),Identifier), 502 | Declaration(TemplateType(TypeIdentifier,TemplateArgumentList( 503 | ParameterPackExpansion(TypeDescriptor(TypeIdentifier)), 504 | TypeDescriptor(TypeIdentifier), 505 | TypeDescriptor(TypeIdentifier) 506 | )),Identifier), 507 | TypeDefinition(typedef,TemplateType(TypeIdentifier,TemplateArgumentList( 508 | ParameterPackExpansion(TypeDescriptor(TemplateType(TypeIdentifier,TemplateArgumentList( 509 | TypeDescriptor(TypeIdentifier),TypeDescriptor(TypeIdentifier))))))),TypeIdentifier), 510 | ExpressionStatement(CallExpression(Identifier,ArgumentList(ParameterPackExpansion(PointerExpression(Identifier))))), 511 | LineComment, 512 | ExpressionStatement(CallExpression(Identifier,ArgumentList( 513 | Identifier, 514 | ParameterPackExpansion(UpdateExpression(UpdateOp,Identifier))))), 515 | LineComment, 516 | ExpressionStatement(CallExpression(Identifier,ArgumentList( 517 | ParameterPackExpansion(UpdateExpression(UpdateOp,Identifier)),Identifier))), 518 | LineComment, 519 | ExpressionStatement(CallExpression(Identifier,ArgumentList( 520 | ParameterPackExpansion(CallExpression(TemplateFunction(Identifier,TemplateArgumentList( 521 | TypeDescriptor(const,TypeIdentifier,AbstractPointerDeclarator) 522 | )),ArgumentList(PointerExpression(Identifier))))))), 523 | LineComment, 524 | ExpressionStatement(CallExpression(Identifier,ArgumentList(ParameterPackExpansion(BinaryExpression( 525 | CallExpression(Identifier,ArgumentList(ParameterPackExpansion(Identifier))), 526 | ArithOp, 527 | Identifier))))), 528 | LineComment, 529 | Declaration(const,PrimitiveType,InitDeclarator(Identifier,BinaryExpression( 530 | SizeofExpression(sizeof,Identifier), 531 | ArithOp, 532 | Number))), 533 | Declaration(PrimitiveType, 534 | InitDeclarator(ArrayDeclarator(Identifier,Identifier),InitializerList(Number,ParameterPackExpansion(Identifier),Number))), 535 | Declaration(PrimitiveType,InitDeclarator( 536 | ArrayDeclarator(Identifier,SizeofExpression(sizeof,Identifier)), 537 | InitializerList(ParameterPackExpansion(ParenthesizedExpression(CommaExpression( 538 | BinaryExpression(ScopedIdentifier(NamespaceIdentifier,Identifier),BitOp,Identifier), 539 | Number)))))), 540 | Declaration(auto,InitDeclarator(Identifier,LambdaExpression( 541 | LambdaCaptureSpecifier(ParameterPackExpansion(Identifier)), 542 | CompoundStatement(ReturnStatement(return,CallExpression(Identifier,ArgumentList(ParameterPackExpansion(Identifier)))))))), 543 | ClassSpecifier(class,TypeIdentifier,BaseClassClause(Access,TypeIdentifier),FieldDeclarationList( 544 | AccessSpecifier(Access), 545 | FunctionDefinition(FunctionDeclarator(Identifier,ParameterList( 546 | VariadicParameterDeclaration(const,TypeIdentifier,ReferenceDeclarator(VariadicDeclarator(Identifier)))) 547 | ),FieldInitializerList(FieldInitializer(FieldIdentifier,ArgumentList(Identifier))),CompoundStatement))), 548 | TemplateDeclaration(template, 549 | TemplateParameterList(VariadicTypeParameterDeclaration(typename,TypeIdentifier)), 550 | FunctionDefinition(PrimitiveType,FunctionDeclarator(Identifier,ParameterList( 551 | VariadicParameterDeclaration(TypeIdentifier,ReferenceDeclarator(VariadicDeclarator(Identifier))) 552 | )),CompoundStatement( 553 | ExpressionStatement(CallExpression(Identifier,ArgumentList( 554 | ParameterPackExpansion(CallExpression(TemplateFunction(Identifier,TemplateArgumentList( 555 | TypeDescriptor(TypeIdentifier) 556 | )),ArgumentList(Identifier))))))))), 557 | FunctionDefinition(PrimitiveType, 558 | FunctionDeclarator(Identifier,ParameterList(VariadicParameterDeclaration(TypeIdentifier,VariadicDeclarator))), 559 | CompoundStatement)) 560 | 561 | # User-defined literals 562 | 563 | 1.2_km; 564 | "foo" "bar"_baz; 565 | 566 | ==> 567 | 568 | Program( 569 | ExpressionStatement(UserDefinedLiteral(Number,Identifier)), 570 | ExpressionStatement(UserDefinedLiteral(ConcatenatedString(String,String),Identifier))) 571 | 572 | # Coroutines 573 | 574 | co_await fn() || co_await var; 575 | co_return 1; 576 | co_return; 577 | co_yield 1; 578 | 579 | ==> 580 | 581 | Program( 582 | ExpressionStatement(BinaryExpression( 583 | CoAwaitExpression(co_await,CallExpression(Identifier,ArgumentList)), 584 | LogicOp, 585 | CoAwaitExpression(co_await,Identifier))), 586 | CoReturnStatement(co_return,Number), 587 | CoReturnStatement(co_return), 588 | CoYieldStatement(co_yield,Number)) 589 | 590 | # Fold Expressions 591 | 592 | bool t = (... + IndexOf); 593 | bool t2 = (IndexOf + ...); 594 | bool t3 = (1 + ... + IndexOf); 595 | bool t3 = (IndexOf + ... + 1); 596 | 597 | ==> 598 | 599 | Program( 600 | Declaration(PrimitiveType,InitDeclarator(Identifier,ParenthesizedExpression(BinaryExpression( 601 | ParamPack, 602 | ArithOp, 603 | TemplateFunction(Identifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier))))))), 604 | Declaration(PrimitiveType,InitDeclarator(Identifier,ParenthesizedExpression(BinaryExpression( 605 | TemplateFunction(Identifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier))), 606 | ArithOp, 607 | ParamPack)))), 608 | Declaration(PrimitiveType,InitDeclarator(Identifier,ParenthesizedExpression(BinaryExpression( 609 | BinaryExpression(Number,ArithOp,ParamPack), 610 | ArithOp, 611 | TemplateFunction(Identifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier))))))), 612 | Declaration(PrimitiveType,InitDeclarator(Identifier,ParenthesizedExpression(BinaryExpression( 613 | BinaryExpression(TemplateFunction(Identifier,TemplateArgumentList(TypeDescriptor(TypeIdentifier))),ArithOp,ParamPack), 614 | ArithOp, 615 | Number))))) 616 | 617 | # Range-based for loops 618 | 619 | T main() { 620 | for (auto n = v.size(); auto i : v) { 621 | cout << --n + i << ' '; 622 | } 623 | 624 | for (using elem_t = T::value_type; elem_t i : v) { 625 | cout << --n + i << ' '; 626 | } 627 | } 628 | 629 | ==> 630 | 631 | Program(FunctionDefinition(TypeIdentifier,FunctionDeclarator(Identifier,ParameterList),CompoundStatement( 632 | ForRangeLoop(for, 633 | Declaration(auto,InitDeclarator(Identifier,CallExpression(FieldExpression(Identifier,FieldIdentifier),ArgumentList))), 634 | auto,Identifier,Identifier, 635 | CompoundStatement( 636 | ExpressionStatement(BinaryExpression( 637 | BinaryExpression(Identifier,BitOp,BinaryExpression(UpdateExpression(UpdateOp,Identifier),ArithOp,Identifier)), 638 | BitOp, 639 | CharLiteral)))), 640 | ForRangeLoop(for, 641 | AliasDeclaration(using,TypeIdentifier,TypeDescriptor(ScopedTypeIdentifier(NamespaceIdentifier,TypeIdentifier))), 642 | TypeIdentifier,Identifier,Identifier, 643 | CompoundStatement( 644 | ExpressionStatement(BinaryExpression( 645 | BinaryExpression(Identifier,BitOp,BinaryExpression(UpdateExpression(UpdateOp,Identifier),ArithOp,Identifier)), 646 | BitOp, 647 | CharLiteral))))))) 648 | 649 | # Attributes 650 | 651 | void f() { 652 | [[a]] switch (b) { 653 | [[c]] case 1: {} 654 | } 655 | [[a]] while (true) {} 656 | [[a]] if (true) {} 657 | [[a]] for (auto x : y) {} 658 | [[a]] for (;;) {} 659 | [[a]] return; 660 | [[a]] a; 661 | [[a]]; 662 | [[a]] label: {} 663 | [[a]] goto label; 664 | } 665 | 666 | ==> 667 | 668 | Program(FunctionDefinition(PrimitiveType,FunctionDeclarator(Identifier,ParameterList),CompoundStatement( 669 | AttributeStatement( 670 | Attribute(AttributeName(Identifier)), 671 | SwitchStatement(switch,ConditionClause(Identifier),CompoundStatement( 672 | AttributeStatement(Attribute(AttributeName(Identifier)),CaseStatement(case,Number,CompoundStatement))))), 673 | AttributeStatement(Attribute(AttributeName(Identifier)),WhileStatement(while,ConditionClause(True),CompoundStatement)), 674 | AttributeStatement(Attribute(AttributeName(Identifier)),IfStatement(if,ConditionClause(True),CompoundStatement)), 675 | AttributeStatement(Attribute(AttributeName(Identifier)),ForRangeLoop(for,auto,Identifier,Identifier,CompoundStatement)), 676 | AttributeStatement(Attribute(AttributeName(Identifier)),ForStatement(for,CompoundStatement)), 677 | AttributeStatement(Attribute(AttributeName(Identifier)),ReturnStatement(return)), 678 | AttributeStatement(Attribute(AttributeName(Identifier)),ExpressionStatement(Identifier)), 679 | AttributeStatement(Attribute(AttributeName(Identifier)),ExpressionStatement), 680 | AttributeStatement(Attribute(AttributeName(Identifier)),LabeledStatement(StatementIdentifier,CompoundStatement)), 681 | AttributeStatement(Attribute(AttributeName(Identifier)),GotoStatement(goto,StatementIdentifier))))) 682 | 683 | # Modules 684 | 685 | export module helloworld; 686 | module a.b; 687 | module : private; 688 | import a:C; 689 | import ; 690 | export void hello() {} 691 | export import :B; 692 | 693 | ==> 694 | 695 | Program( 696 | ExportDeclaration(export,ModuleDeclaration(module,ModuleName(Identifier))), 697 | ModuleDeclaration(module,ModuleName(Identifier,Identifier)), 698 | ModuleDeclaration(module,Access), 699 | ImportDeclaration(import,ModuleName(Identifier,PartitionName)), 700 | ImportDeclaration(import,HeaderName), 701 | ExportDeclaration(export,FunctionDefinition(PrimitiveType,FunctionDeclarator(Identifier,ParameterList),CompoundStatement)), 702 | ExportDeclaration(export,ImportDeclaration(import,ModuleName(PartitionName)))) 703 | -------------------------------------------------------------------------------- /test/declarations.txt: -------------------------------------------------------------------------------- 1 | # Namespace definitions 2 | 3 | namespace std { 4 | 5 | int x; 6 | 7 | } // namespace std 8 | 9 | ==> 10 | 11 | Program( 12 | NamespaceDefinition(namespace, 13 | Identifier, 14 | CompoundStatement( 15 | Declaration( 16 | PrimitiveType, 17 | Identifier))), 18 | LineComment) 19 | 20 | 21 | # Using declarations 22 | 23 | using a; 24 | using ::b; 25 | using c::d; 26 | using ::e::f::g; 27 | using h = i::j; 28 | using namespace std; 29 | 30 | template 31 | using a = typename b::c; 32 | 33 | ==> 34 | 35 | Program( 36 | UsingDeclaration(using, Identifier), 37 | UsingDeclaration(using, ScopedIdentifier(Identifier)), 38 | UsingDeclaration(using, ScopedIdentifier(NamespaceIdentifier, Identifier)), 39 | UsingDeclaration(using, 40 | ScopedIdentifier( 41 | ScopedNamespaceIdentifier( 42 | ScopedNamespaceIdentifier(NamespaceIdentifier), 43 | NamespaceIdentifier), 44 | Identifier)), 45 | AliasDeclaration(using, 46 | TypeIdentifier, 47 | TypeDescriptor(ScopedTypeIdentifier(NamespaceIdentifier, TypeIdentifier))), 48 | UsingDeclaration(using, namespace, Identifier), 49 | TemplateDeclaration(template, 50 | TemplateParameterList( 51 | TypeParameterDeclaration(typename, TypeIdentifier)), 52 | AliasDeclaration(using, 53 | TypeIdentifier, 54 | TypeDescriptor( 55 | DependentType( 56 | typename, 57 | ScopedTypeIdentifier( 58 | TemplateType(TypeIdentifier, TemplateArgumentList(TypeDescriptor(TypeIdentifier))), 59 | TypeIdentifier)))))) 60 | 61 | 62 | # Reference declarations 63 | 64 | int main() { 65 | T &x = y(); 66 | } 67 | 68 | ==> 69 | 70 | Program( 71 | FunctionDefinition( 72 | PrimitiveType, 73 | FunctionDeclarator(Identifier, ParameterList), 74 | CompoundStatement( 75 | Declaration( 76 | TypeIdentifier, 77 | InitDeclarator( 78 | ReferenceDeclarator(Identifier), 79 | CallExpression( 80 | TemplateFunction( 81 | Identifier, 82 | TemplateArgumentList( 83 | TypeDescriptor(TypeIdentifier, AbstractReferenceDeclarator))), 84 | ArgumentList)))))) 85 | 86 | 87 | # R-value reference declarations 88 | 89 | int main(T &&); 90 | 91 | int main(T &&t) { 92 | const U &&u = v; 93 | } 94 | 95 | ==> 96 | 97 | Program( 98 | Declaration( 99 | PrimitiveType, 100 | FunctionDeclarator( 101 | Identifier, 102 | ParameterList(ParameterDeclaration(TypeIdentifier, AbstractReferenceDeclarator)))), 103 | FunctionDefinition( 104 | PrimitiveType, 105 | FunctionDeclarator( 106 | Identifier, 107 | ParameterList(ParameterDeclaration(TypeIdentifier, ReferenceDeclarator(Identifier)))), 108 | CompoundStatement( 109 | Declaration( 110 | const, 111 | TypeIdentifier, 112 | InitDeclarator(ReferenceDeclarator(Identifier), Identifier))))) 113 | 114 | 115 | # Inline method definitions 116 | 117 | struct S { 118 | int f; 119 | 120 | S() : f(0) {} 121 | 122 | private: 123 | int getF() const { return f; } 124 | }; 125 | 126 | ==> 127 | 128 | Program( 129 | StructSpecifier(struct, TypeIdentifier, FieldDeclarationList( 130 | FieldDeclaration(PrimitiveType, FieldIdentifier), 131 | FunctionDefinition( 132 | FunctionDeclarator(Identifier, ParameterList), 133 | FieldInitializerList(FieldInitializer(FieldIdentifier, ArgumentList(Number))), 134 | CompoundStatement), 135 | AccessSpecifier(Access), 136 | FunctionDefinition( 137 | PrimitiveType, 138 | FunctionDeclarator(FieldIdentifier, ParameterList, const), 139 | CompoundStatement(ReturnStatement(return, Identifier)))))) 140 | 141 | 142 | # Inline method definitions with overrides 143 | 144 | struct B : A { 145 | int foo() override { return 2; } 146 | int pho() final { return 3; } 147 | int bar() const override { return 4; } 148 | int baz() const final { return 5; } 149 | int bag() const final override { return 6; } 150 | int bah() const override final { return 7; } 151 | }; 152 | 153 | ==> 154 | 155 | Program( 156 | StructSpecifier(struct, TypeIdentifier, BaseClassClause(TypeIdentifier), FieldDeclarationList( 157 | FunctionDefinition( 158 | PrimitiveType, 159 | FunctionDeclarator(FieldIdentifier, ParameterList, VirtualSpecifier), 160 | CompoundStatement(ReturnStatement(return, Number))), 161 | FunctionDefinition( 162 | PrimitiveType, 163 | FunctionDeclarator(FieldIdentifier, ParameterList, VirtualSpecifier), 164 | CompoundStatement(ReturnStatement(return, Number))), 165 | FunctionDefinition( 166 | PrimitiveType, 167 | FunctionDeclarator(FieldIdentifier, ParameterList, const, VirtualSpecifier), 168 | CompoundStatement(ReturnStatement(return, Number))), 169 | FunctionDefinition( 170 | PrimitiveType, 171 | FunctionDeclarator(FieldIdentifier, ParameterList, const, VirtualSpecifier), 172 | CompoundStatement(ReturnStatement(return, Number))), 173 | FunctionDefinition( 174 | PrimitiveType, 175 | FunctionDeclarator(FieldIdentifier, ParameterList, const, VirtualSpecifier, VirtualSpecifier), 176 | CompoundStatement(ReturnStatement(return, Number))), 177 | FunctionDefinition( 178 | PrimitiveType, 179 | FunctionDeclarator(FieldIdentifier, ParameterList, const, VirtualSpecifier, VirtualSpecifier), 180 | CompoundStatement(ReturnStatement(return, Number)))))) 181 | 182 | 183 | # Virtual method declarations 184 | 185 | class A { 186 | virtual ~Point(); 187 | void b(); 188 | virtual void foo() {} 189 | virtual void bar(); 190 | }; 191 | 192 | ==> 193 | 194 | Program( 195 | ClassSpecifier(class, 196 | TypeIdentifier, 197 | FieldDeclarationList( 198 | Declaration( 199 | virtual, 200 | FunctionDeclarator(DestructorName, ParameterList)), 201 | FieldDeclaration( 202 | PrimitiveType, 203 | FunctionDeclarator(FieldIdentifier, ParameterList)), 204 | FunctionDefinition( 205 | virtual, 206 | PrimitiveType, 207 | FunctionDeclarator( 208 | FieldIdentifier, 209 | ParameterList), 210 | CompoundStatement), 211 | FieldDeclaration( 212 | virtual, 213 | PrimitiveType, 214 | FunctionDeclarator( 215 | FieldIdentifier, 216 | ParameterList))))) 217 | 218 | 219 | # Constructor and destructor declarations 220 | 221 | class C { 222 | void *data_; 223 | 224 | public: 225 | C(); 226 | C(int, float); 227 | ~C(); 228 | }; 229 | 230 | ==> 231 | 232 | Program( 233 | ClassSpecifier(class, TypeIdentifier, FieldDeclarationList( 234 | FieldDeclaration(PrimitiveType, PointerDeclarator(FieldIdentifier)), 235 | AccessSpecifier(Access), 236 | Declaration(FunctionDeclarator(Identifier, ParameterList)), 237 | Declaration(FunctionDeclarator(Identifier, ParameterList( 238 | ParameterDeclaration(PrimitiveType), 239 | ParameterDeclaration(PrimitiveType)))), 240 | Declaration(FunctionDeclarator(DestructorName, ParameterList))))) 241 | 242 | # Forward class declaration 243 | 244 | class Foo; 245 | 246 | ==> 247 | 248 | Program(ClassSpecifier(class,TypeIdentifier)) 249 | 250 | # Forward function declarations 251 | 252 | void foo(Bar& x, Bar& y) noexcept; 253 | 254 | void Foo(const unsigned char* in_bytes, char* out); 255 | 256 | foo::bar(); 257 | 258 | void foo(::y data, void* arg, void (*r)(void*)); 259 | 260 | ==> 261 | 262 | Program( 263 | Declaration(PrimitiveType,FunctionDeclarator(Identifier,ParameterList( 264 | ParameterDeclaration(TypeIdentifier,ReferenceDeclarator(Identifier)), 265 | ParameterDeclaration(TypeIdentifier,ReferenceDeclarator(Identifier))), Noexcept(noexcept))), 266 | Declaration(PrimitiveType,FunctionDeclarator(Identifier,ParameterList( 267 | ParameterDeclaration(const,SizedTypeSpecifier(TypeSize,PrimitiveType),PointerDeclarator(Identifier)), 268 | ParameterDeclaration(PrimitiveType,PointerDeclarator(Identifier))))), 269 | ExpressionStatement(CallExpression(ScopedIdentifier(NamespaceIdentifier,Identifier),ArgumentList)) 270 | Declaration(PrimitiveType,FunctionDeclarator(Identifier,ParameterList( 271 | ParameterDeclaration(ScopedTypeIdentifier(TypeIdentifier),Identifier), 272 | ParameterDeclaration(PrimitiveType,PointerDeclarator(Identifier)), 273 | ParameterDeclaration(PrimitiveType,FunctionDeclarator(ParenthesizedDeclarator( 274 | PointerDeclarator(Identifier)),ParameterList(ParameterDeclaration(PrimitiveType,AbstractPointerDeclarator)))))))) 275 | 276 | # Classes with inheritance 277 | 278 | class A : public B { 279 | }; 280 | 281 | class C : C::D, public E { 282 | }; 283 | 284 | ==> 285 | 286 | Program( 287 | ClassSpecifier(class, 288 | TypeIdentifier, 289 | BaseClassClause(Access, TypeIdentifier), 290 | FieldDeclarationList), 291 | ClassSpecifier(class, 292 | TypeIdentifier, 293 | BaseClassClause( 294 | ScopedTypeIdentifier(NamespaceIdentifier, TypeIdentifier), 295 | Access, TypeIdentifier), 296 | FieldDeclarationList)) 297 | 298 | 299 | # Classes with final virt specifier 300 | 301 | class A final : public B { 302 | }; 303 | 304 | class C final {}; 305 | 306 | struct D final {}; 307 | 308 | ==> 309 | 310 | Program( 311 | ClassSpecifier(class, 312 | TypeIdentifier, 313 | VirtualSpecifier, 314 | BaseClassClause(Access, TypeIdentifier), 315 | FieldDeclarationList), 316 | ClassSpecifier(class, 317 | TypeIdentifier, 318 | VirtualSpecifier, 319 | FieldDeclarationList), 320 | StructSpecifier(struct, 321 | TypeIdentifier, 322 | VirtualSpecifier, 323 | FieldDeclarationList)) 324 | 325 | 326 | # Nested classes 327 | 328 | class A { 329 | private: 330 | class B : private C, public D { 331 | }; 332 | 333 | B e, f; 334 | }; 335 | 336 | ==> 337 | 338 | Program( 339 | ClassSpecifier(class, TypeIdentifier, FieldDeclarationList( 340 | AccessSpecifier(Access), 341 | FieldDeclaration( 342 | ClassSpecifier(class, TypeIdentifier, BaseClassClause(Access, TypeIdentifier, Access, TypeIdentifier), FieldDeclarationList)), 343 | FieldDeclaration( 344 | TypeIdentifier, FieldIdentifier, FieldIdentifier)))) 345 | 346 | # Macro noise 347 | 348 | class Z { 349 | int num_to_block_ GUARDED_BY("foo" ++ lock_); 350 | 351 | MOCK_METHOD3(DoFoo, bool(const ns::Something&, 352 | const std::vector&, const string)); 353 | }; 354 | SOME_OTHER_MACRO(2.44e3); 355 | int z MACRO() = 0; 356 | 357 | ==> 358 | 359 | Program( 360 | ClassSpecifier(class,TypeIdentifier,FieldDeclarationList( 361 | FieldDeclaration(PrimitiveType,FieldIdentifier(Macro(MacroName,ArgumentList(BinaryExpression(String,UpdateOp,Identifier))))), 362 | Declaration(FunctionDeclarator(Identifier,ParameterList( 363 | ParameterDeclaration(TypeIdentifier), 364 | ParameterDeclaration(PrimitiveType,AbstractFunctionDeclarator(ParameterList( 365 | ParameterDeclaration(const,ScopedTypeIdentifier(NamespaceIdentifier,TypeIdentifier),AbstractReferenceDeclarator), 366 | ParameterDeclaration(const,TemplateType( 367 | ScopedTypeIdentifier(NamespaceIdentifier,TypeIdentifier), 368 | TemplateArgumentList(TypeDescriptor(PrimitiveType))),AbstractReferenceDeclarator), 369 | ParameterDeclaration(const,TypeIdentifier))))))))), 370 | ExpressionStatement(CallExpression(Identifier,ArgumentList(Number))), 371 | Declaration(PrimitiveType,InitDeclarator(Identifier(Macro(MacroName,ArgumentList)),Number))) 372 | 373 | # Friend declarations 374 | 375 | struct C { 376 | friend class D; 377 | friend D; 378 | friend int f(C &); 379 | }; 380 | 381 | ==> 382 | 383 | Program( 384 | StructSpecifier(struct, TypeIdentifier, FieldDeclarationList( 385 | FriendDeclaration(friend, class, TypeIdentifier), 386 | FriendDeclaration(friend, TypeIdentifier), 387 | FriendDeclaration(friend, Declaration(PrimitiveType, FunctionDeclarator( 388 | Identifier, 389 | ParameterList(ParameterDeclaration(TypeIdentifier, AbstractReferenceDeclarator)))))))) 390 | 391 | 392 | # Default member initializers 393 | 394 | struct A { 395 | bool a = 1; 396 | vector b = {c, d, e}; 397 | F g {h}; 398 | }; 399 | 400 | ==> 401 | 402 | Program( 403 | StructSpecifier(struct, TypeIdentifier, FieldDeclarationList( 404 | FieldDeclaration( 405 | PrimitiveType, 406 | FieldIdentifier, 407 | Number), 408 | FieldDeclaration( 409 | TemplateType(TypeIdentifier, TemplateArgumentList(TypeDescriptor(PrimitiveType))), 410 | FieldIdentifier, 411 | InitializerList(Identifier, Identifier, Identifier)), 412 | FieldDeclaration( 413 | TypeIdentifier, 414 | FieldIdentifier, 415 | InitializerList(Identifier))))) 416 | 417 | 418 | # Function parameters with default values 419 | 420 | int foo(bool x = 5) {} 421 | 422 | ==> 423 | 424 | Program( 425 | FunctionDefinition( 426 | PrimitiveType, 427 | FunctionDeclarator( 428 | Identifier, 429 | ParameterList( 430 | OptionalParameterDeclaration(PrimitiveType, Identifier, Number))), 431 | CompoundStatement)) 432 | 433 | 434 | # Declarations with attributes 435 | 436 | int f([[a::b(c), d]] int x) {} 437 | 438 | [[gnu::always_inline]] [[gnu::hot]] [[gnu::const]] [[nodiscard]] 439 | inline int g(); 440 | 441 | [[ foo::target(gpu, [cpu]) ]] 442 | class Foo; 443 | 444 | ==> 445 | 446 | Program( 447 | FunctionDefinition( 448 | PrimitiveType, 449 | FunctionDeclarator( 450 | Identifier, 451 | ParameterList( 452 | ParameterDeclaration( 453 | Attribute(AttributeName(Identifier,Identifier),AttributeArgs(Identifier),AttributeName(Identifier)) 454 | PrimitiveType, 455 | Identifier))), 456 | CompoundStatement), 457 | Declaration( 458 | Attribute(AttributeName(Identifier,Identifier)) 459 | Attribute(AttributeName(Identifier,Identifier)) 460 | Attribute(AttributeName(Identifier,Identifier)) 461 | Attribute(AttributeName(Identifier)) 462 | inline, 463 | PrimitiveType, 464 | FunctionDeclarator(Identifier, ParameterList)), 465 | Attribute(AttributeName(Identifier,Identifier),AttributeArgs(Identifier,Identifier)), 466 | ClassSpecifier(class,TypeIdentifier)) 467 | 468 | # Operator overload declarations 469 | 470 | ostream &operator<<(ostream &, const A &a); 471 | 472 | bool A::operator!=(const A &other) const; 473 | 474 | ==> 475 | 476 | Program( 477 | Declaration( 478 | TypeIdentifier, 479 | ReferenceDeclarator( 480 | FunctionDeclarator( 481 | OperatorName(operator, BitOp), 482 | ParameterList( 483 | ParameterDeclaration(TypeIdentifier, AbstractReferenceDeclarator), 484 | ParameterDeclaration(const, TypeIdentifier, ReferenceDeclarator(Identifier)))))), 485 | Declaration( 486 | PrimitiveType, 487 | FunctionDeclarator( 488 | ScopedIdentifier(NamespaceIdentifier, OperatorName(operator, CompareOp)), 489 | ParameterList( 490 | ParameterDeclaration(const, TypeIdentifier, ReferenceDeclarator(Identifier))), 491 | const))) 492 | 493 | 494 | # Template declarations 495 | 496 | template 497 | void foo(T &t); 498 | 499 | template 500 | int bar(T &t) { return u; } 501 | 502 | template 503 | class Foo {}; 504 | 505 | template 506 | Foo::Foo(int mem) : mem_(mem) {} 507 | 508 | template 509 | template 510 | void A::foo(U&) {} 511 | 512 | ==> 513 | 514 | Program( 515 | TemplateDeclaration(template, 516 | TemplateParameterList( 517 | TypeParameterDeclaration(typename, TypeIdentifier)), 518 | Declaration( 519 | PrimitiveType, 520 | FunctionDeclarator( 521 | Identifier, 522 | ParameterList( 523 | ParameterDeclaration(TypeIdentifier, ReferenceDeclarator(Identifier)))))), 524 | TemplateDeclaration(template, 525 | TemplateParameterList( 526 | TypeParameterDeclaration(typename, TypeIdentifier), 527 | ParameterDeclaration(PrimitiveType, Identifier)), 528 | FunctionDefinition( 529 | PrimitiveType, 530 | FunctionDeclarator( 531 | Identifier, 532 | ParameterList(ParameterDeclaration(TypeIdentifier, ReferenceDeclarator(Identifier)))), 533 | CompoundStatement(ReturnStatement(return, Identifier)))), 534 | TemplateDeclaration(template, 535 | TemplateParameterList( 536 | TypeParameterDeclaration(typename, TypeIdentifier)), 537 | ClassSpecifier(class, TypeIdentifier, FieldDeclarationList)), 538 | TemplateDeclaration(template, 539 | TemplateParameterList( 540 | TypeParameterDeclaration(typename, TypeIdentifier)), 541 | FunctionDefinition( 542 | FunctionDeclarator( 543 | ScopedIdentifier( 544 | TemplateType( 545 | TypeIdentifier, 546 | TemplateArgumentList(TypeDescriptor(TypeIdentifier))), 547 | Identifier), 548 | ParameterList( 549 | ParameterDeclaration(PrimitiveType, Identifier))), 550 | FieldInitializerList( 551 | FieldInitializer( 552 | FieldIdentifier, 553 | ArgumentList(Identifier))), 554 | CompoundStatement)), 555 | TemplateDeclaration(template, 556 | TemplateParameterList( 557 | TypeParameterDeclaration(typename, TypeIdentifier)), 558 | TemplateDeclaration(template, 559 | TemplateParameterList( 560 | TypeParameterDeclaration(typename, TypeIdentifier)), 561 | FunctionDefinition( 562 | PrimitiveType, 563 | FunctionDeclarator( 564 | ScopedIdentifier( 565 | TemplateType( 566 | TypeIdentifier, 567 | TemplateArgumentList(TypeDescriptor(TypeIdentifier))), 568 | Identifier), 569 | ParameterList( 570 | ParameterDeclaration( 571 | TypeIdentifier, 572 | AbstractReferenceDeclarator))), 573 | CompoundStatement)))) 574 | 575 | 576 | # Template template declarations 577 | 578 | template