如何使用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
的内容并输出 byte
或 short
之类的内容而不将其更改为 Lexer(TerminalNode ).我检查了aidlParser.java
的代码(aidl.g4是我的初始语法文件(
其次,我想知道是否有办法知道解析器实际匹配的内容。例如,我想知道 type
的哪个规则(如 primitiveType
或 referencedType
...)用于匹配语法中的类型,而不必访问每个子节点(实际上是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
参数包含规则中每个备选方案的成员。检查哪个不为空以查看哪个实际匹配。
据我所知,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
的内容并输出 byte
或 short
之类的内容而不将其更改为 Lexer(TerminalNode ).我检查了aidlParser.java
的代码(aidl.g4是我的初始语法文件(
其次,我想知道是否有办法知道解析器实际匹配的内容。例如,我想知道 type
的哪个规则(如 primitiveType
或 referencedType
...)用于匹配语法中的类型,而不必访问每个子节点(实际上是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
参数包含规则中每个备选方案的成员。检查哪个不为空以查看哪个实际匹配。