【问题标题】:Get children count of a tree node获取树节点的子节点数
【发布时间】:2020-10-22 08:57:59
【问题描述】:

docs for Node 仅提及以下方法:

EqualGreaterThanGreaterThanOrEqualLessThanLessThanOrEqualNotEqualSliceSubscription

它确实提到了如何使用Subscription 按索引访问子节点,但是我如何找出必须遍历它们的子节点的计数?

这是我的用例:

Exp parsed = parse(#Exp, "2+(4+3)*48");
println("the number of root children is: " + size(parsed));

但它会产生错误,因为 size() 似乎只适用于 List

【问题讨论】:

    标签: rascal


    【解决方案1】:

    不同的答案,更好或更差的不同方面。以下是一些:

    import ParseTree;
    
    int getChildrenCount1(Tree parsed) {
       return (0 | it + 1 | _ <- parsed.args);
    }
    

    getChildrenCount1 迭代解析树节点的原始子节点。这包括空格和注释节点 (layout) 和关键字 (literals)。您可能想要过滤这些,或按除法补偿。

    另一方面,这似乎有点间接。我们也可以直接询问孩子列表的长度:

    import List;
    import ParseTree;
    
    int getChildrenCount2(Tree parsed) {
       return size(parsed.args) / 2 + 1; // here we divide by two assuming every other node is a layout node
    }
    

    还有元数据的方式。每个解析树节点都直接在那里对产生式进行说明性描述,可以查询和探索:

    import ParseTree;
    import List;
    
    // immediately match on the meta-structure of a parse node:
    int getChildrenCount3(appl(Production prod, list[Tree] args)) {
        return size(prod.symbols);
    }
    

    这个符号的长度应该和args的长度一样。

    // To filter for "meaningful" children in a declarative way:
    int getChildrenCount4(appl(prod(_, list[Symbol] symbols, _), list[Tree] args)) {
        return (0 | it + 1 | sort(_) <- symbols);
    }
    

    sort 过滤上下文无关的非终端,如 syntax 规则声明的那样。词法子代将匹配lex,布局和文字与layoutslit 匹配。

    没有所有的模式匹配:

    int getChildrenCount4(Tree tree) {
        return (0 | it + 1 | s <- tree.prod.symbols, isInteresting(s));
    }
    
    bool isInteresting(Symbol s) = s is sort || s is lex;
    

    【讨论】:

    • 酷,谢谢,这个parsed.args 正是我要找的。​​span>
    • 没问题;查看标准库中的ParseTree 模块,了解解析树格式的完整定义。相当有钱。如果您具体化语法类型,也会产生相同的格式:#Exp.definitions 包含原始语法中的所有规则,其格式与生成的分析树中使用的格式相同。
    • 这里可能不完全相关,但是对于一般Node的情况,还有一个arity函数返回孩子的数量。
    • 这里的问题是有一些你不想计算的孩子——那些代表布局的孩子(例如,空白)。这就是为什么我提到它可能与这种情况无关,但总的来说它会有所帮助。
    • @JurgenVinju 同意,我只是认为添加它可能很有用,因为最初的问题是关于查找节点类型的子节点的数量,只是用例是解析树。跨度>
    【解决方案2】:

    到目前为止,这似乎可行,但很糟糕:

    int getChildrenCount(Tree parsed) {
        int infinity = 1000;
        for (int i <- [0..infinity]) {
            try parsed[i];
            catch: return i;
        }
        return infinity;
    }
    
    void main() {
        Exp parsed = parse(#Exp, "132+(4+3)*48");
        println("the number of root children is: ");
        println(getChildrenCount(parsed));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-10
      • 1970-01-01
      • 1970-01-01
      • 2013-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多