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

How to use Listener method in antlr4 to get the contents of parsers?

据我所知,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 的内容并输出 byteshort 之类的内容而不将其更改为 Lexer(TerminalNode ).我检查了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-\u007F\uD800-\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-\u007F\uD800-\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  :  [ \t\r\n\u000C]+ -> skip
    ;

非常感谢您的及时帮助!

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

对于你的第二个问题,你会做同样的事情,只是使用 enterType 方法。 EnterTypeContext 参数包含规则中每个备选方案的成员。检查哪个不为空以查看哪个实际匹配。