1# Antlr4使用教程 2 3## 一、Antlr4工具介绍 4 5Antlr4(Another Tool for Language Recognition)是一款基于Java开发的开源的语法分析器生成工具,能够根据语法规则文件生成对应的语法分析器,广泛应用于DSL构建,语言词法语法解析等领域。 6 7## 二、安装和配置(windows10) 8 9ANTLR依赖Java环境,所以必须要安装JDK 1.6+,并设置好环境变量。 10 111. 下载安装 12 13可通过以下方式安装,两者选其一就好: 14 15官网下载:https://www.antlr.org/download.html 16命令行安装:curl -O https://www.antlr.org/download/antlr-4.13.2-complete.jar 17 182. 测试下ANTLR工具是否工作正常: 19 20 ``` 21 java -jar antlr-4.13.2-complete.jar 22 ``` 23 24 将工具存放在特定文件夹中方便日后寻找,例如C:\Users\zxj\TOOLS\ANTLR4,在该文件夹下新建bat文件夹,新增两文件antlr4.bat和grun.bat,内容分别如下: 25 26 ``` 27 java org.antlr.v4.Tool %* //antlr4.bat 28 ``` 29 30 ``` 31 java org.antlr.v4.gui.TestRig %* //grun.bat 32 ``` 33 343. 配置环境变量 35 36 1)修改CLASSPATH 37 打开环境变量,选择“系统变量”中的“CLASSPATH”,双击打开,如果系统变量中没有“CLASSPATH”,需新建“CLASSPATH”,在变量值中做如下添加: 38  39  40 ps:需要有一个 点(.)。 41 42 2)修改Path 43 找到系统变量中的Path进行修改,双击打开,点击“新建”,添加C:\Users\zxj\TOOLS\ANTLR4\bat\到末尾,点击“确定”(C:\Users\zxj\TOOLS\ANTLR4为前面提到的antlr-4.13.2-complete.jar存放的文件夹)。 44 45路径添加完毕!重启电脑让路径生效。 46 473. 测试下是否安装成功:在cmd中输入antlr4,回车,观察输出是否如下图。 48  49 在cmd中输入grun,回车,观察输出是否如下图,如果正常的话,那到这里就说明Antlr4的安装和配置已经成功! 50  51 52## 三、语法文件编写 53 54语法文件整体结构如下: 55 56``` 57/** Optional javadoc style comment */ 58 59grammar Name; 60 61options {...} 62 63import ... ; 64 65 66 67tokens {...} 68 69channels {...} // lexer only 70 71@actionName {...} 72 73 74 75rule1 // parser and lexer rules, possibly intermingled 76 77... 78 79ruleN 80``` 81 82- **grammar Name**是词法跟语法都在同一个文件声明的写法,称之为**combined**。若要分开,可以使用lexer grammar Name和parser grammar Name。需要注意的是,Name要和文件名保持一致。 83 84- **options**可以是如下四个选项: 85 86 superClass:指定生成xxxLexer.java、xxxParser.java的父类。 87 language:生成目标语言,如java。 88 tokenVocab:导入外部词法文件(用于拆分大型语法)。 89 TokenLabelType:默认的是antlr的Token类型,这里可以使用自定义的token类,如MyToken。需要配合TokenFactory使用 90 91- **import**导入别的语法文件的规则,lexer grammer只能导入lexer grammer,parser grammer只能导入parser grammer,混合语法可以同时导入以上两者。 92 93- **tokens**定义虚拟Token,用于在语法树上标记节点,不用于匹配具体字符。 94 95- **actionName** 可以是如下内容 96 97 @header:在生成的代码文件头部插入内容(如包声明、导入语句)。 98 @member:在生成的分析器中添加成员变量或添加方法。 99 100 如果要指定在lexer或者parser中,可以使用 @lexer::member、@parser::member。 101 102- **channels**将某些词法规则分配到特定通道,如隐藏注释但不丢弃 103 104- **rule** 词法规则和语法规则 105 106 *lexer示例* 107 108 ``` 109 lexer grammar HelloLexer; 110 HI : 'H' 'i' 111 ID : [a-z]+; 112 WS : [\t\n\r\s]+ -> skip; 113 ``` 114 115 *parser示例* 116 117 ``` 118 parser grammar HelloParser; 119 options { 120 language=Java; 121 tokenVocab=HelloLexer; 122 } 123 124 @header { 125 package com.laudandjolynn.antlr; 126 import java.util.Set; 127 import java.util.HashSet; 128 } 129 @member { 130 private int count; 131 public int getCount() { 132 return count; 133 } 134 } 135 start : HI ID; 136 ``` 137 138- 词法规则以大写字母开头,定义了如何将输入文本分解成词法单元(tokens)。词法规则使用正则表达式来定义匹配模式。 139 140- 语法规则以小写字母开头,规则通过组合词法单元和别的语法规则来定义语法结构,例如 141 142``` 143expr : expr op=('*'|'/') expr # MulDiv 144 | expr op=('+'|'-') expr # AddSub 145 | INT # int 146 | '(' expr ')' # parens 147 ; 148``` 149 1501. 常见的语言模式 151 152 1)序列模式 153 154 它是一个任意长的,可能为空的序列,其中的元素可以是词法符号或者子规则。比如一个协议语言POP,由关键字、整数和换行组成,如下: 155 156 ``` 157 retr : 'RETR' INT '\n' 158 ``` 159 160 任意长度序列可以用 `+` 字符。`(INT)+` 或者 `INT+`。 161 162 2)选择模式(多个备选分支) 163 164 使用符号 `|` 作为“或者”来表达编程语言中的选择模式。备选分支或者可生成的结果。 165 166 ``` 167 type : 'float' | 'int' | 'void' 168 ``` 169 170 3)词法符号依赖 171 172 依赖符号的语法,比如数组的括号。表达对符号的依赖的方法。 173 174 ``` 175 vector : '[' INT+ ']' ; // [1], [1 2], [1 2 3], ... 176 ``` 177 178 以方法定义为例,它的语法表示如下: 179 180 ``` 181 functionDecl 182 : type ID '{' formalParameters? '}' 183 ; 184 formalParameters 185 : formalParameter (',' formalParameter)* 186 ; 187 formalParameter 188 : type ID 189 ``` 190 191 4)嵌套结构 192 193 自己引用自己。如果一条规则定义中的伪代码引用了它自身,就需要一条递归规则(自引用规则)。例如: 194 195 ``` 196 expr: ID '[' expr ']' //a[1],a[b[1]],a[(2*b[1])] 197 | '(' expr ')' //(1),(a[1]),(((1))),(2*a[1]) 198 | INT 199 ; 200 ``` 201 202“|”、“?“等记号在语法文件中比较常见,其功能如下方表格: 203 204| 用法 | 描述 | 205| --------------------- | --------------------------------- | 206| x | 匹配词法符号、规则引用或者子规则x | 207| x y ... z | 匹配一列规则元素 | 208| (... \| ... \| ...) | 一个具有多个备选分支的子规则 | 209| x? | 匹配x或者忽略它 | 210| x* | 匹配x零次或多次 | 211| x+ | 匹配x一次或多次 | 212| r: ...; | 定义规则r | 213| r: ... \| ... \| .... | 定义具有多个备选分支的规则r | 214 2152. 左递归和优先级:直接或间接调用在选项左边缘的自身的规则,写在前面的语法拥有较高的优先级。ANTLR可以处理直接左递归,不能处理间接左递归。如果遇到从右向左结合的,需要使用assoc手工指定结合性: 216 217``` 218expr : <assoc=right> expr '^' expr 219 | INT 220 ; 221``` 222 2233. 识别词法 224 225- 匹配标识符 226 227 ``` 228 ID : [a-zA-z]+ ;//匹配一个或多个大小写字母 229 ``` 230 231 或者 232 233 ``` 234 ID : ('a'..'z'|'A'..'Z')+ ; 235 ``` 236 237 ID规则可能和别的规则冲突,譬如别的关键字enum 238 239- 匹配数字 240 241 i)整数 242 243 ``` 244 INT : [0-9]+ ; 245 ``` 246 247 或者 248 249 ``` 250 INT : '0'..'9'+ ; 251 ``` 252 253 ii)浮点数 254 255 ``` 256 FLOAT : DIGIT+ '.' DIGIT* // 1. 3.14 257 | '.' DIGIT+ // .1 .1415 258 ; 259 fragment 260 DIGIT : [0-9] ; // 单个数字 261 ``` 262 263 fragment:词法片段,构成词法的元素,不是一个词法规则。在词法规则中可引用一个或多个词法片段。 264 265- 字符串 266 267 ``` 268 STRING : '"' .*? '"' ; 269 ``` 270 271 `.` 匹配任意单个字符,`.*` 匹配零个或多个,`?` 标记表示使用非贪婪匹配子规则(nongreedy subrule)。 272 273 ``` 274 //转义字符 275 STRING : '"' (ESC|.)*? '"' ; 276 fragment 277 ESC : '\\"' | '\\\\' ; // 转义 \" 和 \\ 278 ``` 279 280- 注释和空白字符 281 282 C 中的单行和多行注释: 283 284 ``` 285 LINE_COMINT : '//' .*? '\r'? '\n' -> skip ; // 消费掉双斜杠后面的一切字符,直到遇到换行符 286 ``` 287 288 空白字符: 289 290 ``` 291 WS : [ \t\r\n]+ -> skip ; 292 ``` 293 294## 四、示例 295 2961. 新建一个文件夹,然后在文件夹中新建一个语法文件Hello.g4,文件内容如下: 297 298 ``` 299 grammar Hello; // 定义文法的名字 300 301 r : 'hello' ID ; // 匹配关键字hello和标志符 302 ID : [a-z]+ ; // 标志符由小写字母组成 303 WS : [ \t\r\n]+ -> skip ; // 跳过空格、制表符、回车符和换行符 304 ``` 305 3062. 在语法文件所在目录下打开命令行窗口,输入命令 307 308 ``` 309 antlr4 Hello.g4 310 ``` 311 312 运行ANTLR命令编译该语法文件生成词法分析器和语法分析器如下: 313 314  315 3163. 编译生成文件的java代码 317 318 ``` 319 javac *.java 320 ``` 321 3224. 用ANTLR运行库提供的语法调试工具TestRig来对语法文件进行测试,测试命令如下 323 324 ``` 325 grun GrammerName startRuleName [options] 326 ``` 327 328 其中GrammerName是指语法文件名称(不含后缀),startRuleName是指语法文件中起始规则的名称,options是指TestRig参数,常用的参数如下: 329 330 | 选项 | 功能说明 | 示例用法 | 331 | --------- | -------------------------- | ---------------------- | 332 | `-tokens` | 打印词法符号流 | `grun Hello r -tokens` | 333 | `-tree` | 以LISP格式打印语法树 | `grun Hello r -tree` | 334 | `-gui` | 以可视化方式显示语法分析树 | `grun Hello r -gui` | 335 336 在语法文件所在目录的命令行窗口输入 `grun Hello r -tokens`,按回车,然后按Ctrl+Z,再次回车,会得到 337 338  339 340 在语法文件所在目录的命令行窗口输入 `grun Hello r -tree`,按回车,然后按Ctrl+Z,再次回车,会得到 341 342  343 344 在语法文件所在目录的命令行窗口输入 `grun Hello r -gui`,按回车,然后按Ctrl+Z,再次回车,会得到 345 346  347 348 还有一些别的TestRig参数如下: 349 350 | 选项 | 功能说明 | 示例用法 | 351 | ------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | 352 | `-ps file.ts` | 以PostScript格式生成可视化语法分析树并存储在相应文件中 | `run Hello r -ps file.ps` | 353 | `-encoding encodingname` | 指定测试输入文件的编码,若当前区域设定无法正确读取输入时使用 | `grun Hello r -encoding UTF-8` | 354 | `-trace` | 打印规则的名字以及进入和离开该规则时的词法符号,用于调试 | `grun Hello r -trace` | 355 | `-diagnostics` | 开启解析过程中的调试信息输出,通常在输入文本有歧义等特殊情况下使用 | `grun Hello r -diagnostics` | 356 | `-SLL` | 使用更快但受限的解析策略(默认策略为 `LL(*)`) | `grun Hello r -SLL` | 357 | `input-filename(s)` | 输入测试文本文件名,从控制台输入时忽略此参数 | `grun Hello r -gui test.txt`(test.txt是同级目录下的测试文本文件) | 358 359## 五、进阶版示例 360 361这是一个生成TypeScript解析器来解析CPP14代码的示例。 362 3631. 新建一个文件夹,在文件夹中新建一语法文件CPP14.g4,文件内容如下: 364 365 ``` 366 grammar CPP14; 367 368 options { 369 superClass = CPP14ParserBase; 370 } 371 372 /*Basic concepts*/ 373 translationUnit 374 : declarationseq? EOF 375 ; 376 377 /*Expressions*/ 378 primaryExpression 379 : literal+ 380 | This 381 | LeftParen expression RightParen 382 | idExpression 383 | lambdaExpression 384 ; 385 386 idExpression 387 : unqualifiedId 388 | qualifiedId 389 ; 390 391 unqualifiedId 392 : Identifier 393 | operatorFunctionId 394 | conversionFunctionId 395 | literalOperatorId 396 | Tilde (className | decltypeSpecifier) 397 | templateId 398 ; 399 400 qualifiedId 401 : nestedNameSpecifier Template? unqualifiedId 402 ; 403 404 nestedNameSpecifier 405 : (theTypeName | namespaceName | decltypeSpecifier)? Doublecolon 406 | nestedNameSpecifier ( Identifier | Template? simpleTemplateId) Doublecolon 407 ; 408 409 lambdaExpression 410 : lambdaIntroducer lambdaDeclarator? compoundStatement 411 ; 412 413 lambdaIntroducer 414 : LeftBracket lambdaCapture? RightBracket 415 ; 416 417 lambdaCapture 418 : captureList 419 | captureDefault (Comma captureList)? 420 ; 421 422 captureDefault 423 : And 424 | Assign 425 ; 426 427 captureList 428 : capture (Comma capture)* Ellipsis? 429 ; 430 431 capture 432 : simpleCapture 433 | initcapture 434 ; 435 436 simpleCapture 437 : And? Identifier 438 | This 439 ; 440 441 initcapture 442 : And? Identifier initializer 443 ; 444 445 lambdaDeclarator 446 : LeftParen parameterDeclarationClause? RightParen Mutable? exceptionSpecification? attributeSpecifierSeq? trailingReturnType? 447 ; 448 449 postfixExpression 450 : primaryExpression 451 | postfixExpression LeftBracket (expression | bracedInitList) RightBracket 452 | postfixExpression LeftParen expressionList? RightParen 453 | (simpleTypeSpecifier | typeNameSpecifier) ( 454 LeftParen expressionList? RightParen 455 | bracedInitList 456 ) 457 | postfixExpression (Dot | Arrow) (Template? idExpression | pseudoDestructorName) 458 | postfixExpression (PlusPlus | MinusMinus) 459 | (Dynamic_cast | Static_cast | Reinterpret_cast | Const_cast) Less theTypeId Greater LeftParen expression RightParen 460 | typeIdOfTheTypeId LeftParen (expression | theTypeId) RightParen 461 ; 462 463 /* 464 add a middle layer to eliminate duplicated function declarations 465 */ 466 467 typeIdOfTheTypeId 468 : Typeid_ 469 ; 470 471 expressionList 472 : initializerList 473 ; 474 475 pseudoDestructorName 476 : nestedNameSpecifier? (theTypeName Doublecolon)? Tilde theTypeName 477 | nestedNameSpecifier Template simpleTemplateId Doublecolon Tilde theTypeName 478 | Tilde decltypeSpecifier 479 ; 480 481 unaryExpression 482 : postfixExpression 483 | (PlusPlus | MinusMinus | unaryOperator | Sizeof) unaryExpression 484 | Sizeof (LeftParen theTypeId RightParen | Ellipsis LeftParen Identifier RightParen) 485 | Alignof LeftParen theTypeId RightParen 486 | noExceptExpression 487 | newExpression_ 488 | deleteExpression 489 ; 490 491 unaryOperator 492 : Or 493 | Star 494 | And 495 | Plus 496 | Tilde 497 | Minus 498 | Not 499 ; 500 501 newExpression_ 502 : Doublecolon? New newPlacement? (newTypeId | LeftParen theTypeId RightParen) newInitializer_? 503 ; 504 505 newPlacement 506 : LeftParen expressionList RightParen 507 ; 508 509 newTypeId 510 : typeSpecifierSeq newDeclarator_? 511 ; 512 513 newDeclarator_ 514 : pointerOperator newDeclarator_? 515 | noPointerNewDeclarator 516 ; 517 518 noPointerNewDeclarator 519 : LeftBracket expression RightBracket attributeSpecifierSeq? 520 | noPointerNewDeclarator LeftBracket constantExpression RightBracket attributeSpecifierSeq? 521 ; 522 523 newInitializer_ 524 : LeftParen expressionList? RightParen 525 | bracedInitList 526 ; 527 528 deleteExpression 529 : Doublecolon? Delete (LeftBracket RightBracket)? castExpression 530 ; 531 532 noExceptExpression 533 : Noexcept LeftParen expression RightParen 534 ; 535 536 castExpression 537 : unaryExpression 538 | LeftParen theTypeId RightParen castExpression 539 ; 540 541 pointerMemberExpression 542 : castExpression ((DotStar | ArrowStar) castExpression)* 543 ; 544 545 multiplicativeExpression 546 : pointerMemberExpression ((Star | Div | Mod) pointerMemberExpression)* 547 ; 548 549 additiveExpression 550 : multiplicativeExpression ((Plus | Minus) multiplicativeExpression)* 551 ; 552 553 shiftExpression 554 : additiveExpression (shiftOperator additiveExpression)* 555 ; 556 557 shiftOperator 558 : Greater Greater 559 | Less Less 560 ; 561 562 relationalExpression 563 : shiftExpression ((Less | Greater | LessEqual | GreaterEqual) shiftExpression)* 564 ; 565 566 equalityExpression 567 : relationalExpression ((Equal | NotEqual) relationalExpression)* 568 ; 569 570 andExpression 571 : equalityExpression (And equalityExpression)* 572 ; 573 574 exclusiveOrExpression 575 : andExpression (Caret andExpression)* 576 ; 577 578 inclusiveOrExpression 579 : exclusiveOrExpression (Or exclusiveOrExpression)* 580 ; 581 582 logicalAndExpression 583 : inclusiveOrExpression (AndAnd inclusiveOrExpression)* 584 ; 585 586 logicalOrExpression 587 : logicalAndExpression (OrOr logicalAndExpression)* 588 ; 589 590 conditionalExpression 591 : logicalOrExpression (Question expression Colon assignmentExpression)? 592 ; 593 594 assignmentExpression 595 : conditionalExpression 596 | logicalOrExpression assignmentOperator initializerClause 597 | throwExpression 598 ; 599 600 assignmentOperator 601 : Assign 602 | StarAssign 603 | DivAssign 604 | ModAssign 605 | PlusAssign 606 | MinusAssign 607 | RightShiftAssign 608 | LeftShiftAssign 609 | AndAssign 610 | XorAssign 611 | OrAssign 612 ; 613 614 expression 615 : assignmentExpression (Comma assignmentExpression)* 616 ; 617 618 constantExpression 619 : conditionalExpression 620 ; 621 622 /*Statements*/ 623 624 statement 625 : labeledStatement 626 | declarationStatement 627 | attributeSpecifierSeq? ( 628 expressionStatement 629 | compoundStatement 630 | selectionStatement 631 | iterationStatement 632 | jumpStatement 633 | tryBlock 634 ) 635 ; 636 637 labeledStatement 638 : attributeSpecifierSeq? (Identifier | Case constantExpression | Default) Colon statement 639 ; 640 641 expressionStatement 642 : expression? Semi 643 ; 644 645 compoundStatement 646 : LeftBrace statementSeq? RightBrace 647 ; 648 649 statementSeq 650 : statement+ 651 ; 652 653 selectionStatement 654 : If LeftParen condition RightParen statement (Else statement)? 655 | Switch LeftParen condition RightParen statement 656 ; 657 658 condition 659 : expression 660 | attributeSpecifierSeq? declSpecifierSeq declarator ( 661 Assign initializerClause 662 | bracedInitList 663 ) 664 ; 665 666 iterationStatement 667 : While LeftParen condition RightParen statement 668 | Do statement While LeftParen expression RightParen Semi 669 | For LeftParen ( 670 forInitStatement condition? Semi expression? 671 | forRangeDeclaration Colon forRangeInitializer 672 ) RightParen statement 673 ; 674 675 forInitStatement 676 : expressionStatement 677 | simpleDeclaration 678 ; 679 680 forRangeDeclaration 681 : attributeSpecifierSeq? declSpecifierSeq declarator 682 ; 683 684 forRangeInitializer 685 : expression 686 | bracedInitList 687 ; 688 689 jumpStatement 690 : (Break | Continue | Return (expression | bracedInitList)? | Goto Identifier) Semi 691 ; 692 693 declarationStatement 694 : blockDeclaration 695 ; 696 697 /*Declarations*/ 698 699 declarationseq 700 : declaration+ 701 ; 702 703 declaration 704 : blockDeclaration 705 | functionDefinition 706 | templateDeclaration 707 | explicitInstantiation 708 | explicitSpecialization 709 | linkageSpecification 710 | namespaceDefinition 711 | emptyDeclaration_ 712 | attributeDeclaration 713 ; 714 715 blockDeclaration 716 : simpleDeclaration 717 | asmDefinition 718 | namespaceAliasDefinition 719 | usingDeclaration 720 | usingDirective 721 | staticAssertDeclaration 722 | aliasDeclaration 723 | opaqueEnumDeclaration 724 ; 725 726 aliasDeclaration 727 : Using Identifier attributeSpecifierSeq? Assign theTypeId Semi 728 ; 729 730 simpleDeclaration 731 : declSpecifierSeq? initDeclaratorList? Semi 732 | attributeSpecifierSeq declSpecifierSeq? initDeclaratorList Semi 733 ; 734 735 staticAssertDeclaration 736 : Static_assert LeftParen constantExpression Comma StringLiteral RightParen Semi 737 ; 738 739 emptyDeclaration_ 740 : Semi 741 ; 742 743 attributeDeclaration 744 : attributeSpecifierSeq Semi 745 ; 746 747 declSpecifier 748 : storageClassSpecifier 749 | typeSpecifier 750 | functionSpecifier 751 | Friend 752 | Typedef 753 | Constexpr 754 ; 755 756 declSpecifierSeq 757 : declSpecifier+? attributeSpecifierSeq? 758 ; 759 760 storageClassSpecifier 761 : Register 762 | Static 763 | Thread_local 764 | Extern 765 | Mutable 766 ; 767 768 functionSpecifier 769 : Inline 770 | Virtual 771 | Explicit 772 ; 773 774 typedefName 775 : Identifier 776 ; 777 778 typeSpecifier 779 : trailingTypeSpecifier 780 | classSpecifier 781 | enumSpecifier 782 ; 783 784 trailingTypeSpecifier 785 : simpleTypeSpecifier 786 | elaboratedTypeSpecifier 787 | typeNameSpecifier 788 | cvQualifier 789 ; 790 791 typeSpecifierSeq 792 : typeSpecifier+ attributeSpecifierSeq? 793 ; 794 795 trailingTypeSpecifierSeq 796 : trailingTypeSpecifier+ attributeSpecifierSeq? 797 ; 798 799 simpleTypeLengthModifier 800 : Short 801 | Long 802 ; 803 804 simpleTypeSignednessModifier 805 : Unsigned 806 | Signed 807 ; 808 809 simpleTypeSpecifier 810 : nestedNameSpecifier? theTypeName 811 | nestedNameSpecifier Template simpleTemplateId 812 | Char 813 | Char16 814 | Char32 815 | Wchar 816 | Bool 817 | Short 818 | Int 819 | Long 820 | Float 821 | Signed 822 | Unsigned 823 | Float 824 | Double 825 | Void 826 | Auto 827 | decltypeSpecifier 828 ; 829 830 theTypeName 831 : className 832 | enumName 833 | typedefName 834 | simpleTemplateId 835 ; 836 837 decltypeSpecifier 838 : Decltype LeftParen (expression | Auto) RightParen 839 ; 840 841 elaboratedTypeSpecifier 842 : classKey ( 843 attributeSpecifierSeq? nestedNameSpecifier? Identifier 844 | simpleTemplateId 845 | nestedNameSpecifier Template? simpleTemplateId 846 ) 847 | Enum nestedNameSpecifier? Identifier 848 ; 849 850 enumName 851 : Identifier 852 ; 853 854 enumSpecifier 855 : enumHead LeftBrace (enumeratorList Comma?)? RightBrace 856 ; 857 858 enumHead 859 : enumkey attributeSpecifierSeq? (nestedNameSpecifier? Identifier)? enumbase? 860 ; 861 862 opaqueEnumDeclaration 863 : enumkey attributeSpecifierSeq? Identifier enumbase? Semi 864 ; 865 866 enumkey 867 : Enum (Class | Struct)? 868 ; 869 870 enumbase 871 : Colon typeSpecifierSeq 872 ; 873 874 enumeratorList 875 : enumeratorDefinition (Comma enumeratorDefinition)* 876 ; 877 878 enumeratorDefinition 879 : enumerator (Assign constantExpression)? 880 ; 881 882 enumerator 883 : Identifier 884 ; 885 886 namespaceName 887 : originalNamespaceName 888 | namespaceAlias 889 ; 890 891 originalNamespaceName 892 : Identifier 893 ; 894 895 namespaceDefinition 896 : Inline? Namespace (Identifier | originalNamespaceName)? LeftBrace namespaceBody = declarationseq? RightBrace 897 ; 898 899 namespaceAlias 900 : Identifier 901 ; 902 903 namespaceAliasDefinition 904 : Namespace Identifier Assign qualifiednamespacespecifier Semi 905 ; 906 907 qualifiednamespacespecifier 908 : nestedNameSpecifier? namespaceName 909 ; 910 911 usingDeclaration 912 : Using (Typename_? nestedNameSpecifier | Doublecolon) unqualifiedId Semi 913 ; 914 915 usingDirective 916 : attributeSpecifierSeq? Using Namespace nestedNameSpecifier? namespaceName Semi 917 ; 918 919 asmDefinition 920 : Asm LeftParen StringLiteral RightParen Semi 921 ; 922 923 linkageSpecification 924 : Extern StringLiteral (LeftBrace declarationseq? RightBrace | declaration) 925 ; 926 927 attributeSpecifierSeq 928 : attributeSpecifier+ 929 ; 930 931 attributeSpecifier 932 : LeftBracket LeftBracket attributeList? RightBracket RightBracket 933 | alignmentspecifier 934 ; 935 936 alignmentspecifier 937 : Alignas LeftParen (theTypeId | constantExpression) Ellipsis? RightParen 938 ; 939 940 attributeList 941 : attribute (Comma attribute)* Ellipsis? 942 ; 943 944 attribute 945 : (attributeNamespace Doublecolon)? Identifier attributeArgumentClause? 946 ; 947 948 attributeNamespace 949 : Identifier 950 ; 951 952 attributeArgumentClause 953 : LeftParen balancedTokenSeq? RightParen 954 ; 955 956 balancedTokenSeq 957 : balancedtoken+ 958 ; 959 960 balancedtoken 961 : LeftParen balancedTokenSeq RightParen 962 | LeftBracket balancedTokenSeq RightBracket 963 | LeftBrace balancedTokenSeq RightBrace 964 | ~(LeftParen | RightParen | LeftBrace | RightBrace | LeftBracket | RightBracket)+ 965 ; 966 967 /*Declarators*/ 968 969 initDeclaratorList 970 : initDeclarator (Comma initDeclarator)* 971 ; 972 973 initDeclarator 974 : declarator initializer? 975 ; 976 977 declarator 978 : pointerDeclarator 979 | noPointerDeclarator parametersAndQualifiers trailingReturnType 980 ; 981 982 pointerDeclarator 983 : (pointerOperator Const?)* noPointerDeclarator 984 ; 985 986 noPointerDeclarator 987 : declaratorid attributeSpecifierSeq? 988 | noPointerDeclarator ( 989 parametersAndQualifiers 990 | LeftBracket constantExpression? RightBracket attributeSpecifierSeq? 991 ) 992 | LeftParen pointerDeclarator RightParen 993 ; 994 995 parametersAndQualifiers 996 : LeftParen parameterDeclarationClause? RightParen cvqualifierseq? refqualifier? exceptionSpecification? attributeSpecifierSeq? 997 ; 998 999 trailingReturnType 1000 : Arrow trailingTypeSpecifierSeq abstractDeclarator? 1001 ; 1002 1003 pointerOperator 1004 : (And | AndAnd) attributeSpecifierSeq? 1005 | nestedNameSpecifier? Star attributeSpecifierSeq? cvqualifierseq? 1006 ; 1007 1008 cvqualifierseq 1009 : cvQualifier+ 1010 ; 1011 1012 cvQualifier 1013 : Const 1014 | Volatile 1015 ; 1016 1017 refqualifier 1018 : And 1019 | AndAnd 1020 ; 1021 1022 declaratorid 1023 : Ellipsis? idExpression 1024 ; 1025 1026 theTypeId 1027 : typeSpecifierSeq abstractDeclarator? 1028 ; 1029 1030 abstractDeclarator 1031 : pointerAbstractDeclarator 1032 | noPointerAbstractDeclarator? parametersAndQualifiers trailingReturnType 1033 | abstractPackDeclarator 1034 ; 1035 1036 pointerAbstractDeclarator 1037 : pointerOperator* (noPointerAbstractDeclarator | pointerOperator) 1038 ; 1039 1040 noPointerAbstractDeclarator 1041 : (parametersAndQualifiers | LeftParen pointerAbstractDeclarator RightParen) ( 1042 parametersAndQualifiers 1043 | LeftBracket constantExpression? RightBracket attributeSpecifierSeq? 1044 )* 1045 ; 1046 1047 abstractPackDeclarator 1048 : pointerOperator* noPointerAbstractPackDeclarator 1049 ; 1050 1051 noPointerAbstractPackDeclarator 1052 : Ellipsis ( 1053 parametersAndQualifiers 1054 | LeftBracket constantExpression? RightBracket attributeSpecifierSeq? 1055 )* 1056 ; 1057 1058 parameterDeclarationClause 1059 : parameterDeclarationList (Comma? Ellipsis)? 1060 ; 1061 1062 parameterDeclarationList 1063 : parameterDeclaration (Comma parameterDeclaration)* 1064 ; 1065 1066 parameterDeclaration 1067 : attributeSpecifierSeq? declSpecifierSeq (declarator | abstractDeclarator?) ( 1068 Assign initializerClause 1069 )? 1070 ; 1071 1072 functionDefinition 1073 : attributeSpecifierSeq? declSpecifierSeq? declarator virtualSpecifierSeq? functionBody 1074 ; 1075 1076 functionBody 1077 : constructorInitializer? compoundStatement 1078 | functionTryBlock 1079 | Assign (Default | Delete) Semi 1080 ; 1081 1082 initializer 1083 : braceOrEqualInitializer 1084 | LeftParen expressionList RightParen 1085 ; 1086 1087 braceOrEqualInitializer 1088 : Assign initializerClause 1089 | bracedInitList 1090 ; 1091 1092 initializerClause 1093 : assignmentExpression 1094 | bracedInitList 1095 ; 1096 1097 initializerList 1098 : initializerClause Ellipsis? (Comma initializerClause Ellipsis?)* 1099 ; 1100 1101 bracedInitList 1102 : LeftBrace (initializerList Comma?)? RightBrace 1103 ; 1104 1105 /*Classes*/ 1106 1107 className 1108 : Identifier 1109 | simpleTemplateId 1110 ; 1111 1112 classSpecifier 1113 : classHead LeftBrace memberSpecification? RightBrace 1114 ; 1115 1116 classHead 1117 : classKey attributeSpecifierSeq? (classHeadName classVirtSpecifier?)? baseClause? 1118 | Union attributeSpecifierSeq? ( classHeadName classVirtSpecifier?)? 1119 ; 1120 1121 classHeadName 1122 : nestedNameSpecifier? className 1123 ; 1124 1125 classVirtSpecifier 1126 : Final 1127 ; 1128 1129 classKey 1130 : Class 1131 | Struct 1132 ; 1133 1134 memberSpecification 1135 : (memberdeclaration | accessSpecifier Colon)+ 1136 ; 1137 1138 memberdeclaration 1139 : attributeSpecifierSeq? declSpecifierSeq? memberDeclaratorList? Semi 1140 | functionDefinition 1141 | usingDeclaration 1142 | staticAssertDeclaration 1143 | templateDeclaration 1144 | aliasDeclaration 1145 | emptyDeclaration_ 1146 ; 1147 1148 memberDeclaratorList 1149 : memberDeclarator (Comma memberDeclarator)* 1150 ; 1151 1152 memberDeclarator 1153 : declarator ( 1154 virtualSpecifierSeq 1155 | { this.IsPureSpecifierAllowed() }? pureSpecifier 1156 | { this.IsPureSpecifierAllowed() }? virtualSpecifierSeq pureSpecifier 1157 | braceOrEqualInitializer 1158 ) 1159 | declarator 1160 | Identifier? attributeSpecifierSeq? Colon constantExpression 1161 ; 1162 1163 virtualSpecifierSeq 1164 : virtualSpecifier+ 1165 ; 1166 1167 virtualSpecifier 1168 : Override 1169 | Final 1170 ; 1171 1172 /* 1173 purespecifier: Assign '0'//Conflicts with the lexer ; 1174 */ 1175 1176 pureSpecifier 1177 : Assign IntegerLiteral 1178 ; 1179 1180 /*Derived classes*/ 1181 1182 baseClause 1183 : Colon baseSpecifierList 1184 ; 1185 1186 baseSpecifierList 1187 : baseSpecifier Ellipsis? (Comma baseSpecifier Ellipsis?)* 1188 ; 1189 1190 baseSpecifier 1191 : attributeSpecifierSeq? ( 1192 baseTypeSpecifier 1193 | Virtual accessSpecifier? baseTypeSpecifier 1194 | accessSpecifier Virtual? baseTypeSpecifier 1195 ) 1196 ; 1197 1198 classOrDeclType 1199 : nestedNameSpecifier? className 1200 | decltypeSpecifier 1201 ; 1202 1203 baseTypeSpecifier 1204 : classOrDeclType 1205 ; 1206 1207 accessSpecifier 1208 : Private 1209 | Protected 1210 | Public 1211 ; 1212 1213 /*Special member functions*/ 1214 1215 conversionFunctionId 1216 : Operator conversionTypeId 1217 ; 1218 1219 conversionTypeId 1220 : typeSpecifierSeq conversionDeclarator? 1221 ; 1222 1223 conversionDeclarator 1224 : pointerOperator conversionDeclarator? 1225 ; 1226 1227 constructorInitializer 1228 : Colon memInitializerList 1229 ; 1230 1231 memInitializerList 1232 : memInitializer Ellipsis? (Comma memInitializer Ellipsis?)* 1233 ; 1234 1235 memInitializer 1236 : meminitializerid (LeftParen expressionList? RightParen | bracedInitList) 1237 ; 1238 1239 meminitializerid 1240 : classOrDeclType 1241 | Identifier 1242 ; 1243 1244 /*Overloading*/ 1245 1246 operatorFunctionId 1247 : Operator theOperator 1248 ; 1249 1250 literalOperatorId 1251 : Operator (StringLiteral Identifier | UserDefinedStringLiteral) 1252 ; 1253 1254 /*Templates*/ 1255 1256 templateDeclaration 1257 : Template Less templateparameterList Greater declaration 1258 ; 1259 1260 templateparameterList 1261 : templateParameter (Comma templateParameter)* 1262 ; 1263 1264 templateParameter 1265 : typeParameter 1266 | parameterDeclaration 1267 ; 1268 1269 typeParameter 1270 : ((Template Less templateparameterList Greater)? Class | Typename_) ( 1271 Ellipsis? Identifier? 1272 | Identifier? Assign theTypeId 1273 ) 1274 ; 1275 1276 simpleTemplateId 1277 : templateName Less templateArgumentList? Greater 1278 ; 1279 1280 templateId 1281 : simpleTemplateId 1282 | (operatorFunctionId | literalOperatorId) Less templateArgumentList? Greater 1283 ; 1284 1285 templateName 1286 : Identifier 1287 ; 1288 1289 templateArgumentList 1290 : templateArgument Ellipsis? (Comma templateArgument Ellipsis?)* 1291 ; 1292 1293 templateArgument 1294 : theTypeId 1295 | constantExpression 1296 | idExpression 1297 ; 1298 1299 typeNameSpecifier 1300 : Typename_ nestedNameSpecifier (Identifier | Template? simpleTemplateId) 1301 ; 1302 1303 explicitInstantiation 1304 : Extern? Template declaration 1305 ; 1306 1307 explicitSpecialization 1308 : Template Less Greater declaration 1309 ; 1310 1311 /*Exception handling*/ 1312 1313 tryBlock 1314 : Try compoundStatement handlerSeq 1315 ; 1316 1317 functionTryBlock 1318 : Try constructorInitializer? compoundStatement handlerSeq 1319 ; 1320 1321 handlerSeq 1322 : handler+ 1323 ; 1324 1325 handler 1326 : Catch LeftParen exceptionDeclaration RightParen compoundStatement 1327 ; 1328 1329 exceptionDeclaration 1330 : attributeSpecifierSeq? typeSpecifierSeq (declarator | abstractDeclarator)? 1331 | Ellipsis 1332 ; 1333 1334 throwExpression 1335 : Throw assignmentExpression? 1336 ; 1337 1338 exceptionSpecification 1339 : dynamicExceptionSpecification 1340 | noeExceptSpecification 1341 ; 1342 1343 dynamicExceptionSpecification 1344 : Throw LeftParen typeIdList? RightParen 1345 ; 1346 1347 typeIdList 1348 : theTypeId Ellipsis? (Comma theTypeId Ellipsis?)* 1349 ; 1350 1351 noeExceptSpecification 1352 : Noexcept LeftParen constantExpression RightParen 1353 | Noexcept 1354 ; 1355 1356 /*Preprocessing directives*/ 1357 1358 /*Lexer*/ 1359 1360 theOperator 1361 : New (LeftBracket RightBracket)? 1362 | Delete (LeftBracket RightBracket)? 1363 | Plus 1364 | Minus 1365 | Star 1366 | Div 1367 | Mod 1368 | Caret 1369 | And 1370 | Or 1371 | Tilde 1372 | Not 1373 | Assign 1374 | Greater 1375 | Less 1376 | GreaterEqual 1377 | PlusAssign 1378 | MinusAssign 1379 | StarAssign 1380 | ModAssign 1381 | XorAssign 1382 | AndAssign 1383 | OrAssign 1384 | Less Less 1385 | Greater Greater 1386 | RightShiftAssign 1387 | LeftShiftAssign 1388 | Equal 1389 | NotEqual 1390 | LessEqual 1391 | AndAnd 1392 | OrOr 1393 | PlusPlus 1394 | MinusMinus 1395 | Comma 1396 | ArrowStar 1397 | Arrow 1398 | LeftParen RightParen 1399 | LeftBracket RightBracket 1400 ; 1401 1402 literal 1403 : IntegerLiteral 1404 | CharacterLiteral 1405 | FloatingLiteral 1406 | StringLiteral 1407 | BooleanLiteral 1408 | PointerLiteral 1409 | UserDefinedLiteral 1410 ; 1411 1412 1413 IntegerLiteral: 1414 DecimalLiteral Integersuffix? 1415 | OctalLiteral Integersuffix? 1416 | HexadecimalLiteral Integersuffix? 1417 | BinaryLiteral Integersuffix? 1418 ; 1419 1420 CharacterLiteral: ('u' | 'U' | 'L')? '\'' Cchar+ '\''; 1421 1422 FloatingLiteral: 1423 Fractionalconstant Exponentpart? Floatingsuffix? 1424 | Digitsequence Exponentpart Floatingsuffix? 1425 ; 1426 1427 StringLiteral: Encodingprefix? (Rawstring | '"' Schar* '"'); 1428 1429 BooleanLiteral: False_ | True_; 1430 1431 PointerLiteral: Nullptr; 1432 1433 UserDefinedLiteral: 1434 UserDefinedIntegerLiteral 1435 | UserDefinedFloatingLiteral 1436 | UserDefinedStringLiteral 1437 | UserDefinedCharacterLiteral 1438 ; 1439 1440 MultiLineMacro: '#' (~[\n]*? '\\' '\r'? '\n')+ ~ [\n]+ -> channel (HIDDEN); 1441 1442 Directive: '#' ~ [\n]* -> channel (HIDDEN); 1443 /*Keywords*/ 1444 1445 Alignas: 'alignas'; 1446 1447 Alignof: 'alignof'; 1448 1449 Asm: 'asm'; 1450 1451 Auto: 'auto'; 1452 1453 Bool: 'bool'; 1454 1455 Break: 'break'; 1456 1457 Case: 'case'; 1458 1459 Catch: 'catch'; 1460 1461 Char: 'char'; 1462 1463 Char16: 'char16_t'; 1464 1465 Char32: 'char32_t'; 1466 1467 Class: 'class'; 1468 1469 Const: 'const'; 1470 1471 Constexpr: 'constexpr'; 1472 1473 Const_cast: 'const_cast'; 1474 1475 Continue: 'continue'; 1476 1477 Decltype: 'decltype'; 1478 1479 Default: 'default'; 1480 1481 Delete: 'delete'; 1482 1483 Do: 'do'; 1484 1485 Double: 'double'; 1486 1487 Dynamic_cast: 'dynamic_cast'; 1488 1489 Else: 'else'; 1490 1491 Enum: 'enum'; 1492 1493 Explicit: 'explicit'; 1494 1495 Export: 'export'; 1496 1497 Extern: 'extern'; 1498 1499 //DO NOT RENAME - PYTHON NEEDS True and False 1500 False_: 'false'; 1501 1502 Final: 'final'; 1503 1504 Float: 'float'; 1505 1506 For: 'for'; 1507 1508 Friend: 'friend'; 1509 1510 Goto: 'goto'; 1511 1512 If: 'if'; 1513 1514 Inline: 'inline'; 1515 1516 Int: 'int'; 1517 1518 Long: 'long'; 1519 1520 Mutable: 'mutable'; 1521 1522 Namespace: 'namespace'; 1523 1524 New: 'new'; 1525 1526 Noexcept: 'noexcept'; 1527 1528 Nullptr: 'nullptr'; 1529 1530 Operator: 'operator'; 1531 1532 Override: 'override'; 1533 1534 Private: 'private'; 1535 1536 Protected: 'protected'; 1537 1538 Public: 'public'; 1539 1540 Register: 'register'; 1541 1542 Reinterpret_cast: 'reinterpret_cast'; 1543 1544 Return: 'return'; 1545 1546 Short: 'short'; 1547 1548 Signed: 'signed'; 1549 1550 Sizeof: 'sizeof'; 1551 1552 Static: 'static'; 1553 1554 Static_assert: 'static_assert'; 1555 1556 Static_cast: 'static_cast'; 1557 1558 Struct: 'struct'; 1559 1560 Switch: 'switch'; 1561 1562 Template: 'template'; 1563 1564 This: 'this'; 1565 1566 Thread_local: 'thread_local'; 1567 1568 Throw: 'throw'; 1569 1570 //DO NOT RENAME - PYTHON NEEDS True and False 1571 True_: 'true'; 1572 1573 Try: 'try'; 1574 1575 Typedef: 'typedef'; 1576 1577 Typeid_: 'typeid'; 1578 1579 Typename_: 'typename'; 1580 1581 Union: 'union'; 1582 1583 Unsigned: 'unsigned'; 1584 1585 Using: 'using'; 1586 1587 Virtual: 'virtual'; 1588 1589 Void: 'void'; 1590 1591 Volatile: 'volatile'; 1592 1593 Wchar: 'wchar_t'; 1594 1595 While: 'while'; 1596 /*Operators*/ 1597 1598 LeftParen: '('; 1599 1600 RightParen: ')'; 1601 1602 LeftBracket: '['; 1603 1604 RightBracket: ']'; 1605 1606 LeftBrace: '{'; 1607 1608 RightBrace: '}'; 1609 1610 Plus: '+'; 1611 1612 Minus: '-'; 1613 1614 Star: '*'; 1615 1616 Div: '/'; 1617 1618 Mod: '%'; 1619 1620 Caret: '^'; 1621 1622 And: '&'; 1623 1624 Or: '|'; 1625 1626 Tilde: '~'; 1627 1628 Not: '!' | 'not'; 1629 1630 Assign: '='; 1631 1632 Less: '<'; 1633 1634 Greater: '>'; 1635 1636 PlusAssign: '+='; 1637 1638 MinusAssign: '-='; 1639 1640 StarAssign: '*='; 1641 1642 DivAssign: '/='; 1643 1644 ModAssign: '%='; 1645 1646 XorAssign: '^='; 1647 1648 AndAssign: '&='; 1649 1650 OrAssign: '|='; 1651 1652 LeftShiftAssign: '<<='; 1653 1654 RightShiftAssign: '>>='; 1655 1656 Equal: '=='; 1657 1658 NotEqual: '!='; 1659 1660 LessEqual: '<='; 1661 1662 GreaterEqual: '>='; 1663 1664 AndAnd: '&&' | 'and'; 1665 1666 OrOr: '||' | 'or'; 1667 1668 PlusPlus: '++'; 1669 1670 MinusMinus: '--'; 1671 1672 Comma: ','; 1673 1674 ArrowStar: '->*'; 1675 1676 Arrow: '->'; 1677 1678 Question: '?'; 1679 1680 Colon: ':'; 1681 1682 Doublecolon: '::'; 1683 1684 Semi: ';'; 1685 1686 Dot: '.'; 1687 1688 DotStar: '.*'; 1689 1690 Ellipsis: '...'; 1691 1692 fragment Hexquad: HEXADECIMALDIGIT HEXADECIMALDIGIT HEXADECIMALDIGIT HEXADECIMALDIGIT; 1693 1694 fragment Universalcharactername: '\\u' Hexquad | '\\U' Hexquad Hexquad; 1695 1696 Identifier: 1697 /* 1698 Identifiernondigit | Identifier Identifiernondigit | Identifier DIGIT 1699 */ Identifiernondigit (Identifiernondigit | DIGIT)* 1700 ; 1701 1702 fragment Identifiernondigit: NONDIGIT | Universalcharactername; 1703 1704 fragment NONDIGIT: [a-zA-Z_]; 1705 1706 fragment DIGIT: [0-9]; 1707 1708 DecimalLiteral: NONZERODIGIT ('\''? DIGIT)*; 1709 1710 OctalLiteral: '0' ('\''? OCTALDIGIT)*; 1711 1712 HexadecimalLiteral: ('0x' | '0X') HEXADECIMALDIGIT ( '\''? HEXADECIMALDIGIT)*; 1713 1714 BinaryLiteral: ('0b' | '0B') BINARYDIGIT ('\''? BINARYDIGIT)*; 1715 1716 fragment NONZERODIGIT: [1-9]; 1717 1718 fragment OCTALDIGIT: [0-7]; 1719 1720 fragment HEXADECIMALDIGIT: [0-9a-fA-F]; 1721 1722 fragment BINARYDIGIT: [01]; 1723 1724 Integersuffix: 1725 Unsignedsuffix Longsuffix? 1726 | Unsignedsuffix Longlongsuffix? 1727 | Longsuffix Unsignedsuffix? 1728 | Longlongsuffix Unsignedsuffix? 1729 ; 1730 1731 fragment Unsignedsuffix: [uU]; 1732 1733 fragment Longsuffix: [lL]; 1734 1735 fragment Longlongsuffix: 'll' | 'LL'; 1736 1737 fragment Cchar: ~ ['\\\r\n] | Escapesequence | Universalcharactername; 1738 1739 fragment Escapesequence: Simpleescapesequence | Octalescapesequence | Hexadecimalescapesequence; 1740 1741 fragment Simpleescapesequence: 1742 '\\\'' 1743 | '\\"' 1744 | '\\?' 1745 | '\\\\' 1746 | '\\a' 1747 | '\\b' 1748 | '\\f' 1749 | '\\n' 1750 | '\\r' 1751 | '\\' ('\r' '\n'? | '\n') 1752 | '\\t' 1753 | '\\v' 1754 ; 1755 1756 fragment Octalescapesequence: 1757 '\\' OCTALDIGIT 1758 | '\\' OCTALDIGIT OCTALDIGIT 1759 | '\\' OCTALDIGIT OCTALDIGIT OCTALDIGIT 1760 ; 1761 1762 fragment Hexadecimalescapesequence: '\\x' HEXADECIMALDIGIT+; 1763 1764 fragment Fractionalconstant: Digitsequence? '.' Digitsequence | Digitsequence '.'; 1765 1766 fragment Exponentpart: 'e' SIGN? Digitsequence | 'E' SIGN? Digitsequence; 1767 1768 fragment SIGN: [+-]; 1769 1770 fragment Digitsequence: DIGIT ('\''? DIGIT)*; 1771 1772 fragment Floatingsuffix: [flFL]; 1773 1774 fragment Encodingprefix: 'u8' | 'u' | 'U' | 'L'; 1775 1776 fragment Schar: ~ ["\\\r\n] | Escapesequence | Universalcharactername; 1777 1778 fragment Rawstring: 'R"' ( '\\' ["()] | ~[\r\n (])*? '(' ~[)]*? ')' ( '\\' ["()] | ~[\r\n "])*? '"'; 1779 1780 UserDefinedIntegerLiteral: 1781 DecimalLiteral Udsuffix 1782 | OctalLiteral Udsuffix 1783 | HexadecimalLiteral Udsuffix 1784 | BinaryLiteral Udsuffix 1785 ; 1786 1787 UserDefinedFloatingLiteral: 1788 Fractionalconstant Exponentpart? Udsuffix 1789 | Digitsequence Exponentpart Udsuffix 1790 ; 1791 1792 UserDefinedStringLiteral: StringLiteral Udsuffix; 1793 1794 UserDefinedCharacterLiteral: CharacterLiteral Udsuffix; 1795 1796 fragment Udsuffix: Identifier; 1797 1798 Whitespace: [ \t]+ -> skip; 1799 1800 Newline: ('\r' '\n'? | '\n') -> skip; 1801 1802 BlockComment: '/*' .*? '*/' -> skip; 1803 1804 LineComment: '//' ~ [\r\n]* -> skip; 1805 ``` 1806 1807 在文件夹中新建一个CPP14ParserBase.ts文件,内容如下: 1808 1809 ```ts 1810 import {Parser, Lexer, Token, TokenStream, ParserRuleContext} from "antlr4"; 1811 import CPP14Parser from './CPP14Parser'; 1812 import ParametersAndQualifiersContext from './CPP14Parser'; 1813 1814 export default abstract class CPP14ParserBase extends Parser { 1815 1816 constructor(input: TokenStream) { 1817 super(input); 1818 } 1819 1820 protected IsPureSpecifierAllowed() : boolean { 1821 try { 1822 var x = this._ctx; // memberDeclarator 1823 if (!x || !x.children) { 1824 return false; 1825 } 1826 const c = (x.children[0] as ParserRuleContext)?.children?.[0] as ParserRuleContext; 1827 if (!c || !c.children) { 1828 return false; 1829 } 1830 var c2 = c.children[0] as ParserRuleContext; 1831 if (!c2 || !c2.children) { 1832 return false; 1833 } 1834 var p = c2.children[1] as ParserRuleContext; 1835 if (p == undefined) 1836 return false; 1837 var r = p.constructor.name === "ParametersAndQualifiersContext"; 1838 return r; 1839 } catch (e) { 1840 } 1841 return false; 1842 } 1843 } 1844 1845 ``` 1846 18472. 在该语法文件所在目录下打开命令行窗口,输入以下命令生成TypeScript解析器 1848 1849 ``` 1850 antlr4 -Dlanguage=TypeScript -listener CPP14.g4 1851 ``` 1852 1853 生成文件如下 1854 1855  1856 18573. 配置TypeScript项目,即在语法文件所在目录下输入以下命令: 1858 1859 ``` 1860 npm init -y 1861 npm install antlr4 1862 npm install @types/node --save-dev 1863 ``` 1864 1865 并在语法文件所在目录下新建一tsconfig.json文件,文件内容如下: 1866 1867 ```json 1868 { 1869 "compilerOptions": { 1870 "target": "ES6", 1871 "module": "commonjs", 1872 "strict": true, 1873 } 1874 } 1875 ``` 1876 18774. 在语法文件同级目录下新建一文件CPPListener.ts,文件内容如下: 1878 1879 ```ts 1880 import { TerminalNode, ErrorNode, ParserRuleContext } from 'antlr4'; 1881 import CPP14Listener from './CPP14Listener'; 1882 import { SelectionStatementContext, ClassSpecifierContext, FunctionSpecifierContext } from './CPP14Parser'; 1883 1884 export class CPPListener implements CPP14Listener { 1885 private blockDeclarations: string[] = []; 1886 private functionDefinitions: string[] = []; 1887 private selectionStatements: string[] = []; 1888 private classSpecifiers: string[] = []; 1889 1890 enterFunctionDefinition(ctx: FunctionDefinitionContext) { 1891 const functionDefinition = ctx.getText(); 1892 this.functionDefinitions.push(functionDefinition); 1893 console.log(`[Listener] functionDefinition: ${functionDefinition}`) 1894 } 1895 exitFunctionDefinition(ctx: FunctionDefinitionContext) {} 1896 1897 enterSelectionStatement(ctx: SelectionStatementContext) { 1898 const selectionStatement = ctx.getText(); 1899 this.selectionStatements.push(selectionStatement); 1900 console.log(`[Listener] Selection statement: ${selectionStatement}`); 1901 } 1902 exitSelectionStatement(ctx: SelectionStatementContext) {} 1903 1904 enterClassSpecifier(ctx: ClassSpecifierContext) { 1905 const classSpecifier = ctx.getText(); 1906 this.classSpecifiers.push(classSpecifier); 1907 console.log(`[Listener] Class specifier: ${classSpecifier}`); 1908 } 1909 exitClassSpecifier(ctx: ClassSpecifierContext) {} 1910 1911 visitTerminal(node: TerminalNode): void {} 1912 1913 visitErrorNode(node: ErrorNode): void { 1914 console.error(`[Listener] ${node.toString()}`); 1915 } 1916 1917 enterEveryRule(ctx: ParserRuleContext): void { 1918 // console.log(`[Listener] Enter rule: ${ctx}`); 1919 } 1920 exitEveryRule(ctx: ParserRuleContext): void { 1921 // console.log(`[Listener] Exit rule: ${ctx}`); 1922 } 1923 1924 printMessage() { 1925 console.log(`[Listener] Parsing Complete!`); 1926 console.log(`[Listener] Function definitions: ${this.functionDefinitions}`); 1927 console.log(`[Listener] Selection statements: ${this.selectionStatements}`); 1928 console.log(`[Listener] Class specifiers: ${this.classSpecifiers}`); 1929 } 1930 } 1931 ``` 1932 19335. 编写解析代码,即在语法文件所在目录下新建一index.ts文件,内容如下: 1934 1935 ```ts 1936 import { CharStreams, CommonTokenStream, ParseTreeWalker, ParseTree, RuleContext, TerminalNode } from 'antlr4'; 1937 import CPP14Lexer from './CPP14Lexer'; 1938 import CPP14Parser from './CPP14Parser'; 1939 import { CPPListener } from './CPPListener'; 1940 1941 function parseWithListener(content: string) { 1942 const inputStream = CharStreams.fromString(content); 1943 const lexer = new CPP14Lexer(inputStream); 1944 const tokenStream = new CommonTokenStream(lexer); 1945 const parser = new CPP14Parser(tokenStream); 1946 const tree = parser.translationUnit(); 1947 const listener = new CPPListener(); 1948 const walker = new ParseTreeWalker(); 1949 walker.walk(listener, tree); 1950 listener.printMessage(); 1951 1952 return tree; 1953 } 1954 1955 const testInput = ` 1956 #include<cstdio> 1957 #include<memory> 1958 #include"cfi_util.h" 1959 1960 class A { 1961 public: 1962 virtual void f(){ 1963 printf("baseA"); 1964 } 1965 virtual ~A(){} 1966 }; 1967 1968 class B : public A{ 1969 public: 1970 void f() override{ 1971 printf("subclassB"); 1972 } 1973 ~B() override{} 1974 }; 1975 1976 class C: public A{ 1977 public: 1978 void f() override{ 1979 printf("subclassC"); 1980 } 1981 ~C() override{} 1982 }; 1983 1984 int main(){ 1985 1986 if(DEBUG){ 1987 ShowCfiLogFile(); 1988 } 1989 ClearCfiLog(); 1990 if(DEBUG){ 1991 ShowCfiLogFile(); 1992 } 1993 1994 //This test will trigger a subclass parent class conversion CFI check failure 1995 std::shared_ptr<B> b_ptr = std::make_shared<B>(); 1996 std::shared_ptr<A> a_ptr = b_ptr; 1997 int* a_vtable = (int*)a_ptr.get(); 1998 printf("a_vtable: %x",*a_vtable); 1999 std::shared_ptr<C> c_ptr = std::static_pointer_cast<C>(a_ptr); 2000 FindAndCheck("'C' failed during base-to-derived cast"); 2001 2002 ClearCfiLog(); 2003 if(DEBUG){ 2004 ShowCfiLogFile(); 2005 } 2006 return 0; 2007 } 2008 `; 2009 2010 const parseTree = parseWithListener(testInput); 2011 console.log(parseTree); 2012 ``` 2013 20146. 编译并运行解析器 2015 2016 ``` 2017 npx tsc 2018 node index.js 2019 ``` 2020 2021 获得解析结果如下 2022  2023