是否可以从antlr4中的解析器定义的标签中检索列表?

时间:2019-01-28 19:31:31

标签: antlr antlr4

使用此虚拟antlr4-语法:

grammar testingGrammar;
@header{package gen;}

dsopt_rename: 'rename' (OLDN=ID '=' NEWN=ID)+;
ID: [a-zA-Z_];

我的目标是Java。我想得到两个列表:oldNames和newNames;可以这样:

@Override
public DsOption visitDsopt_rename(Dsopt_renameContext ctx) {    
    LinkedList<String> oldNames = new LinkedList<String>();
    LinkedList<String> newNames = new LinkedList<String>();
    for (int i=0; i < ctx.ID().size(); ++i) {
        LinkedList<String> rename = (i%2 == 1) ? oldNames : newNames;
        rename.add(ctx.ID(i).getText());
    }
    return new DsOptRename(oldNames, newNames);
}

我更喜欢以下的-也称为“第二种方法”((如果可行)):

@Override
public DsOption visitDsopt_rename(Dsopt_renameContext ctx) {    
    LinkedList<String> oldNames = new LinkedList<String>();
    LinkedList<String> newNames = new LinkedList<String>();
    ctx.OLDN().forEach(e -> oldNames.add(e.getText()));
    ctx.NEWN().forEach(e -> oldNames.add(e.getText()));
    return new DsOptRename(oldNames, newNames);
}

显然,标签ctx.OLDN(不带括号)和ctx.NEWN只保留列表的第一个迭代,而不是整个列表(例如,ID保留整个列表)。

第一个问题: 1.是否可以通过使用第二种方法(即不触及语法)来修复第二种代码以完成工作?请记住,此示例非常简单,因此第一个代码可以正常工作,但是我是否有类似“ example:(ID ID?ID)+;”的规则?将需要另一种方法;也许不可能修复它,因为这种方法最初不应该起作用(规则应该有不同的定义)。

  1. 修改语法以完成语法的最佳方法是什么?我在想:
grammar testingGrammar;
@header{package gen;}

dsopt_rename: 'rename' (oldn '=' newn)+;
oldn: ID;
newn: ID;
ID: [a-zA-Z_];

但是它可能容易出错,因为oldn和newn可能会意外匹配。

感谢您的时间!

1 个答案:

答案 0 :(得分:3)

使用+=表示法收集令牌:

grammar testingGrammar;

dsopt_rename
 : 'rename' ( lhs+=ID '=' rhs+=ID )+
 ;

ID     : [a-zA-Z_];
SPACES : [ \t\r\n]+ -> skip;

像这样测试它:

String source = "rename a = A b = B c = C";

testingGrammarLexer lexer = new testingGrammarLexer(CharStreams.fromString(source));
testingGrammarParser parser = new testingGrammarParser(new CommonTokenStream(lexer));

testingGrammarParser.Dsopt_renameContext ctx = parser.dsopt_rename();

List<Token> lhsTokens = ctx.lhs;
List<Token> rhsTokens = ctx.rhs;

System.out.printf("lhsTokens=%s\nrhsTokens=%s\n", lhsTokens, rhsTokens);

将打印:

lhsTokens=[[@1,7:7='a',<3>,1:7], [@4,13:13='b',<3>,1:13], [@7,19:19='c',<3>,1:19]]
rhsTokens=[[@3,11:11='A',<3>,1:11], [@6,17:17='B',<3>,1:17], [@9,23:23='C',<3>,1:23]]

更多信息:https://github.com/antlr/antlr4/blob/master/doc/parser-rules.md#rule-element-labels