看懂antlr4生成parsercontext代码,找到一种在一个上下文中检测terminalNode的好方法
Understand antlr4 generated parsercontext code, Find a good way to detect terminalNode in one context
G4文件部分为:
typeSpecifier
: ('void'
| 'char'
| 'short'
| 'int'
| '__m128d'
| '__m128i')
| '__extension__' '(' ('__m128' | '__m128d' | '__m128i') ')'
| atomicTypeSpecifier
| structOrUnionSpecifier
| enumSpecifier
| typedefName
| '__typeof__' '(' constantExpression ')' // GCC extension
;
生成的代码是:
public static class TypeSpecifierContext extends ParserRuleContext {
public AtomicTypeSpecifierContext atomicTypeSpecifier() {
return getRuleContext(AtomicTypeSpecifierContext.class,0);
}
public StructOrUnionSpecifierContext structOrUnionSpecifier() {
return getRuleContext(StructOrUnionSpecifierContext.class,0);
}
public EnumSpecifierContext enumSpecifier() {
return getRuleContext(EnumSpecifierContext.class,0);
}
public TypedefNameContext typedefName() {
return getRuleContext(TypedefNameContext.class,0);
}
public ConstantExpressionContext constantExpression() {
return getRuleContext(ConstantExpressionContext.class,0);
}
public TypeSpecifierContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_typeSpecifier; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof ProbeListener ) ((ProbeListener)listener).enterTypeSpecifier(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof ProbeListener ) ((ProbeListener)listener).exitTypeSpecifier(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof ProbeVisitor ) return ((ProbeVisitor<? extends T>)visitor).visitTypeSpecifier(this);
else return visitor.visitChildren(this);
}
}
我想在我的访问代码中查看此 typeSpecifier 是哪种类型:
TypeSpecifierContext typeSpecifier = ctx.typeSpecifier(); // ctx is parent context
LOG.trace(String.format("typeSepcifier the start is %s the stop is %s" , typeSpecifier.getStart().getText()
, typeSpecifier.getStop().getText()));
我可以获得如下输出:
typeSepcifier the start is int the stop is int
我觉得这个方法很丑,Antlr4 可以提供方法来实现像 instanceof IntTypeSpecifier
这样的方法吗?
您可以使用访问者设计模式来访问 ANTLR 的 AST 并对其进行处理,因此您甚至不需要使用 instanceof。
final class Visitor extends YourGrammarParserBaseVisitor<String> { // The name of the base visitor should be <your grammar name> + 'ParserBaseVisitor'
@Override
public String visitTypeSpecifier(TypeSpecifierContext ctx) { // 'visit' + <name of the rule with the first letter to upper case>
// Your code here
return "the result";
}
// other visit methods for other rules
}
给您的访客打电话:
new Visitor.visit(new YourGrammarParser(/* weird ANTLR stuff */).typeSpecifier());
如果您为 int 类型创建规则,假设:
typeSpecifier
: intTypeSpecifier
| // the other rules
;
intTypeSpecifier : 'int';
您将能够为 IntTypeSpecifierContext 创建一个访问方法 visitIntTypeSpecifier
以轻松处理 int 类型。
因此代码应如下所示:
final class Visitor extends YourGrammarParserBaseVisitor<String> {
@Override
public String visitTypeSpecifier(TypeSpecifierContext ctx) {
return super();
}
@Override
public String visitIntTypeSpecifier(IntTypeSpecifierContext ctx) {
return 'int'; // or ctx.getText()
}
// Rest of the rules
}
现在纠正我,因为我可能错了,但是你可以直接调用 getText
来查看 typeSpecifier 的类型(TypeSpecifierContext extend RuleContext 提供了这个方法)。
G4文件部分为:
typeSpecifier
: ('void'
| 'char'
| 'short'
| 'int'
| '__m128d'
| '__m128i')
| '__extension__' '(' ('__m128' | '__m128d' | '__m128i') ')'
| atomicTypeSpecifier
| structOrUnionSpecifier
| enumSpecifier
| typedefName
| '__typeof__' '(' constantExpression ')' // GCC extension
;
生成的代码是:
public static class TypeSpecifierContext extends ParserRuleContext {
public AtomicTypeSpecifierContext atomicTypeSpecifier() {
return getRuleContext(AtomicTypeSpecifierContext.class,0);
}
public StructOrUnionSpecifierContext structOrUnionSpecifier() {
return getRuleContext(StructOrUnionSpecifierContext.class,0);
}
public EnumSpecifierContext enumSpecifier() {
return getRuleContext(EnumSpecifierContext.class,0);
}
public TypedefNameContext typedefName() {
return getRuleContext(TypedefNameContext.class,0);
}
public ConstantExpressionContext constantExpression() {
return getRuleContext(ConstantExpressionContext.class,0);
}
public TypeSpecifierContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_typeSpecifier; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof ProbeListener ) ((ProbeListener)listener).enterTypeSpecifier(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof ProbeListener ) ((ProbeListener)listener).exitTypeSpecifier(this);
}
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
if ( visitor instanceof ProbeVisitor ) return ((ProbeVisitor<? extends T>)visitor).visitTypeSpecifier(this);
else return visitor.visitChildren(this);
}
}
我想在我的访问代码中查看此 typeSpecifier 是哪种类型:
TypeSpecifierContext typeSpecifier = ctx.typeSpecifier(); // ctx is parent context
LOG.trace(String.format("typeSepcifier the start is %s the stop is %s" , typeSpecifier.getStart().getText()
, typeSpecifier.getStop().getText()));
我可以获得如下输出:
typeSepcifier the start is int the stop is int
我觉得这个方法很丑,Antlr4 可以提供方法来实现像 instanceof IntTypeSpecifier
这样的方法吗?
您可以使用访问者设计模式来访问 ANTLR 的 AST 并对其进行处理,因此您甚至不需要使用 instanceof。
final class Visitor extends YourGrammarParserBaseVisitor<String> { // The name of the base visitor should be <your grammar name> + 'ParserBaseVisitor'
@Override
public String visitTypeSpecifier(TypeSpecifierContext ctx) { // 'visit' + <name of the rule with the first letter to upper case>
// Your code here
return "the result";
}
// other visit methods for other rules
}
给您的访客打电话:
new Visitor.visit(new YourGrammarParser(/* weird ANTLR stuff */).typeSpecifier());
如果您为 int 类型创建规则,假设:
typeSpecifier
: intTypeSpecifier
| // the other rules
;
intTypeSpecifier : 'int';
您将能够为 IntTypeSpecifierContext 创建一个访问方法 visitIntTypeSpecifier
以轻松处理 int 类型。
因此代码应如下所示:
final class Visitor extends YourGrammarParserBaseVisitor<String> {
@Override
public String visitTypeSpecifier(TypeSpecifierContext ctx) {
return super();
}
@Override
public String visitIntTypeSpecifier(IntTypeSpecifierContext ctx) {
return 'int'; // or ctx.getText()
}
// Rest of the rules
}
现在纠正我,因为我可能错了,但是你可以直接调用 getText
来查看 typeSpecifier 的类型(TypeSpecifierContext extend RuleContext 提供了这个方法)。