如何得到一个树形结构的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      :   [ trn] -> channel(HIDDEN);

和它的结果是这样的树在预览树

我已经有功能添加节点到我的树的形式(其他要求):

添加"label 1" "label 2"…"标签n"

解析器的完美结果是:

  • "代理1"ip"192.67.4.1"
  • "代理1"端口"12345"
  • "代理1"邻居"代理2"ip"192.67.4.2"
  • "代理1"邻居"代理2"端口"12345"

但是我不能得到进一步和实现我的解析器来获得这样的字符串数组。所以我的问题是怎么做?我知道我需要扩展类似于BasicListener的Parser但无法管理这个

解决方案

首先,让我们将命名的备选root更改为:

group
    :   node '(' (group (',')?)+ ')'     # root
    |   node                             # value
    ;

这允许我们跟踪每个group的标头(node)。当我进一步提到时,我的意思是配置树结构。然后让我们做两个定义:

  • 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的头放到堆栈中。否则,我们将检索部分路径并将其添加到根的头。当我们在树的叶子上偶然发现value时,我们完成了路径。我们pop() 部分路径,然后我们添加node值。结果字符串(完整路径)进入paths列表。

相关内容

  • 没有找到相关文章

最新更新