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

标签 parsing antlr antlr4 lexer

就我而言,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 参数具有规则中每个备选方案的成员。检查哪一个不为空以查看哪一个实际匹配。

关于parsing - 如何使用antlr4中的Listener方法获取解析器的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61716403/

相关文章:

java - 从 Android 中的 URL 解析极其简单的 JSON

linux - 解析json数据时文本编码错误

java - JavaCC 中的左递归(直接和间接)消除

c# - 解析看似正确的日期时间时抛出异常

java - Antlr4 - 语法解析日志文件

java - 在 Apache Ant 中使用 <java> 标签,我可以同时运行 Server 和 Proxy Server 类吗

c# - ANTLR:如何避免在用户修改文本时重新解析整个文件

java - ANTLR 警告 : TestRig moved to org. antlr.v4.gui.TestRig

带有 @init block 的 ANTLR4 词法分析器规则

java - 使用字符串模板将首字母转换为大写