如何使用antlr4中的Listener方法来获取解析器的内容



就我而言,antlr4的Listener方法似乎只能直接获取TerminalNodes的信息,特别是Lexer Nodes。

然而,现在我希望发布这样的Parser信息:

type : 
primitiveType
|   referencedType
|   arrayType
|   listType
|   mapType
|   'void'
;
primitiveType : 
'byte'
|   'short'
|   'int'
|   'long'
|   'char'  
|   'float'
|   'double'
|   'boolean'
;
referencedType : 
'String'
|   'CharSequence'
|   selfdefineType
;

首先,我想弄清楚如何直接获得primitiveType的内容,并在不将其更改为Lexer(TerminalNode(的情况下发出类似byteshort的内容。我已经检查了aidlParser.java的代码(aidl.g4是我的初始语法文件(

其次,我想知道是否有一种方法可以知道解析器实际匹配的内容。例如,我想知道type的哪条规则(比如primitiveTypereferencedType…(用于匹配语法中的类型,而不必访问type的每个子节点(实际上是Lisenter方法中的规则(,看看哪条规则包含什么。

这是我的.g4文件的全部代码:

grammar aidl;
//parser
//file
file : packageDeclaration* importDeclaration* parcelableDeclaration? interfaceDeclaration? ;
//packageDeclaration
packageDeclaration :'package' packageName ';';
packageName :   Identifier 
| 
packageName '.' Identifier;

// importDeclaration
importDeclaration 
: 'import'  importName   ';'   
;
importName : Identifier 
|     
importName '.' Identifier; 

//parcelableDeclaration
parcelableDeclaration : 'parcelable'   parcelableName   ';'   ;
parcelableName : Identifier ; 

//interfaceDeclaration
interfaceDeclaration :  interfaceTag?  'interface'  interfaceName  '{'  methodsDeclaration+  '}' ; 
interfaceTag : 'oneway' ;
interfaceName : Identifier ;

// methodsDeclaration
methodsDeclaration :  methodTag? returnType  methodName  '(' parameters?  ')'  ';'  ;
methodName : Identifier ;
methodTag: 'oneway';
returnType : type ; 

// parameters
parameters
:   parameter (',' parameter)*
;

parameter
:   parameterTag?  parameterType parameterName ;
parameterType : type ;
parameterName : Identifier;
parameterTag : 'in' | 'out' | 'inout' ;

// type 
type : 
primitiveType
|   referencedType
|   arrayType
|   listType
|   mapType
|   'void'
;
primitiveType : 
'byte'
|   'short'
|   'int'
|   'long'
|   'char'  
|   'float'
|   'double'
|   'boolean'
;
referencedType : 
'String'
|   'CharSequence'
|   selfdefineType
;
selfdefineType : Identifier;
arrayType : primitiveType  dims
|   referencedType dims
;
listType : 'List' ('<' (primitiveType | referencedType) (',' (primitiveType | referencedType))* '>')?;
mapType : 'Map' ('<' (primitiveType | referencedType) (',' (primitiveType | referencedType))* '>')?;
dims
:    '[' ']' ( '[' ']')*
;

//Lexer
// Identifier
Identifier
:   JavaLetter JavaLetterOrDigit*
;
fragment
JavaLetter
:   [a-zA-Z$_] // these are the "java letters" below 0x7F
|   // covers all characters above 0x7F which are not a surrogate
~[u0000-u007FuD800-uDBFF]
{Character.isJavaIdentifierStart(_input.LA(-1))}?
|   // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
[uD800-uDBFF] [uDC00-uDFFF]
{Character.isJavaIdentifierStart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
;
fragment
JavaLetterOrDigit
:   [a-zA-Z0-9$_] // these are the "java letters or digits" below 0x7F
|   // covers all characters above 0x7F which are not a surrogate
~[u0000-u007FuD800-uDBFF]
{Character.isJavaIdentifierPart(_input.LA(-1))}?
|   // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
[uD800-uDBFF] [uDC00-uDFFF]
{Character.isJavaIdentifierPart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
;

WS  :  [ trnu000C]+ -> skip
;

我将衷心感谢你的及时帮助!

解析运行结束后,您将获得一个解析树。您可以将该树向下遍历到感兴趣的节点(通常使用解析树侦听器,只覆盖与问题相关的enter/exit*方法(。在enterPrimitveType方法中,您将获得一个EnterPrimitiveTypeContext参数。使用其getText方法来获取与其匹配的文本。

对于您的第二个问题,您也可以使用完全相同的方法,只需使用enterType方法即可。EnterTypeContext参数为规则中的每个备选方案都有成员。检查哪一个不为空,看看哪一个实际匹配。

最新更新