ANTLR4如何获取树结构
How to get a tree structure ANLTR4
我需要像这样解析配置文件
"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 "label 1" "label 2" ... "label n"
因此解析器的完美结果将是字符串数组,如:
- "Agent 1" "ip" "192.67.4.1"
- "Agent 1" "port" "12345"
- "Agent 1" "neighbours" "agent 2" "ip" "192.67.4.2"
- "Agent 1""neighbours""agent 2""port"“12345”
- 等等...
但我无法进一步实现我的解析器来获取这样的字符串数组。所以我的问题是该怎么做?我知道我需要扩展 BasicListener 的 Parser 之类的东西,但无法管理它。
解决方案
首先,让我们将命名替代项 root
更改为:
group
: node '(' (group (',')?)+ ')' # root
| node # value
;
这使我们能够跟踪每个 group
的 header(node
)。当我进一步提到 tree 时,我的意思是 config 树结构 。那我们来做两个定义:
- path - 是从树根到树叶收集的一串值(例如
"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
的header。否则我们检索 部分路径 并向其添加根的 header。当我们偶然发现 value
我们在树的叶子上时,我们完成了 路径 。我们 pop()
部分路径 ,然后我们向其添加 node
值。结果字符串(完整的 path)进入 paths
列表。
我需要像这样解析配置文件
"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 "label 1" "label 2" ... "label n"
因此解析器的完美结果将是字符串数组,如:
- "Agent 1" "ip" "192.67.4.1"
- "Agent 1" "port" "12345"
- "Agent 1" "neighbours" "agent 2" "ip" "192.67.4.2"
- "Agent 1""neighbours""agent 2""port"“12345”
- 等等...
但我无法进一步实现我的解析器来获取这样的字符串数组。所以我的问题是该怎么做?我知道我需要扩展 BasicListener 的 Parser 之类的东西,但无法管理它。
解决方案
首先,让我们将命名替代项 root
更改为:
group
: node '(' (group (',')?)+ ')' # root
| node # value
;
这使我们能够跟踪每个 group
的 header(node
)。当我进一步提到 tree 时,我的意思是 config 树结构 。那我们来做两个定义:
- path - 是从树根到树叶收集的一串值(例如
"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
的header。否则我们检索 部分路径 并向其添加根的 header。当我们偶然发现 value
我们在树的叶子上时,我们完成了 路径 。我们 pop()
部分路径 ,然后我们向其添加 node
值。结果字符串(完整的 path)进入 paths
列表。