我需要以这样的形式解析配置文件
"agent 1"(
"ip"("192.67.4.1"),
"port"("12345"),
"neighbours"(
"agent 2"(
"ip"("192.67.4.2"),
"port"("12345")),
"agent 3"(
"ip"("192.67.4.1"),
"port"("12346"))),
"measurements"(
"voltage"("4.2V"),
"power"("7KW")))
到目前为止我得到的是语法(主要通过少数教程中的试错法获得)
grammar Tree;
compileUnit
: group EOF
;
group
: (node '(' group ')' (',')? )* # root
| node # value
;
node
: STRING # label
;
STRING : '"'[ a-zA-Z0-9\.]+'"';
WS : [ \t\r\n] -> channel(HIDDEN);
在预览中它的结果是这样的树 Tree
我已经有了以表格形式向我的树添加节点的功能(其他要求):
ADD"标签1" "标签2" ......"标签n"
因此,解析器的完美结果将是String数组,如:
但是我无法进一步实现我的解析器以获得这样的String数组。所以我的问题是如何做到这一点?我知道我需要扩展像BasicListener的Parser这样的东西但是无法管理它。
答案 0 :(得分:1)
首先,让我们将命名的替代root
更改为:
group
: node '(' (group (',')?)+ ')' # root
| node # value
;
这样我们就可以跟踪每个node
的标题(group
)。当我进一步引用树时,我的意思是配置树结构。然后让我们做两个定义:
"Agent 1" "neighbours" "agent 2" "ip" "192.67.4.2"
),"Agent 1" "neighbours" "agent 2" "ip"
)。现在我们将编写一个简单的树监听器来收集路径。
public class TreeToArray extends TreeBaseListener {
Stack<String> partialPath = new Stack<>();
public List<String> paths = new ArrayList<>();
@Override
public void enterRoot(TreeParser.RootContext ctx) {
if (partialPath.isEmpty()) {
// We are in top-root, partial path consists of top-root's name
partialPath.push(ctx.node().getText());
} else {
// We are in one of the sub-roots, partialPath.peek() returns a current partial path
partialPath.push(partialPath.peek() + " " + ctx.node().getText());
}
}
@Override
public void enterValue(TreeParser.ValueContext ctx) {
paths.add(partialPath.peek() + " " + ctx.getText());
}
@Override
public void exitRoot(TreeParser.RootContext ctx) {
partialPath.pop();
}
}
堆栈partialPath
保留有关当前构建的部分路径的信息。当我们访问主要内容时,首先root
(例如"Agent 1"
)我们没有任何部分路径,因此我们将root
放入堆栈头。否则,我们会检索部分路径并将其添加到root的标头中。当我们遇到value
我们在树的叶子时,我们完成了路径。我们pop()
部分路径,然后我们添加node
值。结果字符串(完整的路径)会进入paths
列表。