是否可以从 antlr4 中的解析器定义的标签中检索列表?
is it possible to retrieve a list from parser-defined label in 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);
}
我更喜欢以下 - 也称为 "second approach"-(如果有效的话):
@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)+;' 这样的规则,则需要另一种方法;也许无法修复它,因为这种方法一开始就不应该起作用(规则应该有不同的定义)。
- 修改语法以完成它的最佳方法是什么?我在想:
grammar testingGrammar;
@header{package gen;}
dsopt_rename: 'rename' (oldn '=' newn)+;
oldn: ID;
newn: ID;
ID: [a-zA-Z_];
但这可能容易出错,因为 oldn 和 newn 可能会意外匹配。
感谢您的宝贵时间!
使用+=
符号来收集您的代币:
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
使用这个虚拟的 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);
}
我更喜欢以下 - 也称为 "second approach"-(如果有效的话):
@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)+;' 这样的规则,则需要另一种方法;也许无法修复它,因为这种方法一开始就不应该起作用(规则应该有不同的定义)。
- 修改语法以完成它的最佳方法是什么?我在想:
grammar testingGrammar;
@header{package gen;}
dsopt_rename: 'rename' (oldn '=' newn)+;
oldn: ID;
newn: ID;
ID: [a-zA-Z_];
但这可能容易出错,因为 oldn 和 newn 可能会意外匹配。
感谢您的宝贵时间!
使用+=
符号来收集您的代币:
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