Parsing 如何在antlr4中使用Listener方法来获取解析器的内容?
就我而言,antlr4的侦听器方法似乎只能直接获取终端节点的信息——特别是Lexer节点 但是,现在我希望把解析器的信息发布如下:Parsing 如何在antlr4中使用Listener方法来获取解析器的内容?,parsing,antlr,antlr4,lexer,Parsing,Antlr,Antlr4,Lexer,就我而言,antlr4的侦听器方法似乎只能直接获取终端节点的信息——特别是Lexer节点 但是,现在我希望把解析器的信息发布如下: type : primitiveType | referencedType | arrayType | listType | mapType | 'void' ; primitiveType : 'byte' | 'short' | 'i
type :
primitiveType
| referencedType
| arrayType
| listType
| mapType
| 'void'
;
primitiveType :
'byte'
| 'short'
| 'int'
| 'long'
| 'char'
| 'float'
| 'double'
| 'boolean'
;
referencedType :
'String'
| 'CharSequence'
| selfdefineType
;
首先,我想弄清楚如何直接获取primitiveType
的内容,并将byte
或short
等内容输出,而不将其更改为Lexer(TerminalNode)。我已经检查了aidlParser.java
(aidl.g4是我的初始语法文件)的代码(
其次,我想知道是否有一种方法可以知道解析器实际匹配的是什么。例如,我想知道type
的哪个规则(比如primitiveType
或referencedType
…)用于匹配语法中的类型,而不必访问每个子节点(实际上是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
;
语法辅助;
//分析器
//文件
文件:packageDeclaration*importDeclaration*parcelableDeclaration?interfaceDeclaration;
//包装声明
packageDeclaration:'package'packageName';';
packageName:标识符
|
packageName“.”标识符;
//进口折扣
进口折扣
:'import'importName';'
;
importName:标识符
|
导入名称“.”标识符;
//包裹申报
parcelableDeclaration:“parcelable'parcelableName';”;
parcelableName:标识符;
//接口声明
interfaceDeclaration:interfaceTag?'interface'interfaceName'{'methodsDeclaration+'}';
接口标签:“单向”;
接口名称:标识符;
//方法说明
methodsDeclaration:methodTag?returnType methodName'(“参数”)“”;
方法名称:标识符;
methodTag:‘单向’;
返回类型:返回类型;
//参数
参数
:参数(“,”参数)*
;
参数
:parameterTag?parameterType parameterName;
参数类型:类型;
参数名称:标识符;
参数标签:“in”|“out”|“inout”;
//类型
类型:
基本类型
|引用类型
|阵列类型
|列表类型
|地图类型
|“无效”
;
基本类型:
“字节”
|“短”
|“int”
|“长”
|“char”
|“浮动”
|“双人”
|“布尔”
;
引用类型:
“字符串”
|“字符序列”
|自定义类型
;
selfdefineType:标识符;
arrayType:基本类型dims
|引用类型dims
;
listType:'列表'('')?;
映射类型:“映射”(“”)?;
昏暗
: '[' ']' ( '[' ']')*
;
//雷克瑟
//标识符
标识符
:JavaLetter javaletterDigit*
;
片段
爪哇字母
:[a-zA-Z$\//这些是0x7F下面的“java字母”
|//覆盖0x7F以上不是代理项的所有字符
~[\u0000-\u007F\uD800-\uDBFF]
{Character.isJavaIdentifierStart(_input.LA(-1))}?
|//涵盖U+10000到U+10FFFF的UTF-16代理项对编码
[\uD800-\uDBFF][\uDC00-\uDFFF]
{Character.isJavaIdentifierStart(Character.toCodePoint((char)_input.LA(-2),(char)_input.LA(-1))}?
;
片段
JavaletterDigit
:[a-zA-Z0-9$\这些是0x7F下面的“java字母或数字”
|//覆盖0x7F以上不是代理项的所有字符
~[\u0000-\u007F\uD800-\uDBFF]
{Character.isJavaIdentifierPart(_input.LA(-1))}?
|//涵盖U+10000到U+10FFFF的UTF-16代理项对编码
[\uD800-\uDBFF][\uDC00-\uDFFF]
{Character.isJavaIdentifierPart(Character.toCodePoint((char)_input.LA(-2),(char)_input.LA(-1))}?
;
WS:[\t\r\n\u000C]+->跳过
;
我衷心感谢您及时提供的帮助!一旦您的解析运行结束,您将得到一个解析树。您可以将该树向下遍历到您感兴趣的节点(通常使用解析树侦听器,并且只覆盖与您的问题相关的enter/exit*方法)。在
enterPrimitveType
方法中,您将获得一个EnterPrimitiveTypeContext
参数。使用其getText
方法获取匹配的文本
对于你的第二个问题,你也可以这样做,只需使用
enterType
方法即可。在规则中,EnterTypeContext
参数具有每个备选方案的成员。请检查哪个选项不为null,以查看哪个选项实际匹配。谢谢!我会尝试一下!实际上toString
方法似乎没有起作用nd只返回一个[]。但是,它的getText()
方法的工作原理与toString类似,解析器节点也可以使用它。是的,这很可能是Mike的意思。我将编辑他的答案以反映这一点。