• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.batgrun.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   ![image-1](.\images\image-1.png)
39   ![image-2](.\images\image-2.png)
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   ![image-3](.\images\image-3.png)
49   在cmd中输入grun,回车,观察输出是否如下图,如果正常的话,那到这里就说明Antlr4的安装和配置已经成功!
50   ![image-4](.\images\image-4.png)
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.javaxxxParser.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   ![image-5](.\images\image-5.png)
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   ![image-6](.\images\image-6.png)
339
340   在语法文件所在目录的命令行窗口输入  `grun Hello r -tree`,按回车,然后按Ctrl+Z,再次回车,会得到
341
342   ![image-7](.\images\image-7.png)
343
344   在语法文件所在目录的命令行窗口输入  `grun Hello r -gui`,按回车,然后按Ctrl+Z,再次回车,会得到
345
346   ![image-8](.\images\image-8.png)
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   ![image-9](.\images\image-9.png)
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   ![image-10](.\images\image-10.png)
2023